Fix DAO/BAO namespaces and definitions
This commit is contained in:
parent
7cca29b458
commit
64d6b48813
10 changed files with 41 additions and 77 deletions
|
@ -1,679 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Civi\Twingle\Shop\BAO;
|
||||
|
||||
use Civi\Api4\PriceField;
|
||||
use Civi\Twingle\Shop\DAO\TwingleProduct as TwingleProductDAO;
|
||||
use Civi\Twingle\Shop\DAO\TwingleShop as TwingleShopDAO;
|
||||
use Civi\Twingle\Shop\Exceptions\ProductException;
|
||||
use Civi\Twingle\Shop\Exceptions\ShopException;
|
||||
use CRM_Core_Exception;
|
||||
use CRM_Core_Transaction;
|
||||
use CRM_Twingle_ExtensionUtil as E;
|
||||
use CRM_Utils_Type;
|
||||
use function Civi\Twingle\Shop\Utils\convert_int_to_bool;
|
||||
use function Civi\Twingle\Shop\Utils\convert_str_to_date;
|
||||
use function Civi\Twingle\Shop\Utils\convert_str_to_int;
|
||||
use function Civi\Twingle\Shop\Utils\convert_empty_string_to_null;
|
||||
use function Civi\Twingle\Shop\Utils\filter_attributes;
|
||||
use function Civi\Twingle\Shop\Utils\validate_data_types;
|
||||
|
||||
require_once E::path() . '/Civi/Twingle/Shop/Utils/TwingleShopUtils.php';
|
||||
|
||||
/**
|
||||
* TwingleProduct BAO class.
|
||||
* This class is used to implement the logic for the TwingleProduct entity.
|
||||
*/
|
||||
class TwingleProduct extends TwingleProductDAO {
|
||||
|
||||
/**
|
||||
* Name of this product.
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Is this product active?
|
||||
*/
|
||||
public $is_active;
|
||||
|
||||
/**
|
||||
* Price of this product.
|
||||
*/
|
||||
public $price;
|
||||
|
||||
/**
|
||||
* Sort order of this product.
|
||||
*/
|
||||
public $sort;
|
||||
|
||||
/**
|
||||
* Short description of this Product.
|
||||
*/
|
||||
public $text;
|
||||
|
||||
/**
|
||||
* Long description of this Product.
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* ID of the corresponding Twingle Shop.
|
||||
*/
|
||||
public $project_id;
|
||||
|
||||
/**
|
||||
* ID of the financial type of this product.
|
||||
*/
|
||||
public $financial_type_id;
|
||||
|
||||
/**
|
||||
* Timestamp of the last update in Twingle db.
|
||||
*/
|
||||
public $tw_updated_at;
|
||||
|
||||
/**
|
||||
* The values of this attributes can be 0.
|
||||
* (For filtering purposes)
|
||||
*/
|
||||
protected const CAN_BE_ZERO = [
|
||||
"price",
|
||||
"sort",
|
||||
];
|
||||
|
||||
/**
|
||||
* Attributes that need to be converted to int.
|
||||
*/
|
||||
protected const STR_TO_INT_CONVERSION = [
|
||||
"id",
|
||||
"twingle_shop_id",
|
||||
"financial_type_id",
|
||||
"price_field_id",
|
||||
"project_id",
|
||||
"external_id",
|
||||
"tw_updated_at",
|
||||
"tw_created_at",
|
||||
"price",
|
||||
"sort",
|
||||
];
|
||||
|
||||
/**
|
||||
* Attributes that need to be converted to boolean.
|
||||
*/
|
||||
protected const INT_TO_BOOL_CONVERSION = [
|
||||
"is_active",
|
||||
];
|
||||
|
||||
/**
|
||||
* String to date conversion.
|
||||
*/
|
||||
protected const STR_TO_DATE_CONVERSION = [
|
||||
"created_at",
|
||||
"updated_at",
|
||||
];
|
||||
|
||||
/**
|
||||
* Empty string to null conversion.
|
||||
*/
|
||||
protected const EMPTY_STRING_TO_NULL = [
|
||||
"price",
|
||||
];
|
||||
|
||||
/**
|
||||
* Allowed product attributes.
|
||||
* Attributes that we currently don't support are commented out.
|
||||
*/
|
||||
protected const ALLOWED_ATTRIBUTES = [
|
||||
"id" => CRM_Utils_Type::T_INT,
|
||||
"external_id" => CRM_Utils_Type::T_INT,
|
||||
"name" => CRM_Utils_Type::T_STRING,
|
||||
"is_active" => CRM_Utils_Type::T_BOOLEAN,
|
||||
"description" => CRM_Utils_Type::T_STRING,
|
||||
"price" => CRM_Utils_Type::T_INT,
|
||||
"created_at" => CRM_Utils_Type::T_INT,
|
||||
"tw_created_at" => CRM_Utils_Type::T_INT,
|
||||
"updated_at" => CRM_Utils_Type::T_INT,
|
||||
"tw_updated_at" => CRM_Utils_Type::T_INT,
|
||||
"is_orphaned" => CRM_Utils_Type::T_BOOLEAN,
|
||||
"is_outdated" => CRM_Utils_Type::T_BOOLEAN,
|
||||
"project_id" => CRM_Utils_Type::T_INT,
|
||||
"sort" => CRM_Utils_Type::T_INT,
|
||||
"financial_type_id" => CRM_Utils_Type::T_INT,
|
||||
"twingle_shop_id" => CRM_Utils_Type::T_INT,
|
||||
"price_field_id" => CRM_Utils_Type::T_INT,
|
||||
# "text" => \CRM_Utils_Type::T_STRING,
|
||||
# "images" => \CRM_Utils_Type::T_STRING,
|
||||
# "categories" = \CRM_Utils_Type::T_STRING,
|
||||
# "internal_id" => \CRM_Utils_Type::T_STRING,
|
||||
# "has_zero_price" => \CRM_Utils_Type::T_BOOLEAN,
|
||||
# "name_plural" => \CRM_Utils_Type::T_STRING,
|
||||
# "max_count" => \CRM_Utils_Type::T_INT,
|
||||
# "has_textinput" => \CRM_Utils_Type::T_BOOLEAN,
|
||||
# "count" => \CRM_Utils_Type::T_INT,
|
||||
];
|
||||
|
||||
/**
|
||||
* Change attribute names to match the database column names.
|
||||
*
|
||||
* @param array $values
|
||||
* Array with product data from Twingle API
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function renameTwingleAttrs(array $values) {
|
||||
$new_values = [];
|
||||
foreach ($values as $key => $value) {
|
||||
// replace 'id' with 'external_id'
|
||||
if ($key == 'id') {
|
||||
$key = 'external_id';
|
||||
}
|
||||
// replace 'updated_at' with 'tw_updated_at'
|
||||
if ($key == 'updated_at') {
|
||||
$key = 'tw_updated_at';
|
||||
}
|
||||
// replace 'created_at' with 'tw_created_at'
|
||||
if ($key == 'created_at') {
|
||||
$key = 'tw_created_at';
|
||||
}
|
||||
$new_values[$key] = $value;
|
||||
}
|
||||
return $new_values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load product data.
|
||||
*
|
||||
* @param array $product_data
|
||||
* Array with product data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ProductException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function load(array $product_data): void {
|
||||
// Filter for allowed attributes
|
||||
filter_attributes(
|
||||
$product_data,
|
||||
self::ALLOWED_ATTRIBUTES,
|
||||
self::CAN_BE_ZERO,
|
||||
);
|
||||
|
||||
// Does this product allow to enter a custom price?
|
||||
$custom_price = array_key_exists('price', $product_data) && $product_data['price'] === Null;
|
||||
if (!$custom_price && isset($product_data['price_field_id'])) {
|
||||
try {
|
||||
$price_field = civicrm_api3('PriceField', 'getsingle', [
|
||||
'id' => $product_data['price_field_id'],
|
||||
'return' => 'is_enter_qty',
|
||||
]);
|
||||
$custom_price = (bool) $price_field['is_enter_qty'];
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts("Could not find PriceField for Twingle Product ['id': %1, 'external_id': %2]: %3",
|
||||
[
|
||||
1 => $product_data['id'],
|
||||
2 => $product_data['external_id'],
|
||||
3 => $e->getMessage(),
|
||||
]),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
// Amend data from corresponding PriceFieldValue
|
||||
if (isset($product_data['price_field_id'])) {
|
||||
try {
|
||||
$price_field_value = civicrm_api3('PriceFieldValue', 'getsingle', [
|
||||
'price_field_id' => $product_data['price_field_id'],
|
||||
]);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts("Could not find PriceFieldValue for Twingle Product ['id': %1, 'external_id': %2]: %3",
|
||||
[
|
||||
1 => $product_data['id'],
|
||||
2 => $product_data['external_id'],
|
||||
3 => $e->getMessage(),
|
||||
]),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_VALUE_NOT_FOUND);
|
||||
}
|
||||
$product_data['name'] = $product_data['name'] ?? $price_field_value['label'];
|
||||
$product_data['price'] = $custom_price ? Null : $product_data['price'] ?? $price_field_value['amount'];
|
||||
$product_data['financial_type_id'] = $product_data['financial_type_id'] ?? $price_field_value['financial_type_id'];
|
||||
$product_data['is_active'] = $product_data['is_active'] ?? $price_field_value['is_active'];
|
||||
$product_data['sort'] = $product_data['sort'] ?? $price_field_value['weight'];
|
||||
$product_data['description'] = $product_data['description'] ?? $price_field_value['description'];
|
||||
}
|
||||
|
||||
// Change data types
|
||||
try {
|
||||
convert_str_to_int($product_data, self::STR_TO_INT_CONVERSION);
|
||||
convert_int_to_bool($product_data, self::INT_TO_BOOL_CONVERSION);
|
||||
convert_str_to_date($product_data, self::STR_TO_DATE_CONVERSION);
|
||||
convert_empty_string_to_null($product_data, self::EMPTY_STRING_TO_NULL);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
throw new ProductException($e->getMessage(), ProductException::ERROR_CODE_ATTRIBUTE_WRONG_DATA_TYPE);
|
||||
}
|
||||
|
||||
// Validate data types
|
||||
try {
|
||||
validate_data_types($product_data, self::ALLOWED_ATTRIBUTES);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
throw new ProductException($e->getMessage(), ProductException::ERROR_CODE_ATTRIBUTE_WRONG_DATA_TYPE);
|
||||
}
|
||||
|
||||
// Set attributes
|
||||
foreach ($product_data as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a price field to represents this product in CiviCRM.
|
||||
*
|
||||
* @param string $mode
|
||||
* 'create' or 'edit'
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function createPriceField() {
|
||||
// Define mode for PriceField
|
||||
$mode = $this->price_field_id ? 'edit' : 'create';
|
||||
$action = $mode == 'create' ? 'create' : 'update';
|
||||
|
||||
// Check if PriceSet for this Shop already exists
|
||||
try {
|
||||
$price_field = civicrm_api3('PriceField', 'get', [
|
||||
'name' => 'tw_product_' . $this->external_id,
|
||||
]);
|
||||
if ($price_field['count'] > 0 && $mode == 'create') {
|
||||
throw new ProductException(
|
||||
E::ts('PriceField for this Twingle Product already exists.'),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_ALREADY_EXISTS,
|
||||
);
|
||||
} elseif ($price_field['count'] == 0 && $mode == 'edit') {
|
||||
throw new ProductException(
|
||||
E::ts('PriceField for this Twingle Product does not exist and cannot be edited.'),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not check if PriceField for this Twingle Product already exists.'),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Try to find corresponding price set via TwingleShop
|
||||
try {
|
||||
$shop = civicrm_api3('TwingleShop', 'getsingle', [
|
||||
'id' => $this->twingle_shop_id,
|
||||
]);
|
||||
$this->price_set_id = (int) $shop['price_set_id'];
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not find PriceSet for this Twingle Product.'),
|
||||
ProductException::ERROR_CODE_PRICE_SET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Create PriceField
|
||||
$price_field_data = [
|
||||
'price_set_id' => $this->price_set_id,
|
||||
'name' => 'tw_product_' . $this->external_id,
|
||||
'label' => $this->name,
|
||||
'is_active' => $this->is_active,
|
||||
'weight' => $this->sort,
|
||||
'html_type' => 'Text',
|
||||
'is_required' => false,
|
||||
];
|
||||
|
||||
// If the product has no fixed price, allow the user to enter a custom price
|
||||
if ($this->price === Null) {
|
||||
$price_field_data['is_enter_qty'] = true;
|
||||
$price_field_data['is_display_amounts'] = false;
|
||||
}
|
||||
|
||||
// Add id if in edit mode
|
||||
if ($mode == 'edit') {
|
||||
$price_field_data['id'] = $this->price_field_id;
|
||||
}
|
||||
try {
|
||||
$price_field = civicrm_api4(
|
||||
'PriceField',
|
||||
$action,
|
||||
['values' => $price_field_data],
|
||||
)->first();
|
||||
$this->price_field_id = (int) $price_field['id'];
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not create PriceField for this Twingle Product: %1',
|
||||
[1 => $e->getMessage()]),
|
||||
ProductException::ERROR_CODE_COULD_NOT_CREATE_PRICE_FIELD);
|
||||
}
|
||||
|
||||
// Try to find existing PriceFieldValue if in edit mode
|
||||
$price_field_value = NULL;
|
||||
if ($mode == 'edit') {
|
||||
try {
|
||||
$price_field_value = civicrm_api3('PriceFieldValue', 'getsingle', [
|
||||
'price_field_id' => $this->price_field_id,
|
||||
]);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not find PriceFieldValue for this Twingle Product: %1',
|
||||
[1 => $e->getMessage()]),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_VALUE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
// Create PriceFieldValue
|
||||
$price_field_value_data = [
|
||||
'price_field_id' => $this->price_field_id,
|
||||
'financial_type_id' => $this->financial_type_id,
|
||||
'label' => $this->name,
|
||||
'amount' => $this->price === Null ? 1 : $this->price,
|
||||
'is_active' => $this->is_active,
|
||||
'description' => $this->description,
|
||||
];
|
||||
// Add id if in edit mode
|
||||
if ($mode == 'edit' && $price_field_value) {
|
||||
$price_field_value_data['id'] = $price_field_value['id'];
|
||||
}
|
||||
try {
|
||||
civicrm_api4(
|
||||
'PriceFieldValue',
|
||||
$action,
|
||||
['values' => $price_field_value_data],
|
||||
);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not create PriceFieldValue for this Twingle Product: %1',
|
||||
[1 => $e->getMessage()]),
|
||||
ProductException::ERROR_CODE_COULD_NOT_CREATE_PRICE_FIELD_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this TwingleProduct's attributes.
|
||||
*
|
||||
* @return array
|
||||
* @throws \CRM_Core_Exception
|
||||
*/
|
||||
public function getAttributes() {
|
||||
// Filter for allowed attributes
|
||||
return array_intersect_key(
|
||||
get_object_vars($this),
|
||||
$this::ALLOWED_ATTRIBUTES
|
||||
) // Add financial type id of this product if it exists
|
||||
+ ['financial_type_id' => $this->getFinancialTypeId()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find TwingleProduct by its external ID.
|
||||
*
|
||||
* @param int $external_id
|
||||
* External id of the product (by Twingle)
|
||||
*
|
||||
* @return TwingleProduct|null
|
||||
* TwingleProduct object or NULL if not found
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
* @throws \Civi\Core\Exception\DBQueryException
|
||||
*/
|
||||
public static function findByExternalId($external_id) {
|
||||
$dao = TwingleShopDAO::executeQuery("SELECT * FROM civicrm_twingle_product WHERE external_id = %1",
|
||||
[1 => [$external_id, 'String']]);
|
||||
if ($dao->fetch()) {
|
||||
$product = new self();
|
||||
$product->load($dao->toArray());
|
||||
return $product;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Twingle Product
|
||||
*
|
||||
* @param string $mode
|
||||
* 'create' or 'edit'
|
||||
* @return array
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function add($mode = 'create') {
|
||||
|
||||
$tx = new CRM_Core_Transaction();
|
||||
|
||||
// Define mode
|
||||
$mode = $this->id ? 'edit' : 'create';
|
||||
|
||||
// Try to lookup object in database
|
||||
try {
|
||||
$dao = TwingleShopDAO::executeQuery("SELECT * FROM civicrm_twingle_product WHERE external_id = %1",
|
||||
[1 => [$this->external_id, 'String']]);
|
||||
if ($dao->fetch()) {
|
||||
$this->copyValues(array_merge($dao->toArray(), $this->getAttributes()));
|
||||
}
|
||||
}
|
||||
catch (\Civi\Core\Exception\DBQueryException $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not find TwingleProduct in database: ' . $e->getMessage()),
|
||||
ShopException::ERROR_CODE_COULD_NOT_FIND_SHOP_IN_DB);
|
||||
}
|
||||
|
||||
// Register pre-hook
|
||||
$twingle_product_values = $this->getAttributes();
|
||||
try {
|
||||
\CRM_Utils_Hook::pre($mode, 'TwingleProduct', $this->id, $twingle_product_values);
|
||||
} catch (\Exception $e) {
|
||||
$tx->rollback();
|
||||
throw $e;
|
||||
}
|
||||
$this->load($twingle_product_values);
|
||||
|
||||
// Set latest tw_updated_at as new updated_at
|
||||
$this->updated_at = \CRM_Utils_Time::date('Y-m-d H:i:s', $this->tw_updated_at);
|
||||
|
||||
// Convert created_at to date string
|
||||
$this->created_at = \CRM_Utils_Time::date('Y-m-d H:i:s', $this->created_at);
|
||||
|
||||
// Save object to database
|
||||
try {
|
||||
$this->save();
|
||||
} catch (\Exception $e) {
|
||||
$tx->rollback();
|
||||
throw new ProductException(
|
||||
E::ts('Could not save TwingleProduct to database: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_COULD_NOT_CREATE_PRODUCT);
|
||||
}
|
||||
$result = self::findById($this->id);
|
||||
/* @var self $result */
|
||||
$this->load($result->getAttributes());
|
||||
|
||||
// Register post-hook
|
||||
$twingle_product_values = $this->getAttributes();
|
||||
try {
|
||||
\CRM_Utils_Hook::post($mode, 'TwingleProduct', $this->id, $twingle_product_values);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
$tx->rollback();
|
||||
throw $e;
|
||||
}
|
||||
$this->load($twingle_product_values);
|
||||
|
||||
return $result->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete TwingleProduct along with associated PriceField and PriceFieldValue.
|
||||
*
|
||||
* @override \Civi\Twingle\Shop\DAO\TwingleProduct::delete
|
||||
* @throws \CRM_Core_Exception
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
function delete($useWhere = FALSE) {
|
||||
// Register post-hook
|
||||
$twingle_product_values = $this->getAttributes();
|
||||
\CRM_Utils_Hook::pre('delete', 'TwingleProduct', $this->id, $twingle_product_values);
|
||||
$this->load($twingle_product_values);
|
||||
|
||||
// Delete TwingleProduct
|
||||
parent::delete($useWhere);
|
||||
|
||||
// Register post-hook
|
||||
\CRM_Utils_Hook::post('delete', 'TwingleProduct', $this->id, $instance);
|
||||
|
||||
// Free global arrays associated with this object
|
||||
$this->free();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complements the data with the data that was fetched from Twingle.
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function complementWithDataFromTwingle($product_from_twingle) {
|
||||
// Complement with data from Twingle
|
||||
$this->load([
|
||||
'project_id' => $product_from_twingle['project_id'],
|
||||
'tw_updated_at' => $product_from_twingle['updated_at'],
|
||||
'tw_created_at' => $product_from_twingle['created_at'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the product is outdated.
|
||||
*
|
||||
* @param $product_from_twingle
|
||||
*
|
||||
* @return void
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function checkOutdated($product_from_twingle) {
|
||||
// Mark outdated products which have a newer timestamp in Twingle
|
||||
if ($this->updated_at < intval($product_from_twingle['updated_at'])) {
|
||||
// Overwrite the product with the data from Twingle
|
||||
$this->load(self::renameTwingleAttrs($product_from_twingle));
|
||||
$this->is_outdated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two products
|
||||
*
|
||||
* @param TwingleProduct $product_to_compare_with
|
||||
* Product from database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals($product_to_compare_with) {
|
||||
return
|
||||
$this->name === $product_to_compare_with->name &&
|
||||
$this->description === $product_to_compare_with->description &&
|
||||
$this->text === $product_to_compare_with->text &&
|
||||
$this->price === $product_to_compare_with->price &&
|
||||
$this->external_id === $product_to_compare_with->external_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the financial type id of this product.
|
||||
*
|
||||
* @return int|null
|
||||
* @throws \CRM_Core_Exception
|
||||
*/
|
||||
public function getFinancialTypeId(): ?int {
|
||||
if (!empty($this->price_field_id)) {
|
||||
$price_set = \Civi\Api4\PriceField::get()
|
||||
->addSelect('financial_type_id')
|
||||
->addWhere('id', '=', $this->price_field_id)
|
||||
->execute()
|
||||
->first();
|
||||
return $price_set['financial_type_id'];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the price field value id of this product.
|
||||
*
|
||||
* @return int|null
|
||||
* @throws \CRM_Core_Exception
|
||||
*/
|
||||
public function getPriceFieldValueId() {
|
||||
if (!empty($this->price_field_id)) {
|
||||
$price_field_value = \Civi\Api4\PriceFieldValue::get()
|
||||
->addSelect('id')
|
||||
->addWhere('price_field_id', '=', $this->price_field_id)
|
||||
->execute()
|
||||
->first();
|
||||
return $price_field_value['id'];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete PriceField and PriceFieldValue of this TwingleProduct if they exist.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function deletePriceField(): void {
|
||||
// Before we can delete the PriceField we need to delete the associated
|
||||
// PriceFieldValue
|
||||
try {
|
||||
$result = civicrm_api3('PriceFieldValue', 'getsingle',
|
||||
['price_field_id' => $this->price_field_id]);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('An Error occurred while searching for the associated PriceFieldValue: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_VALUE_NOT_FOUND);
|
||||
}
|
||||
try {
|
||||
civicrm_api3('PriceFieldValue', 'delete', ['id' => $result['id']]);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not delete associated PriceFieldValue: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_COULD_NOT_DELETE_PRICE_FIELD_VALUE);
|
||||
}
|
||||
|
||||
// Try to delete PriceField
|
||||
// If no PriceField is found, we assume that it has already been deleted
|
||||
try {
|
||||
civicrm_api3('PriceField', 'delete',
|
||||
['id' => $this->price_field_id]);
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
// Check if PriceField yet exists
|
||||
try {
|
||||
$result = civicrm_api3('PriceField', 'get',
|
||||
['id' => $this->price_field_id]);
|
||||
// Throw exception if PriceField still exists
|
||||
if ($result['count'] > 0) {
|
||||
throw new ProductException(
|
||||
E::ts('PriceField for this Twingle Product still exists.'),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_STILL_EXISTS);
|
||||
}
|
||||
}
|
||||
catch (CRM_Core_Exception $e) {
|
||||
throw new ProductException(
|
||||
E::ts('An Error occurred while searching for the associated PriceField: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_PRICE_FIELD_NOT_FOUND);
|
||||
}
|
||||
throw new ProductException(
|
||||
E::ts('Could not delete associated PriceField: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_COULD_NOT_DELETE_PRICE_FIELD);
|
||||
}
|
||||
$this->price_field_id = NULL;
|
||||
}
|
||||
}
|
|
@ -1,478 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Civi\Twingle\Shop\BAO;
|
||||
|
||||
// phpcs:disable
|
||||
use CRM_Twingle_ExtensionUtil as E;
|
||||
use Civi\Twingle\Shop\DAO\TwingleShop as TwingleShopDAO;
|
||||
use Civi\Twingle\Shop\BAO\TwingleProduct as TwingleProductBAO;
|
||||
use Civi\Twingle\Shop\ApiCall;
|
||||
use Civi\Twingle\Shop\Exceptions\ShopException;
|
||||
use Civi\Twingle\Shop\Exceptions\ProductException;
|
||||
use Exception;
|
||||
use function Civi\Twingle\Shop\Utils\filter_attributes;
|
||||
use function Civi\Twingle\Shop\Utils\convert_str_to_int;
|
||||
use function Civi\Twingle\Shop\Utils\validate_data_types;
|
||||
// phpcs:enable
|
||||
|
||||
require_once E::path() . '/Civi/Twingle/Shop/Utils/TwingleShopUtils.php';
|
||||
|
||||
class TwingleShop extends TwingleShopDAO {
|
||||
|
||||
public const ALLOWED_ATTRIBUTES = [
|
||||
'id' => \CRM_Utils_Type::T_INT,
|
||||
'project_identifier' => \CRM_Utils_Type::T_STRING,
|
||||
'numerical_project_id' => \CRM_Utils_Type::T_INT,
|
||||
'name' => \CRM_Utils_Type::T_STRING,
|
||||
'price_set_id' => \CRM_Utils_Type::T_INT,
|
||||
'financial_type_id' => \CRM_Utils_Type::T_INT,
|
||||
];
|
||||
|
||||
public const STR_TO_INT_CONVERSION = [
|
||||
'id',
|
||||
'numerical_project_id',
|
||||
'price_set_id',
|
||||
'financial_type_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array $products
|
||||
* Array of Twingle Shop products (Cache)
|
||||
*/
|
||||
public $products;
|
||||
|
||||
/**
|
||||
* FK to Financial Type
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $financial_type_id;
|
||||
|
||||
/**
|
||||
* TwingleShop constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
// Get TwingleApiCall singleton
|
||||
$this->twingleApi = ApiCall::singleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Twingle Shop from database by its project identifier
|
||||
* (like 'tw620214349ac97')
|
||||
*
|
||||
* @param string $project_identifier
|
||||
* Twingle project identifier
|
||||
*
|
||||
* @return TwingleShop
|
||||
*
|
||||
* @throws ShopException
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ApiCallError
|
||||
* @throws \CRM_Core_Exception
|
||||
*/
|
||||
public static function findByProjectIdentifier(string $project_identifier) {
|
||||
$shop = new TwingleShop();
|
||||
$shop->get('project_identifier', $project_identifier);
|
||||
if (!$shop->id) {
|
||||
$shop->fetchDataFromTwingle($project_identifier);
|
||||
}
|
||||
else {
|
||||
$shop->price_set_id = civicrm_api3('PriceSet', 'getvalue',
|
||||
['return' => 'id', 'name' => $project_identifier]);
|
||||
}
|
||||
return $shop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Twingle Shop data
|
||||
*
|
||||
* @param array $shop_data
|
||||
* Array with shop data
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ShopException
|
||||
*/
|
||||
public function load(array $shop_data): void {
|
||||
// Filter for allowed attributes
|
||||
filter_attributes($shop_data, self::ALLOWED_ATTRIBUTES);
|
||||
|
||||
// Convert string to int
|
||||
try {
|
||||
convert_str_to_int($shop_data, self::STR_TO_INT_CONVERSION);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new ShopException($e->getMessage(), ShopException::ERROR_CODE_ATTRIBUTE_WRONG_DATA_TYPE);
|
||||
}
|
||||
|
||||
// Validate data types
|
||||
try {
|
||||
validate_data_types($shop_data, self::ALLOWED_ATTRIBUTES);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new ShopException($e->getMessage(), ShopException::ERROR_CODE_ATTRIBUTE_WRONG_DATA_TYPE);
|
||||
}
|
||||
|
||||
// Set attributes
|
||||
foreach ($shop_data as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getAttributes(): array {
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'project_identifier' => $this->project_identifier,
|
||||
'numerical_project_id' => $this->numerical_project_id,
|
||||
'name' => $this->name,
|
||||
'price_set_id' => $this->price_set_id,
|
||||
'financial_type_id' => $this->financial_type_id,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Twingle Shop
|
||||
*
|
||||
* @param string $mode
|
||||
* 'create' or 'edit'
|
||||
* @return array
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ShopException
|
||||
*/
|
||||
public function add($mode = 'create') {
|
||||
|
||||
// Try to lookup object in database
|
||||
try {
|
||||
$dao = TwingleShopDAO::executeQuery("SELECT * FROM civicrm_twingle_shop WHERE project_identifier = %1",
|
||||
[1 => [$this->project_identifier, 'String']]);
|
||||
if ($dao->fetch()) {
|
||||
$this->load($dao->toArray());
|
||||
}
|
||||
} catch (\Civi\Core\Exception\DBQueryException $e) {
|
||||
throw new ShopException(
|
||||
E::ts('Could not find TwingleShop in database: ' . $e->getMessage()),
|
||||
ShopException::ERROR_CODE_COULD_NOT_FIND_SHOP_IN_DB);
|
||||
}
|
||||
|
||||
// Register pre-hook
|
||||
$twingle_shop_values = $this->getAttributes();
|
||||
\CRM_Utils_Hook::pre($mode, 'TwingleShop', $this->id, $twingle_shop_values);
|
||||
$this->load($twingle_shop_values);
|
||||
|
||||
// Save object to database
|
||||
$result = $this->save();
|
||||
|
||||
// Register post-hook
|
||||
\CRM_Utils_Hook::post($mode, 'TwingleShop', $this->id, $instance);
|
||||
|
||||
return $result->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete object by deleting the associated PriceSet and letting the foreign
|
||||
* key constraint do the rest.
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ShopException*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
function deleteByConstraint() {
|
||||
// Register post-hook
|
||||
$twingle_shop_values = $this->getAttributes();
|
||||
\CRM_Utils_Hook::pre('delete', 'TwingleShop', $this->id, $twingle_shop_values);
|
||||
$this->load($twingle_shop_values);
|
||||
|
||||
// Delete associated products
|
||||
$this->deleteProducts();
|
||||
|
||||
// Try to get single PriceSet
|
||||
try {
|
||||
civicrm_api3('PriceSet', 'getsingle',
|
||||
['id' => $this->price_set_id]);
|
||||
}
|
||||
catch (\CRM_Core_Exception $e) {
|
||||
if ($e->getMessage() != 'Expected one PriceSet but found 0') {
|
||||
throw new ShopException(
|
||||
E::ts('Could not find associated PriceSet: ' . $e->getMessage()),
|
||||
ShopException::ERROR_CODE_PRICE_SET_NOT_FOUND);
|
||||
}
|
||||
else {
|
||||
// If no PriceSet is found, we can simply delete the TwingleShop
|
||||
return $this->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting the associated PriceSet will also lead to the deletion of this
|
||||
// TwingleShop because of the foreign key constraint and cascading.
|
||||
try {
|
||||
$result = civicrm_api3('PriceSet', 'delete',
|
||||
['id' => $this->price_set_id]);
|
||||
} catch (\CRM_Core_Exception $e) {
|
||||
throw new ShopException(
|
||||
E::ts('Could not delete associated PriceSet: ' . $e->getMessage()),
|
||||
ShopException::ERROR_CODE_COULD_NOT_DELETE_PRICE_SET);
|
||||
}
|
||||
|
||||
// Register post-hook
|
||||
\CRM_Utils_Hook::post('delete', 'TwingleShop', $this->id, $instance);
|
||||
|
||||
// Free global arrays associated with this object
|
||||
$this->free();
|
||||
|
||||
return $result['is_error'] == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Twingle Shop products from Twingle
|
||||
*
|
||||
* @return array
|
||||
* array of CRM_Twingle_Shop_BAO_Product
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ApiCallError;
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException;
|
||||
* @throws \Civi\Core\Exception\DBQueryException
|
||||
* @throws \CRM_Core_Exception
|
||||
*/
|
||||
public function fetchProducts(): array {
|
||||
// Establish connection, if not already connected
|
||||
if (!$this->twingleApi->isConnected) {
|
||||
$this->twingleApi->connect();
|
||||
}
|
||||
|
||||
// Fetch products from Twingle API
|
||||
$products_from_twingle = $this->twingleApi->get(
|
||||
'project',
|
||||
$this->numerical_project_id,
|
||||
'products',
|
||||
);
|
||||
|
||||
// Fetch products from database
|
||||
if ($this->id) {
|
||||
$products_from_db = $this->getProducts();
|
||||
|
||||
$products_from_twingle = array_reduce($products_from_twingle, function($carry, $product) {
|
||||
$carry[$product['id']] = $product;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
foreach ($products_from_db as $product) {
|
||||
/* @var TwingleProductBAO $product */
|
||||
|
||||
// Find orphaned products which are in the database but not in Twingle
|
||||
$found = array_key_exists($product->external_id, $products_from_twingle);
|
||||
if (!$found) {
|
||||
$product->is_orphaned = TRUE;
|
||||
}
|
||||
else {
|
||||
// Complement with data from Twingle
|
||||
$product->complementWithDataFromTwingle($products_from_twingle[$product->external_id]);
|
||||
// Mark outdated products which have a newer version in Twingle
|
||||
$product->checkOutdated($products_from_twingle[$product->external_id]);
|
||||
}
|
||||
$this->products[] = $product;
|
||||
}
|
||||
}
|
||||
|
||||
// Create array with external_id as key
|
||||
$products = array_reduce($this->products ?? [], function($carry, $product) {
|
||||
$carry[$product->external_id] = $product;
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
// Add new products from Twingle
|
||||
foreach ($products_from_twingle as $product_from_twingle) {
|
||||
$found = array_key_exists($product_from_twingle['id'], $products);
|
||||
if (!$found) {
|
||||
$product = new TwingleProduct();
|
||||
$product->load(TwingleProduct::renameTwingleAttrs($product_from_twingle));
|
||||
$product->twingle_shop_id = $this->id;
|
||||
$this->products[] = $product;
|
||||
}
|
||||
}
|
||||
return $this->products;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated products.
|
||||
*
|
||||
* @return array[Civi\Twingle\Shop\BAO\TwingleProduct]
|
||||
* @throws \Civi\Core\Exception\DBQueryException
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function getProducts() {
|
||||
$products = [];
|
||||
|
||||
$result = TwingleProductBAO::executeQuery(
|
||||
"SELECT * FROM civicrm_twingle_product WHERE twingle_shop_id = %1",
|
||||
[1 => [$this->id, 'Integer']]
|
||||
);
|
||||
|
||||
while ($result->fetch()) {
|
||||
$product = new TwingleProductBAO();
|
||||
$product->load($result->toArray());
|
||||
$products[] = $product;
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Twingle Shop as a price set in CiviCRM.
|
||||
*
|
||||
* @param string $mode
|
||||
* 'create' or 'edit'
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ShopException
|
||||
*/
|
||||
public function createPriceSet($mode = 'create') {
|
||||
|
||||
// Define mode
|
||||
$mode = $this->price_set_id ? 'edit' : 'create';
|
||||
|
||||
// Check if PriceSet for this Shop already exists
|
||||
try {
|
||||
$price_set = civicrm_api3('PriceSet', 'get', [
|
||||
'name' => $this->project_identifier,
|
||||
]);
|
||||
if ($price_set['count'] > 0 && $mode == 'create') {
|
||||
throw new ShopException(
|
||||
E::ts('PriceSet for this Twingle Shop already exists.'),
|
||||
ShopException::ERROR_CODE_PRICE_SET_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
elseif ($price_set['count'] == 0 && $mode == 'edit') {
|
||||
throw new ShopException(
|
||||
E::ts('PriceSet for this Twingle Shop does not exist and cannot be edited.'),
|
||||
ShopException::ERROR_CODE_PRICE_SET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
} catch (\CRM_Core_Exception $e) {
|
||||
throw new ShopException(
|
||||
E::ts('Could not check if PriceSet for this TwingleShop already exists.'),
|
||||
ShopException::ERROR_CODE_PRICE_SET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
// Create PriceSet
|
||||
$price_set_data = [
|
||||
'name' => $this->project_identifier,
|
||||
'title' => "$this->name ($this->project_identifier)",
|
||||
'is_active' => 1,
|
||||
'extends' => 2,
|
||||
'financial_type_id' => $this->financial_type_id,
|
||||
];
|
||||
// Set id if in edit mode
|
||||
if ($mode == 'edit') {
|
||||
$price_set_data['id'] = $this->price_set_id;
|
||||
}
|
||||
try {
|
||||
$price_set = civicrm_api4('PriceSet', 'create',
|
||||
['values' => $price_set_data])->first();
|
||||
$this->price_set_id = (int) $price_set['id'];
|
||||
} catch (\CRM_Core_Exception $e) {
|
||||
throw new ShopException(
|
||||
E::ts('Could not create PriceSet for this TwingleShop.'),
|
||||
ShopException::ERROR_CODE_COULD_NOT_CREATE_PRICE_SET,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the numerical project ID and the name of this shop from Twingle.
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ShopException
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ApiCallError
|
||||
*/
|
||||
private function fetchDataFromTwingle() {
|
||||
|
||||
// Establish connection, if not already connected
|
||||
if (!$this->twingleApi->isConnected) {
|
||||
$this->twingleApi->connect();
|
||||
}
|
||||
|
||||
// Get shops from Twingle if not cached
|
||||
$shops = \Civi::cache('long')->get('twingle_shops');
|
||||
if (empty($shops)) {
|
||||
$this::fetchShops($this->twingleApi);
|
||||
$shops = \Civi::cache('long')->get('twingle_shops');
|
||||
}
|
||||
|
||||
// Set Shop ID and name
|
||||
foreach ($shops as $shop) {
|
||||
if (isset($shop['identifier']) && $shop['identifier'] == $this->project_identifier) {
|
||||
$this->numerical_project_id = $shop['id'];
|
||||
$this->name = $shop['name'];
|
||||
}
|
||||
}
|
||||
|
||||
// Throw an Exception if this Twingle Project is not of type 'shop'
|
||||
if (!isset($this->numerical_project_id)) {
|
||||
throw new ShopException(
|
||||
E::ts('This Twingle Project is not a shop.'),
|
||||
ShopException::ERROR_CODE_NOT_A_SHOP,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all Twingle projects of the type 'shop'.
|
||||
*
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ShopException
|
||||
*/
|
||||
static private function fetchShops(ApiCall $api): void {
|
||||
$organisationId = $api->organisationId;
|
||||
try {
|
||||
$projects = $api->get(
|
||||
'project',
|
||||
NULL,
|
||||
'by-organisation',
|
||||
$organisationId,
|
||||
);
|
||||
$shops = array_filter(
|
||||
$projects,
|
||||
function($project) {
|
||||
return isset($project['type']) && $project['type'] == 'shop';
|
||||
}
|
||||
);
|
||||
\Civi::cache('long')->set('twingle_shops', $shops);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new ShopException(
|
||||
E::ts('Could not retrieve Twingle projects from API.
|
||||
Please check your API credentials.'),
|
||||
ShopException::ERROR_CODE_COULD_NOT_GET_PROJECTS,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all associated products.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Civi\Twingle\Shop\Exceptions\ProductException
|
||||
*/
|
||||
public function deleteProducts() {
|
||||
try {
|
||||
$products = $this->getProducts();
|
||||
} catch (\Civi\Core\Exception\DBQueryException $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not retrieve associated products: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_COULD_NOT_GET_PRODUCTS
|
||||
);
|
||||
}
|
||||
try {
|
||||
foreach ($products as $product) {
|
||||
$product->delete();
|
||||
}
|
||||
}
|
||||
catch (ProductException $e) {
|
||||
throw new ProductException(
|
||||
E::ts('Could not delete associated products: ' . $e->getMessage()),
|
||||
ProductException::ERROR_CODE_COULD_NOT_DELETE_PRICE_SET
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Civi\Twingle\Shop\DAO;
|
||||
|
||||
/**
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC https://civicrm.org/licensing
|
||||
*
|
||||
* Generated from de.systopia.twingle/xml/schema/CRM/Twingle/TwingleProduct.xml
|
||||
* DO NOT EDIT. Generated by CRM_Core_CodeGen
|
||||
* (GenCodeChecksum:b8ced533ba6f4249619ffe5353965a4f)
|
||||
*/
|
||||
use CRM_Twingle_ExtensionUtil as E;
|
||||
|
||||
/**
|
||||
* Database access object for the TwingleProduct entity.
|
||||
*/
|
||||
class TwingleProduct extends \CRM_Core_DAO {
|
||||
const EXT = E::LONG_NAME;
|
||||
const TABLE_ADDED = '';
|
||||
|
||||
/**
|
||||
* Static instance to hold the table name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $_tableName = 'civicrm_twingle_product';
|
||||
|
||||
/**
|
||||
* Should CiviCRM log any modifications to this table in the civicrm_log table.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $_log = FALSE;
|
||||
|
||||
/**
|
||||
* Unique TwingleProduct ID
|
||||
*
|
||||
* @var int|string|null
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The ID of this product in the Twingle database
|
||||
*
|
||||
* @var int|string
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $external_id;
|
||||
|
||||
/**
|
||||
* FK to Price Field
|
||||
*
|
||||
* @var int|string
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $price_field_id;
|
||||
|
||||
/**
|
||||
* FK to Twingle Shop
|
||||
*
|
||||
* @var int|string|null
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $twingle_shop_id;
|
||||
|
||||
/**
|
||||
* Timestamp of when the product was created in the database
|
||||
*
|
||||
* @var string
|
||||
* (SQL type: datetime)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $created_at;
|
||||
|
||||
/**
|
||||
* Timestamp of when the product was last updated in the database
|
||||
*
|
||||
* @var string
|
||||
* (SQL type: datetime)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $updated_at;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->__table = 'civicrm_twingle_product';
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localized title of this entity.
|
||||
*
|
||||
* @param bool $plural
|
||||
* Whether to return the plural version of the title.
|
||||
*/
|
||||
public static function getEntityTitle($plural = FALSE) {
|
||||
return $plural ? E::ts('Twingle Products') : E::ts('Twingle Product');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns foreign keys and entity references.
|
||||
*
|
||||
* @return array
|
||||
* [CRM_Core_Reference_Interface]
|
||||
*/
|
||||
public static function getReferenceColumns() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['links'])) {
|
||||
\Civi::$statics[__CLASS__]['links'] = static::createReferenceColumns(__CLASS__);
|
||||
\Civi::$statics[__CLASS__]['links'][] = new \CRM_Core_Reference_Basic(self::getTableName(), 'price_field_id', 'civicrm_contact', 'id');
|
||||
\Civi::$statics[__CLASS__]['links'][] = new \CRM_Core_Reference_Basic(self::getTableName(), 'twingle_shop_id', 'civicrm_twingle_shop', 'id');
|
||||
\CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', \Civi::$statics[__CLASS__]['links']);
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['links'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the column names of this table
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &fields() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['fields'])) {
|
||||
\Civi::$statics[__CLASS__]['fields'] = [
|
||||
'id' => [
|
||||
'name' => 'id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('ID'),
|
||||
'description' => E::ts('Unique TwingleProduct ID'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.id',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Number',
|
||||
],
|
||||
'readonly' => TRUE,
|
||||
'add' => NULL,
|
||||
],
|
||||
'external_id' => [
|
||||
'name' => 'external_id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('External ID'),
|
||||
'description' => E::ts('The ID of this product in the Twingle database'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.external_id',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Number',
|
||||
],
|
||||
'add' => NULL,
|
||||
],
|
||||
'price_field_id' => [
|
||||
'name' => 'price_field_id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('Price Field ID'),
|
||||
'description' => E::ts('FK to Price Field'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.price_field_id',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'FKClassName' => 'CRM_Contact_DAO_Contact',
|
||||
'add' => NULL,
|
||||
],
|
||||
'twingle_shop_id' => [
|
||||
'name' => 'twingle_shop_id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('Twingle Shop ID'),
|
||||
'description' => E::ts('FK to Twingle Shop'),
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.twingle_shop_id',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'FKClassName' => 'Civi\Twingle\Shop\DAO\TwingleShop',
|
||||
'add' => NULL,
|
||||
],
|
||||
'created_at' => [
|
||||
'name' => 'created_at',
|
||||
'type' => \CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME,
|
||||
'title' => E::ts('Created At'),
|
||||
'description' => E::ts('Timestamp of when the product was created in the database'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.created_at',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'add' => NULL,
|
||||
],
|
||||
'updated_at' => [
|
||||
'name' => 'updated_at',
|
||||
'type' => \CRM_Utils_Type::T_DATE + \CRM_Utils_Type::T_TIME,
|
||||
'title' => E::ts('Updated At'),
|
||||
'description' => E::ts('Timestamp of when the product was last updated in the database'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_product.updated_at',
|
||||
'table_name' => 'civicrm_twingle_product',
|
||||
'entity' => 'TwingleProduct',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleProduct',
|
||||
'localizable' => 0,
|
||||
'add' => NULL,
|
||||
],
|
||||
];
|
||||
\CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', \Civi::$statics[__CLASS__]['fields']);
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['fields'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mapping from field-name to the corresponding key (as used in fields()).
|
||||
*
|
||||
* @return array
|
||||
* Array(string $name => string $uniqueName).
|
||||
*/
|
||||
public static function &fieldKeys() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['fieldKeys'])) {
|
||||
\Civi::$statics[__CLASS__]['fieldKeys'] = array_flip(\CRM_Utils_Array::collect('name', self::fields()));
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['fieldKeys'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of this table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName() {
|
||||
return self::$_tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this table needs to be logged
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getLog() {
|
||||
return self::$_log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of fields that can be imported
|
||||
*
|
||||
* @param bool $prefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &import($prefix = FALSE) {
|
||||
$r = \CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'twingle_product', $prefix, []);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of fields that can be exported
|
||||
*
|
||||
* @param bool $prefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &export($prefix = FALSE) {
|
||||
$r = \CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'twingle_product', $prefix, []);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of indices
|
||||
*
|
||||
* @param bool $localize
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function indices($localize = TRUE) {
|
||||
$indices = [];
|
||||
return ($localize && !empty($indices)) ? \CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,307 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Civi\Twingle\Shop\DAO;
|
||||
|
||||
/**
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC https://civicrm.org/licensing
|
||||
*
|
||||
* Generated from de.systopia.twingle/xml/schema/CRM/Twingle/TwingleShop.xml
|
||||
* DO NOT EDIT. Generated by CRM_Core_CodeGen
|
||||
* (GenCodeChecksum:95a46935c30b3da52e4df2bec871b962)
|
||||
*/
|
||||
use CRM_Twingle_ExtensionUtil as E;
|
||||
|
||||
/**
|
||||
* Database access object for the TwingleShop entity.
|
||||
*/
|
||||
class TwingleShop extends \CRM_Core_DAO {
|
||||
const EXT = E::LONG_NAME;
|
||||
const TABLE_ADDED = '';
|
||||
|
||||
/**
|
||||
* Static instance to hold the table name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $_tableName = 'civicrm_twingle_shop';
|
||||
|
||||
/**
|
||||
* Should CiviCRM log any modifications to this table in the civicrm_log table.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $_log = FALSE;
|
||||
|
||||
/**
|
||||
* Unique TwingleShop ID
|
||||
*
|
||||
* @var int|string|null
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* Twingle Project Identifier
|
||||
*
|
||||
* @var string
|
||||
* (SQL type: varchar(32))
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $project_identifier;
|
||||
|
||||
/**
|
||||
* Numerical Twingle Project Identifier
|
||||
*
|
||||
* @var int|string
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $numerical_project_id;
|
||||
|
||||
/**
|
||||
* FK to Price Set
|
||||
*
|
||||
* @var int|string|null
|
||||
* (SQL type: int unsigned)
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $price_set_id;
|
||||
|
||||
/**
|
||||
* name of the shop
|
||||
*
|
||||
* @var string
|
||||
* (SQL type: varchar(64))
|
||||
* Note that values will be retrieved from the database as a string.
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->__table = 'civicrm_twingle_shop';
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns localized title of this entity.
|
||||
*
|
||||
* @param bool $plural
|
||||
* Whether to return the plural version of the title.
|
||||
*/
|
||||
public static function getEntityTitle($plural = FALSE) {
|
||||
return $plural ? E::ts('Twingle Shops') : E::ts('Twingle Shop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns foreign keys and entity references.
|
||||
*
|
||||
* @return array
|
||||
* [CRM_Core_Reference_Interface]
|
||||
*/
|
||||
public static function getReferenceColumns() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['links'])) {
|
||||
\Civi::$statics[__CLASS__]['links'] = static::createReferenceColumns(__CLASS__);
|
||||
\Civi::$statics[__CLASS__]['links'][] = new \CRM_Core_Reference_Basic(self::getTableName(), 'price_set_id', 'civicrm_price_set', 'id');
|
||||
\CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', \Civi::$statics[__CLASS__]['links']);
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['links'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the column names of this table
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &fields() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['fields'])) {
|
||||
\Civi::$statics[__CLASS__]['fields'] = [
|
||||
'id' => [
|
||||
'name' => 'id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('ID'),
|
||||
'description' => E::ts('Unique TwingleShop ID'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_shop.id',
|
||||
'table_name' => 'civicrm_twingle_shop',
|
||||
'entity' => 'TwingleShop',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleShop',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Number',
|
||||
],
|
||||
'readonly' => TRUE,
|
||||
'add' => NULL,
|
||||
],
|
||||
'project_identifier' => [
|
||||
'name' => 'project_identifier',
|
||||
'type' => \CRM_Utils_Type::T_STRING,
|
||||
'title' => E::ts('Project Identifier'),
|
||||
'description' => E::ts('Twingle Project Identifier'),
|
||||
'required' => TRUE,
|
||||
'maxlength' => 32,
|
||||
'size' => \CRM_Utils_Type::MEDIUM,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_shop.project_identifier',
|
||||
'table_name' => 'civicrm_twingle_shop',
|
||||
'entity' => 'TwingleShop',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleShop',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Text',
|
||||
],
|
||||
'add' => NULL,
|
||||
],
|
||||
'numerical_project_id' => [
|
||||
'name' => 'numerical_project_id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('Numerical Project ID'),
|
||||
'description' => E::ts('Numerical Twingle Project Identifier'),
|
||||
'required' => TRUE,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_shop.numerical_project_id',
|
||||
'table_name' => 'civicrm_twingle_shop',
|
||||
'entity' => 'TwingleShop',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleShop',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Number',
|
||||
],
|
||||
'add' => NULL,
|
||||
],
|
||||
'price_set_id' => [
|
||||
'name' => 'price_set_id',
|
||||
'type' => \CRM_Utils_Type::T_INT,
|
||||
'title' => E::ts('Price Set ID'),
|
||||
'description' => E::ts('FK to Price Set'),
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_shop.price_set_id',
|
||||
'table_name' => 'civicrm_twingle_shop',
|
||||
'entity' => 'TwingleShop',
|
||||
'bao' => 'Civi\Twingle\Shop\DAO\TwingleShop',
|
||||
'localizable' => 0,
|
||||
'FKClassName' => 'CRM_Price_DAO_PriceSet',
|
||||
'add' => NULL,
|
||||
],
|
||||
'name' => [
|
||||
'name' => 'name',
|
||||
'type' => \CRM_Utils_Type::T_STRING,
|
||||
'title' => E::ts('Name'),
|
||||
'description' => E::ts('name of the shop'),
|
||||
'required' => TRUE,
|
||||
'maxlength' => 64,
|
||||
'size' => \CRM_Utils_Type::BIG,
|
||||
'usage' => [
|
||||
'import' => FALSE,
|
||||
'export' => FALSE,
|
||||
'duplicate_matching' => FALSE,
|
||||
'token' => FALSE,
|
||||
],
|
||||
'where' => 'civicrm_twingle_shop.name',
|
||||
'table_name' => 'civicrm_twingle_shop',
|
||||
'entity' => 'TwingleShop',
|
||||
'bao' => 'CRM_Twingle_Shop_DAO_TwingleShop',
|
||||
'localizable' => 0,
|
||||
'html' => [
|
||||
'type' => 'Text',
|
||||
],
|
||||
'add' => NULL,
|
||||
],
|
||||
];
|
||||
\CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', \Civi::$statics[__CLASS__]['fields']);
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['fields'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mapping from field-name to the corresponding key (as used in fields()).
|
||||
*
|
||||
* @return array
|
||||
* Array(string $name => string $uniqueName).
|
||||
*/
|
||||
public static function &fieldKeys() {
|
||||
if (!isset(\Civi::$statics[__CLASS__]['fieldKeys'])) {
|
||||
\Civi::$statics[__CLASS__]['fieldKeys'] = array_flip(\CRM_Utils_Array::collect('name', self::fields()));
|
||||
}
|
||||
return \Civi::$statics[__CLASS__]['fieldKeys'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of this table
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTableName() {
|
||||
return self::$_tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this table needs to be logged
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getLog() {
|
||||
return self::$_log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of fields that can be imported
|
||||
*
|
||||
* @param bool $prefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &import($prefix = FALSE) {
|
||||
$r = \CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'twingle_shop', $prefix, []);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of fields that can be exported
|
||||
*
|
||||
* @param bool $prefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function &export($prefix = FALSE) {
|
||||
$r = \CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'twingle_shop', $prefix, []);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of indices
|
||||
*
|
||||
* @param bool $localize
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function indices($localize = TRUE) {
|
||||
$indices = [];
|
||||
return ($localize && !empty($indices)) ? \CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue