nystudio107 /
craft-instantanalytics
| 1 | <?php |
||||
| 2 | /** |
||||
| 3 | * Instant Analytics plugin for Craft CMS |
||||
| 4 | * |
||||
| 5 | * Instant Analytics brings full Google Analytics support to your Twig templates |
||||
| 6 | * |
||||
| 7 | * @link https://nystudio107.com |
||||
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||||
| 8 | * @copyright Copyright (c) 2017 nystudio107 |
||||
|
0 ignored issues
–
show
|
|||||
| 9 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 10 | |||||
| 11 | namespace nystudio107\instantanalytics\services; |
||||
| 12 | |||||
| 13 | use Craft; |
||||
| 14 | use craft\base\Component; |
||||
| 15 | use craft\commerce\base\Purchasable; |
||||
|
0 ignored issues
–
show
The type
craft\commerce\base\Purchasable was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 16 | use craft\commerce\elements\Order; |
||||
|
0 ignored issues
–
show
The type
craft\commerce\elements\Order was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 17 | use craft\commerce\elements\Product; |
||||
|
0 ignored issues
–
show
The type
craft\commerce\elements\Product was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 18 | use craft\commerce\elements\Variant; |
||||
|
0 ignored issues
–
show
The type
craft\commerce\elements\Variant was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 19 | use craft\commerce\models\LineItem; |
||||
|
0 ignored issues
–
show
The type
craft\commerce\models\LineItem was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths Loading history...
|
|||||
| 20 | use craft\elements\db\CategoryQuery; |
||||
| 21 | use craft\elements\db\MatrixBlockQuery; |
||||
| 22 | use craft\elements\db\TagQuery; |
||||
| 23 | use nystudio107\instantanalytics\helpers\IAnalytics; |
||||
| 24 | use nystudio107\instantanalytics\InstantAnalytics; |
||||
| 25 | |||||
| 26 | /** |
||||
| 27 | * Commerce Service |
||||
| 28 | * |
||||
| 29 | * @author nystudio107 |
||||
|
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
|
|||||
| 30 | * @package InstantAnalytics |
||||
|
0 ignored issues
–
show
|
|||||
| 31 | * @since 1.0.0 |
||||
|
0 ignored issues
–
show
|
|||||
| 32 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 33 | class Commerce extends Component |
||||
| 34 | { |
||||
| 35 | // Public Methods |
||||
| 36 | // ========================================================================= |
||||
| 37 | |||||
| 38 | /** |
||||
| 39 | * Send analytics information for the completed order |
||||
| 40 | * |
||||
| 41 | * @param Order $order the Product or Variant |
||||
| 42 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 43 | public function orderComplete($order = null) |
||||
| 44 | { |
||||
| 45 | if ($order) { |
||||
| 46 | $analytics = InstantAnalytics::$plugin->ia->eventAnalytics( |
||||
| 47 | 'Commerce', |
||||
| 48 | 'Purchase', |
||||
| 49 | $order->reference, |
||||
| 50 | $order->totalPrice |
||||
| 51 | ); |
||||
| 52 | |||||
| 53 | if ($analytics) { |
||||
| 54 | $this->addCommerceOrderToAnalytics($analytics, $order); |
||||
| 55 | // Don't forget to set the product action, in this case to PURCHASE |
||||
| 56 | $analytics->setProductActionToPurchase(); |
||||
| 57 | $analytics->sendEvent(); |
||||
| 58 | |||||
| 59 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 60 | 'instant-analytics', |
||||
| 61 | 'orderComplete for `Commerce` - `Purchase` - `{reference}` - `{price}`', |
||||
| 62 | ['reference' => $order->reference, 'price' => $order->totalPrice] |
||||
| 63 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 64 | } |
||||
| 65 | } |
||||
| 66 | } |
||||
| 67 | |||||
| 68 | /** |
||||
| 69 | * Send analytics information for the item added to the cart |
||||
| 70 | * |
||||
| 71 | * @param Order $order the Product or Variant |
||||
|
0 ignored issues
–
show
|
|||||
| 72 | * @param LineItem $lineItem the line item that was added |
||||
| 73 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 74 | public function addToCart( |
||||
| 75 | /** @noinspection PhpUnusedParameterInspection */ |
||||
|
0 ignored issues
–
show
|
|||||
| 76 | $order = null, $lineItem = null |
||||
| 77 | ) |
||||
| 78 | { |
||||
|
0 ignored issues
–
show
|
|||||
| 79 | if ($lineItem) { |
||||
| 80 | $title = $lineItem->purchasable->title ?? $lineItem->description; |
||||
| 81 | $quantity = $lineItem->qty; |
||||
| 82 | $analytics = InstantAnalytics::$plugin->ia->eventAnalytics('Commerce', 'Add to Cart', $title, $quantity); |
||||
| 83 | |||||
| 84 | if ($analytics) { |
||||
| 85 | $title = $this->addProductDataFromLineItem($analytics, $lineItem); |
||||
| 86 | $analytics->setEventLabel($title); |
||||
| 87 | // Don't forget to set the product action, in this case to ADD |
||||
| 88 | $analytics->setProductActionToAdd(); |
||||
| 89 | $analytics->sendEvent(); |
||||
| 90 | |||||
| 91 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 92 | 'instant-analytics', |
||||
| 93 | 'addToCart for `Commerce` - `Add to Cart` - `{title}` - `{quantity}`', |
||||
| 94 | ['title' => $title, 'quantity' => $quantity] |
||||
| 95 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 96 | } |
||||
| 97 | } |
||||
| 98 | } |
||||
| 99 | |||||
| 100 | /** |
||||
| 101 | * Send analytics information for the item removed from the cart |
||||
| 102 | * |
||||
| 103 | * @param Order|null $order |
||||
|
0 ignored issues
–
show
|
|||||
| 104 | * @param LineItem|null $lineItem |
||||
|
0 ignored issues
–
show
|
|||||
| 105 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 106 | public function removeFromCart( |
||||
| 107 | /** @noinspection PhpUnusedParameterInspection */ |
||||
|
0 ignored issues
–
show
|
|||||
| 108 | $order = null, $lineItem = null |
||||
| 109 | ) |
||||
| 110 | { |
||||
|
0 ignored issues
–
show
|
|||||
| 111 | if ($lineItem) { |
||||
| 112 | $title = $lineItem->purchasable->title ?? $lineItem->description; |
||||
| 113 | $quantity = $lineItem->qty; |
||||
| 114 | $analytics = InstantAnalytics::$plugin->ia->eventAnalytics( |
||||
| 115 | 'Commerce', |
||||
| 116 | 'Remove from Cart', |
||||
| 117 | $title, |
||||
| 118 | $quantity |
||||
| 119 | ); |
||||
| 120 | |||||
| 121 | if ($analytics) { |
||||
| 122 | $title = $this->addProductDataFromLineItem($analytics, $lineItem); |
||||
| 123 | $analytics->setEventLabel($title); |
||||
| 124 | // Don't forget to set the product action, in this case to ADD |
||||
| 125 | $analytics->setProductActionToRemove(); |
||||
| 126 | $analytics->sendEvent(); |
||||
| 127 | |||||
| 128 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 129 | 'instant-analytics', |
||||
| 130 | 'removeFromCart for `Commerce` - `Remove to Cart` - `{title}` - `{quantity}`', |
||||
| 131 | ['title' => $title, 'quantity' => $quantity] |
||||
| 132 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 133 | } |
||||
| 134 | } |
||||
| 135 | } |
||||
| 136 | |||||
| 137 | |||||
| 138 | /** |
||||
| 139 | * Add a Craft Commerce OrderModel to an Analytics object |
||||
| 140 | * |
||||
| 141 | * @param IAnalytics $analytics the Analytics object |
||||
| 142 | * @param Order $order the Product or Variant |
||||
|
0 ignored issues
–
show
|
|||||
| 143 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 144 | public function addCommerceOrderToAnalytics($analytics = null, $order = null) |
||||
| 145 | { |
||||
| 146 | if ($order && $analytics) { |
||||
| 147 | // First, include the transaction data |
||||
| 148 | $analytics->setTransactionId($order->reference) |
||||
| 149 | ->setCurrencyCode($order->paymentCurrency) |
||||
| 150 | ->setRevenue($order->totalPrice) |
||||
| 151 | ->setTax($order->getTotalTax()) |
||||
| 152 | ->setShipping($order->getTotalShippingCost()); |
||||
| 153 | |||||
| 154 | // Coupon code? |
||||
| 155 | if ($order->couponCode) { |
||||
| 156 | $analytics->setCouponCode($order->couponCode); |
||||
| 157 | } |
||||
| 158 | |||||
| 159 | // Add each line item in the transaction |
||||
| 160 | // Two cases - variant and non variant products |
||||
| 161 | $index = 1; |
||||
| 162 | |||||
| 163 | foreach ($order->lineItems as $key => $lineItem) { |
||||
| 164 | $this->addProductDataFromLineItem($analytics, $lineItem, $index, ''); |
||||
| 165 | $index++; |
||||
| 166 | } |
||||
| 167 | } |
||||
| 168 | } |
||||
| 169 | |||||
| 170 | /** |
||||
| 171 | * Add a Craft Commerce LineItem to an Analytics object |
||||
| 172 | * |
||||
| 173 | * @param IAnalytics|null $analytics |
||||
|
0 ignored issues
–
show
|
|||||
| 174 | * @param LineItem|null $lineItem |
||||
|
0 ignored issues
–
show
|
|||||
| 175 | * @param int $index |
||||
|
0 ignored issues
–
show
|
|||||
| 176 | * @param string $listName |
||||
|
0 ignored issues
–
show
|
|||||
| 177 | * |
||||
| 178 | * @return string the title of the product |
||||
| 179 | * @throws \yii\base\InvalidConfigException |
||||
| 180 | */ |
||||
| 181 | public function addProductDataFromLineItem($analytics = null, $lineItem = null, $index = 0, $listName = ''): string |
||||
| 182 | { |
||||
| 183 | $result = ''; |
||||
| 184 | if ($lineItem && $analytics) { |
||||
| 185 | $product = null; |
||||
| 186 | $purchasable = $lineItem->purchasable; |
||||
| 187 | //This is the same for both variant and non variant products |
||||
| 188 | $productData = [ |
||||
| 189 | 'name' => $purchasable->title ?? $lineItem->description, |
||||
| 190 | 'sku' => $purchasable->sku ?? $lineItem->sku, |
||||
| 191 | 'price' => $lineItem->salePrice, |
||||
| 192 | 'quantity' => $lineItem->qty, |
||||
| 193 | ]; |
||||
| 194 | // Handle this purchasable being a Variant |
||||
| 195 | if (is_a($purchasable, Variant::class)) { |
||||
| 196 | /** @var Variant $purchasable */ |
||||
|
0 ignored issues
–
show
|
|||||
| 197 | $product = $purchasable->getProduct(); |
||||
| 198 | $variant = $purchasable; |
||||
| 199 | // Product with variants |
||||
| 200 | $productData['name'] = $product->title; |
||||
| 201 | $productData['variant'] = $variant->title; |
||||
| 202 | $productData['category'] = $product->getType(); |
||||
| 203 | } |
||||
| 204 | // Handle this purchasable being a Product |
||||
| 205 | if (is_a($purchasable, Product::class)) { |
||||
| 206 | /** @var Product $purchasable */ |
||||
|
0 ignored issues
–
show
|
|||||
| 207 | $product = $purchasable; |
||||
| 208 | $productData['name'] = $product->title; |
||||
| 209 | $productData['variant'] = $product->title; |
||||
| 210 | $productData['category'] = $product->getType(); |
||||
| 211 | } |
||||
| 212 | // Handle product lists |
||||
| 213 | if ($index) { |
||||
| 214 | $productData['position'] = $index; |
||||
| 215 | } |
||||
| 216 | if ($listName) { |
||||
| 217 | $productData['list'] = $listName; |
||||
| 218 | } |
||||
| 219 | // Add in any custom categories/brands that might be set |
||||
| 220 | if (InstantAnalytics::$settings && $product) { |
||||
| 221 | if (isset(InstantAnalytics::$settings['productCategoryField']) |
||||
| 222 | && !empty(InstantAnalytics::$settings['productCategoryField'])) { |
||||
|
0 ignored issues
–
show
|
|||||
| 223 | $productData['category'] = $this->pullDataFromField( |
||||
| 224 | $product, |
||||
| 225 | InstantAnalytics::$settings['productCategoryField'] |
||||
| 226 | ); |
||||
| 227 | } |
||||
| 228 | if (isset(InstantAnalytics::$settings['productBrandField']) |
||||
| 229 | && !empty(InstantAnalytics::$settings['productBrandField'])) { |
||||
|
0 ignored issues
–
show
|
|||||
| 230 | $productData['brand'] = $this->pullDataFromField( |
||||
| 231 | $product, |
||||
| 232 | InstantAnalytics::$settings['productBrandField'] |
||||
| 233 | ); |
||||
| 234 | } |
||||
| 235 | } |
||||
| 236 | $result = $productData['name']; |
||||
| 237 | //Add each product to the hit to be sent |
||||
| 238 | $analytics->addProduct($productData); |
||||
| 239 | } |
||||
| 240 | |||||
| 241 | return $result; |
||||
| 242 | } |
||||
| 243 | |||||
| 244 | /** |
||||
| 245 | * Add a product impression from a Craft Commerce Product or Variant |
||||
| 246 | * |
||||
| 247 | * @param IAnalytics $analytics the Analytics object |
||||
|
0 ignored issues
–
show
|
|||||
| 248 | * @param Product|Variant $productVariant the Product or Variant |
||||
| 249 | * @param int $index Where the product appears in the |
||||
|
0 ignored issues
–
show
|
|||||
| 250 | * list |
||||
|
0 ignored issues
–
show
|
|||||
| 251 | * @param string $listName |
||||
|
0 ignored issues
–
show
|
|||||
| 252 | * @param int $listIndex |
||||
|
0 ignored issues
–
show
|
|||||
| 253 | * |
||||
| 254 | * @throws \yii\base\InvalidConfigException |
||||
| 255 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 256 | public function addCommerceProductImpression( |
||||
| 257 | $analytics = null, |
||||
| 258 | $productVariant = null, |
||||
| 259 | $index = 0, |
||||
| 260 | $listName = 'default', |
||||
| 261 | $listIndex = 1 |
||||
| 262 | ) |
||||
| 263 | { |
||||
|
0 ignored issues
–
show
|
|||||
| 264 | if ($productVariant && $analytics) { |
||||
| 265 | $productData = $this->getProductDataFromProduct($productVariant); |
||||
| 266 | |||||
| 267 | /** |
||||
| 268 | * As per: https://github.com/theiconic/php-ga-measurement-protocol/issues/26 |
||||
| 269 | */ |
||||
| 270 | if ($listName && $listIndex) { |
||||
| 271 | $analytics->setProductImpressionListName($listName, $listIndex); |
||||
| 272 | } |
||||
| 273 | |||||
| 274 | if ($index) { |
||||
| 275 | $productData['position'] = $index; |
||||
| 276 | } |
||||
| 277 | |||||
| 278 | //Add the product to the hit to be sent |
||||
| 279 | $analytics->addProductImpression($productData, $listIndex); |
||||
| 280 | |||||
| 281 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 282 | 'instant-analytics', |
||||
| 283 | 'addCommerceProductImpression for `{sku}` - `{name}` - `{name}` - `{index}`', |
||||
| 284 | ['sku' => $productData['sku'], 'name' => $productData['name'], 'index' => $index] |
||||
| 285 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 286 | } |
||||
| 287 | } |
||||
| 288 | |||||
| 289 | /** |
||||
| 290 | * Add a product detail view from a Craft Commerce Product or Variant |
||||
| 291 | * |
||||
| 292 | * @param IAnalytics $analytics the Analytics object |
||||
|
0 ignored issues
–
show
|
|||||
| 293 | * @param Product|Variant $productVariant the Product or Variant |
||||
| 294 | * |
||||
| 295 | * @throws \yii\base\InvalidConfigException |
||||
| 296 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 297 | public function addCommerceProductDetailView($analytics = null, $productVariant = null) |
||||
| 298 | { |
||||
| 299 | if ($productVariant && $analytics) { |
||||
| 300 | $productData = $this->getProductDataFromProduct($productVariant); |
||||
| 301 | |||||
| 302 | // Don't forget to set the product action, in this case to DETAIL |
||||
| 303 | $analytics->setProductActionToDetail(); |
||||
| 304 | |||||
| 305 | //Add the product to the hit to be sent |
||||
| 306 | $analytics->addProduct($productData); |
||||
| 307 | |||||
| 308 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 309 | 'instant-analytics', |
||||
| 310 | 'addCommerceProductDetailView for `{sku}` - `{name}`', |
||||
| 311 | ['sku' => $productData['sku'], 'name' => $productData['name']] |
||||
| 312 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 313 | } |
||||
| 314 | } |
||||
| 315 | |||||
| 316 | /** |
||||
| 317 | * Add a checkout step and option to an Analytics object |
||||
| 318 | * |
||||
| 319 | * @param IAnalytics $analytics the Analytics object |
||||
| 320 | * @param Order $order the Product or Variant |
||||
|
0 ignored issues
–
show
|
|||||
| 321 | * @param int $step the checkout step |
||||
|
0 ignored issues
–
show
|
|||||
| 322 | * @param string $option the checkout option |
||||
|
0 ignored issues
–
show
|
|||||
| 323 | */ |
||||
|
0 ignored issues
–
show
|
|||||
| 324 | public function addCommerceCheckoutStep($analytics = null, $order = null, $step = 1, $option = '') |
||||
| 325 | { |
||||
| 326 | if ($order && $analytics) { |
||||
| 327 | // Add each line item in the transaction |
||||
| 328 | // Two cases - variant and non variant products |
||||
| 329 | $index = 1; |
||||
| 330 | |||||
| 331 | foreach ($order->lineItems as $key => $lineItem) { |
||||
| 332 | $this->addProductDataFromLineItem($analytics, $lineItem, $index, ''); |
||||
| 333 | $index++; |
||||
| 334 | } |
||||
| 335 | |||||
| 336 | $analytics->setCheckoutStep($step); |
||||
| 337 | |||||
| 338 | if ($option) { |
||||
| 339 | $analytics->setCheckoutStepOption($option); |
||||
| 340 | } |
||||
| 341 | |||||
| 342 | // Don't forget to set the product action, in this case to CHECKOUT |
||||
| 343 | $analytics->setProductActionToCheckout(); |
||||
| 344 | |||||
| 345 | Craft::info(Craft::t( |
||||
|
0 ignored issues
–
show
|
|||||
| 346 | 'instant-analytics', |
||||
| 347 | 'addCommerceCheckoutStep step: `{step}` with option: `{option}`', |
||||
| 348 | ['step' => $step, 'option' => $option] |
||||
| 349 | ), __METHOD__); |
||||
|
0 ignored issues
–
show
For multi-line function calls, the closing parenthesis should be on a new line.
If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line: someFunctionCall(
$firstArgument,
$secondArgument,
$thirdArgument
); // Closing parenthesis on a new line.
Loading history...
|
|||||
| 350 | } |
||||
| 351 | } |
||||
| 352 | |||||
| 353 | /** |
||||
| 354 | * Extract product data from a Craft Commerce Product or Variant |
||||
| 355 | * |
||||
| 356 | * @param Product|Variant $productVariant the Product or Variant |
||||
| 357 | * |
||||
| 358 | * @return array the product data |
||||
| 359 | * @throws \yii\base\InvalidConfigException |
||||
| 360 | */ |
||||
| 361 | public function getProductDataFromProduct($productVariant = null): array |
||||
| 362 | { |
||||
| 363 | $result = []; |
||||
| 364 | |||||
| 365 | // Extract the variant if it's a Product or Purchasable |
||||
| 366 | if ($productVariant && \is_object($productVariant)) { |
||||
| 367 | if (is_a($productVariant, Product::class) |
||||
| 368 | || is_a($productVariant, Purchasable::class) |
||||
| 369 | ) { |
||||
| 370 | $productType = property_exists($productVariant, 'typeId') |
||||
| 371 | ? InstantAnalytics::$commercePlugin->getProductTypes()->getProductTypeById($productVariant->typeId) |
||||
|
0 ignored issues
–
show
The method
getProductTypes() does not exist on null.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||
| 372 | : null; |
||||
| 373 | |||||
| 374 | if ($productType && $productType->hasVariants) { |
||||
| 375 | $productVariants = $productVariant->getVariants(); |
||||
| 376 | $productVariant = reset($productVariants); |
||||
| 377 | $product = $productVariant->getProduct(); |
||||
| 378 | |||||
| 379 | if ($product) { |
||||
| 380 | $category = $product->getType()['name']; |
||||
| 381 | $name = $product->title; |
||||
| 382 | $variant = $productVariant->title; |
||||
| 383 | } else { |
||||
| 384 | $category = $productVariant->getType()['name']; |
||||
| 385 | $name = $productVariant->title; |
||||
| 386 | $variant = ''; |
||||
| 387 | } |
||||
| 388 | } else { |
||||
| 389 | if (!empty($productVariant->defaultVariantId)) { |
||||
| 390 | /** @var Variant $productVariant */ |
||||
|
0 ignored issues
–
show
|
|||||
| 391 | $productVariant = InstantAnalytics::$commercePlugin->getVariants()->getVariantById( |
||||
| 392 | $productVariant->defaultVariantId |
||||
| 393 | ); |
||||
| 394 | $category = $productVariant->getProduct()->getType()['name']; |
||||
| 395 | $name = $productVariant->title; |
||||
| 396 | $variant = ''; |
||||
| 397 | } else { |
||||
| 398 | if (isset($productVariant->product)) { |
||||
| 399 | $category = $productVariant->product->getType()['name']; |
||||
| 400 | $name = $productVariant->product->title; |
||||
| 401 | } else { |
||||
| 402 | $category = $productVariant->getType()['name']; |
||||
| 403 | $name = $productVariant->title; |
||||
| 404 | } |
||||
| 405 | $variant = $productVariant->title; |
||||
| 406 | } |
||||
| 407 | } |
||||
| 408 | } |
||||
| 409 | |||||
| 410 | $productData = [ |
||||
| 411 | 'sku' => $productVariant->sku, |
||||
| 412 | 'name' => $name, |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 413 | 'price' => number_format($productVariant->price, 2, '.', ''), |
||||
| 414 | 'category' => $category, |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 415 | ]; |
||||
| 416 | |||||
| 417 | if ($variant) { |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 418 | $productData['variant'] = $variant; |
||||
| 419 | } |
||||
| 420 | |||||
| 421 | $isVariant = is_a($productVariant, Variant::class); |
||||
| 422 | |||||
| 423 | if (InstantAnalytics::$settings) { |
||||
| 424 | if (isset(InstantAnalytics::$settings['productCategoryField']) |
||||
| 425 | && !empty(InstantAnalytics::$settings['productCategoryField'])) { |
||||
|
0 ignored issues
–
show
|
|||||
| 426 | $productData['category'] = $this->pullDataFromField( |
||||
| 427 | $productVariant, |
||||
| 428 | InstantAnalytics::$settings['productCategoryField'] |
||||
| 429 | ); |
||||
| 430 | if (empty($productData['category']) && $isVariant) { |
||||
| 431 | $productData['category'] = $this->pullDataFromField( |
||||
| 432 | $productVariant->product, |
||||
| 433 | InstantAnalytics::$settings['productCategoryField'] |
||||
| 434 | ); |
||||
| 435 | } |
||||
| 436 | } |
||||
| 437 | if (isset(InstantAnalytics::$settings['productBrandField']) |
||||
| 438 | && !empty(InstantAnalytics::$settings['productBrandField'])) { |
||||
|
0 ignored issues
–
show
|
|||||
| 439 | $productData['brand'] = $this->pullDataFromField( |
||||
| 440 | $productVariant, |
||||
| 441 | InstantAnalytics::$settings['productBrandField'], |
||||
| 442 | true |
||||
| 443 | ); |
||||
| 444 | |||||
| 445 | if (empty($productData['brand']) && $isVariant) { |
||||
| 446 | $productData['brand'] = $this->pullDataFromField( |
||||
| 447 | $productVariant, |
||||
| 448 | InstantAnalytics::$settings['productBrandField'], |
||||
| 449 | true |
||||
| 450 | ); |
||||
| 451 | } |
||||
| 452 | } |
||||
| 453 | } |
||||
| 454 | |||||
| 455 | $result = $productData; |
||||
| 456 | } |
||||
| 457 | |||||
| 458 | return $result; |
||||
| 459 | } |
||||
| 460 | |||||
| 461 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 462 | * @param Product|Variant|null $productVariant |
||||
|
0 ignored issues
–
show
|
|||||
| 463 | * @param string $fieldHandle |
||||
|
0 ignored issues
–
show
|
|||||
| 464 | * @param bool $isBrand |
||||
|
0 ignored issues
–
show
|
|||||
| 465 | * |
||||
| 466 | * @return string |
||||
| 467 | */ |
||||
| 468 | protected function pullDataFromField($productVariant, $fieldHandle, $isBrand = false): string |
||||
| 469 | { |
||||
| 470 | $result = ''; |
||||
| 471 | if ($productVariant && $fieldHandle) { |
||||
| 472 | $srcField = $productVariant[$fieldHandle] ?? $productVariant->product[$fieldHandle] ?? null; |
||||
| 473 | // Handle eager loaded elements |
||||
| 474 | if (is_array($srcField)) { |
||||
| 475 | return $this->getDataFromElements($isBrand, $srcField); |
||||
| 476 | } |
||||
| 477 | // If the source field isn't an object, return nothing |
||||
| 478 | if (!is_object($srcField)) { |
||||
| 479 | return $result; |
||||
| 480 | } |
||||
| 481 | switch (\get_class($srcField)) { |
||||
| 482 | case MatrixBlockQuery::class: |
||||
|
0 ignored issues
–
show
|
|||||
| 483 | break; |
||||
| 484 | case TagQuery::class: |
||||
|
0 ignored issues
–
show
|
|||||
| 485 | break; |
||||
| 486 | case CategoryQuery::class: |
||||
|
0 ignored issues
–
show
|
|||||
| 487 | $result = $this->getDataFromElements($isBrand, $srcField->all()); |
||||
| 488 | break; |
||||
| 489 | |||||
| 490 | |||||
| 491 | default: |
||||
|
0 ignored issues
–
show
|
|||||
| 492 | $result = strip_tags($srcField); |
||||
|
0 ignored issues
–
show
$srcField of type object is incompatible with the type string expected by parameter $string of strip_tags().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 493 | break; |
||||
| 494 | } |
||||
| 495 | } |
||||
| 496 | |||||
| 497 | return $result; |
||||
| 498 | } |
||||
| 499 | |||||
| 500 | /** |
||||
|
0 ignored issues
–
show
|
|||||
| 501 | * @param bool $isBrand |
||||
|
0 ignored issues
–
show
|
|||||
| 502 | * @param array $elements |
||||
|
0 ignored issues
–
show
|
|||||
| 503 | * @return string |
||||
|
0 ignored issues
–
show
|
|||||
| 504 | */ |
||||
| 505 | protected function getDataFromElements(bool $isBrand, array $elements): string |
||||
| 506 | { |
||||
| 507 | $cats = []; |
||||
| 508 | |||||
| 509 | if ($isBrand) { |
||||
| 510 | // Because we can only have one brand, we'll get |
||||
| 511 | // the very last category. This means if our |
||||
| 512 | // brand is a sub-category, we'll get the child |
||||
| 513 | // not the parent. |
||||
| 514 | foreach ($elements as $cat) { |
||||
| 515 | $cats = [$cat->title]; |
||||
| 516 | } |
||||
| 517 | } else { |
||||
| 518 | // For every category, show its ancestors |
||||
| 519 | // delimited by a slash. |
||||
| 520 | foreach ($elements as $cat) { |
||||
| 521 | $name = $cat->title; |
||||
| 522 | |||||
| 523 | while ($cat = $cat->parent) { |
||||
| 524 | $name = $cat->title . '/' . $name; |
||||
| 525 | } |
||||
| 526 | |||||
| 527 | $cats[] = $name; |
||||
| 528 | } |
||||
| 529 | } |
||||
| 530 | |||||
| 531 | // Join separate categories with a pipe. |
||||
| 532 | return implode('|', $cats); |
||||
| 533 | } |
||||
| 534 | } |
||||
| 535 |