Commit 04ccd84d by lmf

增加FB插件

parent 01582f4e

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
"colinmollenhour/php-redis-session-abstract": "~1.4.0", "colinmollenhour/php-redis-session-abstract": "~1.4.0",
"composer/composer": "^1.9 || ^2.0", "composer/composer": "^1.9 || ^2.0",
"elasticsearch/elasticsearch": "~7.11.0", "elasticsearch/elasticsearch": "~7.11.0",
"facebook/facebook-for-magento2": "^1.4",
"google/apiclient": "^2.12", "google/apiclient": "^2.12",
"guzzlehttp/guzzle": "^6.3.3", "guzzlehttp/guzzle": "^6.3.3",
"jajuma/module-webpimages": "^2.1", "jajuma/module-webpimages": "^2.1",
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "bd7ce4c2323b6f416cd64332b0fae6f1", "content-hash": "c25f21a48780f0491f5334e83669ae20",
"packages": [ "packages": [
{ {
"name": "airwallex/payments-plugin-magento", "name": "airwallex/payments-plugin-magento",
...@@ -1137,6 +1137,81 @@ ...@@ -1137,6 +1137,81 @@
"time": "2021-11-16T11:51:30+00:00" "time": "2021-11-16T11:51:30+00:00"
}, },
{ {
"name": "facebook/facebook-for-magento2",
"version": "1.4.4",
"dist": {
"type": "zip",
"url": "https://repo.magento.com/archives/facebook/facebook-for-magento2/facebook-facebook-for-magento2-1.4.4.0.zip",
"shasum": "a6fbb48b1f4ac9395bcd8fd7e26f334cb0092dc0"
},
"require": {
"facebook/php-business-sdk": "9.0.3"
},
"type": "magento2-module",
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Facebook\\BusinessExtension\\": ""
}
},
"license": [
"GPL-1.0-or-later"
],
"description": "Facebook Business Extension for Magento 2"
},
{
"name": "facebook/php-business-sdk",
"version": "9.0.3",
"source": {
"type": "git",
"url": "https://github.com/facebook/facebook-php-business-sdk.git",
"reference": "4d39da6c1e1cdc9916082d97a5191a549e127b0f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/facebook-php-business-sdk/zipball/4d39da6c1e1cdc9916082d97a5191a549e127b0f",
"reference": "4d39da6c1e1cdc9916082d97a5191a549e127b0f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"guzzlehttp/guzzle": "^6.5 || ^7.0"
},
"require-dev": {
"mockery/mockery": "1.3.3",
"phpunit/phpunit": "~8",
"symfony/finder": "~2.6"
},
"type": "library",
"autoload": {
"psr-4": {
"FacebookAds\\": "src/FacebookAds/"
}
},
"notification-url": "https://packagist.org/downloads/",
"description": "PHP SDK for Facebook Business",
"homepage": "https://developers.facebook.com/",
"keywords": [
"ads",
"business",
"facebook",
"instagram",
"page",
"sdk"
],
"support": {
"source": "https://github.com/facebook/facebook-php-business-sdk/tree/9.0.3"
},
"time": "2021-01-14T00:20:35+00:00"
},
{
"name": "fgrosse/phpasn1", "name": "fgrosse/phpasn1",
"version": "v2.4.0", "version": "v2.4.0",
"source": { "source": {
......
...@@ -133,6 +133,7 @@ return array( ...@@ -133,6 +133,7 @@ return array(
'940abd8fb01ee76a36b44f35dcf9783b' => $vendorDir . '/weew/helpers-array/src/array.php', '940abd8fb01ee76a36b44f35dcf9783b' => $vendorDir . '/weew/helpers-array/src/array.php',
'b598380463d27491e4810196bf363d15' => $vendorDir . '/airwallex/payments-plugin-magento/registration.php', 'b598380463d27491e4810196bf363d15' => $vendorDir . '/airwallex/payments-plugin-magento/registration.php',
'8592c7b0947d8a0965a9e8c3d16f9c24' => $vendorDir . '/elasticsearch/elasticsearch/src/autoload.php', '8592c7b0947d8a0965a9e8c3d16f9c24' => $vendorDir . '/elasticsearch/elasticsearch/src/autoload.php',
'0af31bb4ab00a0ef60de99813b439504' => $vendorDir . '/facebook/facebook-for-magento2/registration.php',
'0b2ea8cc52669e97f3bdd7d78dcd8eb5' => $vendorDir . '/jajuma/module-webpimages/registration.php', '0b2ea8cc52669e97f3bdd7d78dcd8eb5' => $vendorDir . '/jajuma/module-webpimages/registration.php',
'c346667cd80efe409e847ee7ac6f7ce1' => $vendorDir . '/magenest/module-google-shopping/registration.php', 'c346667cd80efe409e847ee7ac6f7ce1' => $vendorDir . '/magenest/module-google-shopping/registration.php',
'eda65932675b68b5aee4503e0762d64d' => $vendorDir . '/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/_bootstrap.php', 'eda65932675b68b5aee4503e0762d64d' => $vendorDir . '/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/_bootstrap.php',
......
...@@ -149,6 +149,8 @@ return array( ...@@ -149,6 +149,8 @@ return array(
'Google\\' => array($vendorDir . '/google/apiclient/src'), 'Google\\' => array($vendorDir . '/google/apiclient/src'),
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'), 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
'Facebook\\WebDriver\\' => array($vendorDir . '/php-webdriver/webdriver/lib'), 'Facebook\\WebDriver\\' => array($vendorDir . '/php-webdriver/webdriver/lib'),
'Facebook\\BusinessExtension\\' => array($vendorDir . '/facebook/facebook-for-magento2'),
'FacebookAds\\' => array($vendorDir . '/facebook/php-business-sdk/src/FacebookAds'),
'FG\\' => array($vendorDir . '/fgrosse/phpasn1/lib'), 'FG\\' => array($vendorDir . '/fgrosse/phpasn1/lib'),
'Elasticsearch\\' => array($vendorDir . '/elasticsearch/elasticsearch/src/Elasticsearch'), 'Elasticsearch\\' => array($vendorDir . '/elasticsearch/elasticsearch/src/Elasticsearch'),
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'), 'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
......
...@@ -134,6 +134,7 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf ...@@ -134,6 +134,7 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf
'940abd8fb01ee76a36b44f35dcf9783b' => __DIR__ . '/..' . '/weew/helpers-array/src/array.php', '940abd8fb01ee76a36b44f35dcf9783b' => __DIR__ . '/..' . '/weew/helpers-array/src/array.php',
'b598380463d27491e4810196bf363d15' => __DIR__ . '/..' . '/airwallex/payments-plugin-magento/registration.php', 'b598380463d27491e4810196bf363d15' => __DIR__ . '/..' . '/airwallex/payments-plugin-magento/registration.php',
'8592c7b0947d8a0965a9e8c3d16f9c24' => __DIR__ . '/..' . '/elasticsearch/elasticsearch/src/autoload.php', '8592c7b0947d8a0965a9e8c3d16f9c24' => __DIR__ . '/..' . '/elasticsearch/elasticsearch/src/autoload.php',
'0af31bb4ab00a0ef60de99813b439504' => __DIR__ . '/..' . '/facebook/facebook-for-magento2/registration.php',
'0b2ea8cc52669e97f3bdd7d78dcd8eb5' => __DIR__ . '/..' . '/jajuma/module-webpimages/registration.php', '0b2ea8cc52669e97f3bdd7d78dcd8eb5' => __DIR__ . '/..' . '/jajuma/module-webpimages/registration.php',
'c346667cd80efe409e847ee7ac6f7ce1' => __DIR__ . '/..' . '/magenest/module-google-shopping/registration.php', 'c346667cd80efe409e847ee7ac6f7ce1' => __DIR__ . '/..' . '/magenest/module-google-shopping/registration.php',
'eda65932675b68b5aee4503e0762d64d' => __DIR__ . '/..' . '/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/_bootstrap.php', 'eda65932675b68b5aee4503e0762d64d' => __DIR__ . '/..' . '/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/_bootstrap.php',
...@@ -330,6 +331,8 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf ...@@ -330,6 +331,8 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf
array ( array (
'Firebase\\JWT\\' => 13, 'Firebase\\JWT\\' => 13,
'Facebook\\WebDriver\\' => 19, 'Facebook\\WebDriver\\' => 19,
'Facebook\\BusinessExtension\\' => 27,
'FacebookAds\\' => 12,
'FG\\' => 3, 'FG\\' => 3,
), ),
'E' => 'E' =>
...@@ -960,6 +963,14 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf ...@@ -960,6 +963,14 @@ class ComposerStaticInitb71ce7c407b65980cf51508f463c8dcf
array ( array (
0 => __DIR__ . '/..' . '/php-webdriver/webdriver/lib', 0 => __DIR__ . '/..' . '/php-webdriver/webdriver/lib',
), ),
'Facebook\\BusinessExtension\\' =>
array (
0 => __DIR__ . '/..' . '/facebook/facebook-for-magento2',
),
'FacebookAds\\' =>
array (
0 => __DIR__ . '/..' . '/facebook/php-business-sdk/src/FacebookAds',
),
'FG\\' => 'FG\\' =>
array ( array (
0 => __DIR__ . '/..' . '/fgrosse/phpasn1/lib', 0 => __DIR__ . '/..' . '/fgrosse/phpasn1/lib',
......
...@@ -2260,6 +2260,87 @@ ...@@ -2260,6 +2260,87 @@
"install-path": "../ezimuel/ringphp" "install-path": "../ezimuel/ringphp"
}, },
{ {
"name": "facebook/facebook-for-magento2",
"version": "1.4.4",
"version_normalized": "1.4.4.0",
"dist": {
"type": "zip",
"url": "https://repo.magento.com/archives/facebook/facebook-for-magento2/facebook-facebook-for-magento2-1.4.4.0.zip",
"shasum": "a6fbb48b1f4ac9395bcd8fd7e26f334cb0092dc0"
},
"require": {
"facebook/php-business-sdk": "9.0.3"
},
"type": "magento2-module",
"installation-source": "dist",
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Facebook\\BusinessExtension\\": ""
}
},
"license": [
"GPL-1.0-or-later"
],
"description": "Facebook Business Extension for Magento 2",
"install-path": "../facebook/facebook-for-magento2"
},
{
"name": "facebook/php-business-sdk",
"version": "9.0.3",
"version_normalized": "9.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/facebook/facebook-php-business-sdk.git",
"reference": "4d39da6c1e1cdc9916082d97a5191a549e127b0f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/facebook-php-business-sdk/zipball/4d39da6c1e1cdc9916082d97a5191a549e127b0f",
"reference": "4d39da6c1e1cdc9916082d97a5191a549e127b0f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"guzzlehttp/guzzle": "^6.5 || ^7.0"
},
"require-dev": {
"mockery/mockery": "1.3.3",
"phpunit/phpunit": "~8",
"symfony/finder": "~2.6"
},
"time": "2021-01-14T00:20:35+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"FacebookAds\\": "src/FacebookAds/"
}
},
"notification-url": "https://packagist.org/downloads/",
"description": "PHP SDK for Facebook Business",
"homepage": "https://developers.facebook.com/",
"keywords": [
"ads",
"business",
"facebook",
"instagram",
"page",
"sdk"
],
"support": {
"source": "https://github.com/facebook/facebook-php-business-sdk/tree/9.0.3"
},
"install-path": "../facebook/php-business-sdk"
},
{
"name": "fgrosse/phpasn1", "name": "fgrosse/phpasn1",
"version": "v2.4.0", "version": "v2.4.0",
"version_normalized": "2.4.0.0", "version_normalized": "2.4.0.0",
......
<?php return array( <?php return array(
'root' => array( 'root' => array(
'pretty_version' => 'dev-master', 'pretty_version' => '2.4.3',
'version' => 'dev-master', 'version' => '2.4.3.0',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '54297ee0198f5ada7d18d3d02b1b23c4e90f00c0', 'reference' => NULL,
'name' => 'magento/magento2ce', 'name' => 'magento/magento2ce',
'dev' => true, 'dev' => true,
), ),
...@@ -349,6 +349,24 @@ ...@@ -349,6 +349,24 @@
'reference' => '92b8161404ab1ad84059ebed41d9f757e897ce74', 'reference' => '92b8161404ab1ad84059ebed41d9f757e897ce74',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'facebook/facebook-for-magento2' => array(
'pretty_version' => '1.4.4',
'version' => '1.4.4.0',
'type' => 'magento2-module',
'install_path' => __DIR__ . '/../facebook/facebook-for-magento2',
'aliases' => array(),
'reference' => NULL,
'dev_requirement' => false,
),
'facebook/php-business-sdk' => array(
'pretty_version' => '9.0.3',
'version' => '9.0.3.0',
'type' => 'library',
'install_path' => __DIR__ . '/../facebook/php-business-sdk',
'aliases' => array(),
'reference' => '4d39da6c1e1cdc9916082d97a5191a549e127b0f',
'dev_requirement' => false,
),
'facebook/webdriver' => array( 'facebook/webdriver' => array(
'dev_requirement' => true, 'dev_requirement' => true,
'replaced' => array( 'replaced' => array(
...@@ -1010,12 +1028,12 @@ ...@@ -1010,12 +1028,12 @@
'dev_requirement' => true, 'dev_requirement' => true,
), ),
'magento/magento2ce' => array( 'magento/magento2ce' => array(
'pretty_version' => 'dev-master', 'pretty_version' => '2.4.3',
'version' => 'dev-master', 'version' => '2.4.3.0',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '54297ee0198f5ada7d18d3d02b1b23c4e90f00c0', 'reference' => NULL,
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'magento/module-admin-analytics' => array( 'magento/module-admin-analytics' => array(
......
name: Bug Report
description: File a bug report / issue
title: "[Bug]: "
labels: [bug, triage]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. email@example.com
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: input
id: magento_version
attributes:
label: Magento Version
description: What version of the Magento software are you running?
validations:
required: true
- type: input
id: plugin_version
attributes:
label: Plugin Version
description: What version of the plugin are you running?
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. Use info tab page for logs (for version 1.4.3 onwards).
render: shell
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://opensource.fb.com/code-of-conduct/) that we expect project participants to adhere to.
options:
- label: I agree to follow this project's Code of Conduct
required: true
blank_issues_enabled: false
contact_links:
- name: Bug Report With Sensitive Information
url: https://www.facebook.com/help/contact/224834796277182
about: Please report issues here in case you want to provide sensitive information, like Pixel ID and logs, that will help us better understand the context.
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Adminhtml;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Magento\Framework\Module\ModuleListInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\Escaper;
use Facebook\BusinessExtension\Helper\LogOrganization;
class Info extends \Magento\Backend\Block\Template
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ModuleListInterface
*/
protected $moduleList;
/**
* @var ProductMetadataInterface
*/
protected $productMetadataInterface;
/**
* @var Escaper
*/
private $escaper;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param FBEHelper $fbeHelper
* @param ModuleListInterface $moduleList
* @param ProductMetadataInterface $productMetadataInterface
* @param Escaper $escaper
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
FBEHelper $fbeHelper,
ModuleListInterface $moduleList,
ProductMetadataInterface $productMetadataInterface,
Escaper $escaper,
array $data = []
) {
$this->fbeHelper = $fbeHelper;
$this->moduleList = $moduleList;
$this->productMetadataInterface = $productMetadataInterface;
$this->escaper = $escaper;
parent::__construct($context, $data);
}
/**
* @return string
*/
public function getFBEVersion() {
return $this->moduleList->getOne("Facebook_BusinessExtension")["setup_version"];
}
/**
* @return string
*/
public function getMagentoVersion() {
return $this->productMetadataInterface->getVersion();
}
/**
* @return string|null
*/
public function fetchPixelId()
{
return $this->fbeHelper->getConfigValue('fbpixel/id');
}
/**
* @return string|null
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getExternalBusinessId()
{
return $this->fbeHelper->getFBEExternalBusinessId();
}
public function allLogs() {
$sortedString = implode("\n", LogOrganization::organizeLogs());
return nl2br($sortedString);
}
public function publicIssueLink() {
$magento_version = $this->getMagentoVersion();
$plugin_version = $this->getFBEVersion();
return "https://github.com/facebookincubator/facebook-for-magento2/issues/new?&template=bug-report.yml&magento_version="
. $magento_version . "&plugin_version=" . $plugin_version;
}
public function privateIssueLink() {
$magento_version = $this->getMagentoVersion();
$plugin_version = $this->getFBEVersion();
$extern_bus_id = $this->getExternalBusinessId();
$pixel_id = $this->fetchPixelId();
return "https://www.facebook.com/help/contact/224834796277182?Field1264912827263491="
. $magento_version . "&Field1465992913778514=" . $plugin_version
. "&Field1500601380300162=" . $extern_bus_id . "&Field2972445263018062=" . $pixel_id;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Adminhtml;
use Facebook\BusinessExtension\Helper\FBEHelper;
class Setup extends \Magento\Backend\Block\Template
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @param \Magento\Backend\Block\Template\Context $context
* @param FBEHelper $fbeHelper
* @param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
FBEHelper $fbeHelper,
array $data = []
) {
$this->fbeHelper = $fbeHelper;
parent::__construct($context, $data);
}
/**
* @return mixed
*/
public function getPixelAjaxRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbpixel');
}
/**
* @return mixed
*/
public function getAccessTokenAjaxRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbtoken');
}
/**
* @return mixed
*/
public function getProfilesAjaxRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbprofiles');
}
/**
* @return mixed
*/
public function getAAMSettingsRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbaamsettings');
}
/**
* @return string|null
*/
public function fetchPixelId()
{
return $this->fbeHelper->getConfigValue('fbpixel/id');
}
/**
* @return string|null
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getExternalBusinessId()
{
return $this->fbeHelper->getFBEExternalBusinessId();
}
/**
* @return mixed
*/
public function getFeedPushAjaxRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbfeedpush');
}
/**
* @return mixed
*/
public function getDeleteAssetIdsAjaxRoute()
{
return $this->fbeHelper->getUrl('fbeadmin/ajax/fbdeleteasset');
}
/**
* @return mixed
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getCurrencyCode()
{
return $this->fbeHelper->getStoreCurrencyCode();
}
/**
* @return string
*/
public function isFBEInstalled()
{
return $this->fbeHelper->isFBEInstalled();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Adminhtml\System\Config;
use Magento\Backend\Block\Widget\Button;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
class CategoryFeed extends Field
{
/**
* @var string
*/
protected $_template = 'Facebook_BusinessExtension::system/config/category_feed.phtml';
/**
* Remove scope label
*
* @param AbstractElement $element
* @return string
*/
public function render(AbstractElement $element)
{
$element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
return parent::render($element);
}
/**
* @todo move to helper
* @return string
*/
public function getAjaxUrl()
{
return $this->getUrl('fbeadmin/ajax/categoryUpload');
}
/**
* @param AbstractElement $element
* @return string
*/
protected function _getElementHtml(AbstractElement $element)
{
return $this->_toHtml();
}
/**
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function getButtonHtml()
{
/** @var Button $button */
$button = $this->getLayout()->createBlock(Button::class);
return $button->setData(['id' => 'fb_category_upload_btn', 'label' => __('Upload to Facebook')])
->toHtml();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Adminhtml\System\Config;
use Magento\Backend\Block\Widget\Button;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
class ProductFeed extends Field
{
/**
* @var string
*/
protected $_template = 'Facebook_BusinessExtension::system/config/product_feed.phtml';
/**
* Remove scope label
*
* @param AbstractElement $element
* @return string
*/
public function render(AbstractElement $element)
{
$element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
return parent::render($element);
}
/**
* @todo move to helper
* @return string
*/
public function getAjaxUrl()
{
return $this->getUrl('fbeadmin/ajax/productFeedUpload');
}
/**
* @param AbstractElement $element
* @return string
*/
protected function _getElementHtml(AbstractElement $element)
{
return $this->_toHtml();
}
/**
* @return string
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function getButtonHtml()
{
/** @var Button $button */
$button = $this->getLayout()->createBlock(Button::class);
return $button->setData(['id' => 'fb_feed_upload_btn', 'label' => __('Upload to Facebook')])
->toHtml();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
class AddToCart extends Common
{
/**
* @return string
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getProductInfoUrl()
{
return sprintf('%sfbe/Pixel/ProductInfoForAddToCart', $this->fbeHelper->getBaseUrl());
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Registry;
use Magento\Framework\View\Element\Template\Context;
class Common extends \Magento\Framework\View\Element\Template
{
/**
* @var ObjectManagerInterface
*/
protected $objectManager;
/**
* @var Registry
*/
protected $registry;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var MagentoDataHelper
*/
protected $magentoDataHelper;
/**
* Common constructor
*
* @param Context $context
* @param ObjectManagerInterface $objectManager
* @param Registry $registry
* @param FBEHelper $fbeHelper
* @param MagentoDataHelper $magentoDataHelper
* @param array $data
*/
public function __construct(
Context $context,
ObjectManagerInterface $objectManager,
Registry $registry,
FBEHelper $fbeHelper,
MagentoDataHelper $magentoDataHelper,
array $data = []
) {
parent::__construct($context, $data);
$this->objectManager = $objectManager;
$this->registry = $registry;
$this->fbeHelper = $fbeHelper;
$this->magentoDataHelper = $magentoDataHelper;
}
/**
* @param $a
* @return string
*/
public function arrayToCommaSeparatedStringValues($a)
{
return implode(',', array_map(function ($i) {
return '"' . $i . '"';
}, $a));
}
/**
* @param $string
* @return string
*/
public function escapeQuotes($string)
{
return addslashes($string);
}
/**
* @return mixed|null
*/
public function getFacebookPixelID()
{
return $this->fbeHelper->getPixelID();
}
/**
* @return string
*/
public function getSource()
{
return $this->fbeHelper->getSource();
}
/**
* @return mixed
*/
public function getMagentoVersion()
{
return $this->fbeHelper->getMagentoVersion();
}
/**
* @return mixed
*/
public function getPluginVersion()
{
return $this->fbeHelper->getPluginVersion();
}
/**
* @return string
*/
public function getFacebookAgentVersion()
{
return $this->fbeHelper->getPartnerAgent();
}
/**
* @return string
*/
public function getContentType()
{
return 'product';
}
/**
* @return mixed
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getCurrency()
{
return $this->_storeManager->getStore()->getCurrentCurrency()->getCode();
}
/**
* @param $pixelId
* @param $pixelEvent
*/
public function logEvent($pixelId, $pixelEvent)
{
$this->fbeHelper->logPixelEvent($pixelId, $pixelEvent);
}
/**
* @param $eventId
*/
public function trackServerEvent($eventId)
{
$this->_eventManager->dispatch($this->getEventToObserveName(), ['eventId' => $eventId]);
}
/**
* @return string
*/
public function getEventToObserveName()
{
return '';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
use Facebook\BusinessExtension\Helper\AAMFieldsExtractorHelper;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Registry;
use Magento\Framework\View\Element\Template\Context;
class Head extends Common
{
/**
* @var AAMFieldsExtractorHelper
*/
protected $aamFieldsExtractorHelper;
/**
* Head constructor
*
* @param Context $context
* @param ObjectManagerInterface $objectManager
* @param Registry $registry
* @param FBEHelper $fbeHelper
* @param MagentoDataHelper $magentoDataHelper
* @param AAMFieldsExtractorHelper $aamFieldsExtractorHelper
* @param array $data
*/
public function __construct(
Context $context,
ObjectManagerInterface $objectManager,
Registry $registry,
FBEHelper $fbeHelper,
MagentoDataHelper $magentoDataHelper,
AAMFieldsExtractorHelper $aamFieldsExtractorHelper,
array $data = []
) {
parent::__construct($context, $objectManager, $registry, $fbeHelper, $magentoDataHelper, $data);
$this->aamFieldsExtractorHelper = $aamFieldsExtractorHelper;
}
/**
* Returns the user data that will be added in the pixel init code
* @return string
*/
public function getPixelInitCode()
{
$userDataArray = $this->aamFieldsExtractorHelper->getNormalizedUserData();
if ($userDataArray) {
return json_encode(array_filter($userDataArray), JSON_PRETTY_PRINT | JSON_FORCE_OBJECT);
}
return '{}';
}
/**
* Create JS code with the data processing options if required
* To learn about this options in Facebook Pixel, read:
* https://developers.facebook.com/docs/marketing-apis/data-processing-options
* @return string
*/
public function getDataProcessingOptionsJSCode()
{
return '';
}
/**
* Create the data processing options passed in the Pixel image tag
* Read about this options in:
* https://developers.facebook.com/docs/marketing-apis/data-processing-options
* @return string
*/
public function getDataProcessingOptionsImgTag()
{
return '';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
class InitiateCheckout extends Common
{
/**
* @return string
*/
public function getContentIDs()
{
$productIds = [];
$cart = $this->fbeHelper->getObject(\Magento\Checkout\Model\Cart::class);
$items = $cart->getQuote()->getAllVisibleItems();
foreach ($items as $item) {
$product = $item->getProduct();
$productIds[] = $product->getId();
}
return $this->arrayToCommaSeparatedStringValues($productIds);
}
public function getValue()
{
$cart = $this->fbeHelper->getObject(\Magento\Checkout\Model\Cart::class);
if (!$cart || !$cart->getQuote()) {
return null;
}
$subtotal = $cart->getQuote()->getSubtotal();
if ($subtotal) {
$priceHelper = $this->fbeHelper->getObject(\Magento\Framework\Pricing\Helper\Data::class);
return $priceHelper->currency($subtotal, false, false);
} else {
return null;
}
}
/**
* @return string
*/
public function getContents()
{
$cart = $this->fbeHelper->getObject(\Magento\Checkout\Model\Cart::class);
if (!$cart || !$cart->getQuote()) {
return '';
}
$contents = [];
$items = $cart->getQuote()->getAllVisibleItems();
$priceHelper = $this->objectManager->get(\Magento\Framework\Pricing\Helper\Data::class);
foreach ($items as $item) {
$product = $item->getProduct();
$price = $priceHelper->currency($product->getFinalPrice(), false, false);
$content = '{id:"' . $product->getId() . '",quantity:' . (int)$item->getQty()
. ',item_price:' . $price . "}";
$contents[] = $content;
}
return implode(',', $contents);
}
/**
* @return int|null
*/
public function getNumItems()
{
$cart = $this->fbeHelper->getObject(\Magento\Checkout\Model\Cart::class);
if (!$cart || !$cart->getQuote()) {
return null;
}
$numItems = 0;
$items = $cart->getQuote()->getAllVisibleItems();
foreach ($items as $item) {
$numItems += $item->getQty();
}
return $numItems;
}
/**
* @return string
*/
public function getEventToObserveName()
{
return 'facebook_businessextension_ssapi_initiate_checkout';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
use Magento\Catalog\Model\Product;
use Magento\Sales\Model\Order;
class Purchase extends Common
{
/**
* @return string
*/
public function getContentIDs()
{
$productIds = [];
/** @var Order $order */
$order = $this->fbeHelper->getObject(\Magento\Checkout\Model\Session::class)->getLastRealOrder();
if ($order) {
$items = $order->getItemsCollection();
foreach ($items as $item) {
$product = $item->getProduct();
$productIds[] = $product->getId();
}
}
return $this->arrayToCommaSeparatedStringValues($productIds);
}
public function getValue()
{
$order = $this->fbeHelper->getObject(\Magento\Checkout\Model\Session::class)->getLastRealOrder();
/** @var Order $order */
if ($order) {
$subtotal = $order->getSubTotal();
if ($subtotal) {
$priceHelper = $this->fbeHelper->getObject(\Magento\Framework\Pricing\Helper\Data::class);
return $priceHelper->currency($subtotal, false, false);
}
} else {
return null;
}
}
public function getContents()
{
$contents = [];
$order = $this->fbeHelper->getObject(\Magento\Checkout\Model\Session::class)->getLastRealOrder();
/** @var Order $order */
if ($order) {
$priceHelper = $this->objectManager->get(\Magento\Framework\Pricing\Helper\Data::class);
$items = $order->getItemsCollection();
foreach ($items as $item) {
/** @var Product $product */
// @todo reuse results from self::getContentIDs()
$product = $item->getProduct();
$price = $priceHelper->currency($product->getFinalPrice(), false, false);
$content = '{id:"' . $product->getId() . '",quantity:' . (int)$item->getQtyOrdered()
. ',item_price:' . $price . '}';
$contents[] = $content;
}
}
return implode(',', $contents);
}
/**
* @return string
*/
public function getEventToObserveName()
{
return 'facebook_businessextension_ssapi_purchase';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
class Search extends Common
{
/**
* @return string
*/
public function getSearchQuery()
{
return htmlspecialchars(
$this->getRequest()->getParam('q'),
ENT_QUOTES,
'UTF-8'
);
}
/**
* @return string
*/
public function getEventToObserveName()
{
return 'facebook_businessextension_ssapi_search';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
class ViewCategory extends Common
{
/**
* @return string|null
*/
public function getCategory()
{
$category = $this->registry->registry('current_category');
if ($category) {
return $this->escapeQuotes($category->getName());
} else {
return null;
}
}
/**
* @return string
*/
public function getEventToObserveName()
{
return 'facebook_businessextension_ssapi_view_category';
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Block\Pixel;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
class ViewContent extends Common
{
/**
* @return string
*/
public function getContentIDs()
{
$product_ids = [];
$product = $this->registry->registry('current_product');
if ($product && $product->getId()) {
$product_ids[] = $product->getId();
}
return $this->arrayToCommaSeparatedStringValues($product_ids);
}
/**
* @return string|null
*/
public function getContentName()
{
$product = $this->registry->registry('current_product');
if ($product && $product->getId()) {
return $this->escapeQuotes($product->getName());
} else {
return null;
}
}
/**
* @return string
*/
public function getContentType()
{
$product = $this->registry->registry('current_product');
return ($product->getTypeId() == Configurable::TYPE_CODE) ? 'product_group' : 'product';
}
/**
* @return string|null
*/
public function getContentCategory()
{
$product = $this->registry->registry('current_product');
$categoryIds = $product->getCategoryIds();
if (count($categoryIds) > 0) {
$categoryNames = [];
$categoryModel = $this->fbeHelper->getObject(\Magento\Catalog\Model\Category::class);
foreach ($categoryIds as $category_id) {
// @todo do not load category model in loop - this can be a performance killer, use category collection
$category = $categoryModel->load($category_id);
$categoryNames[] = $category->getName();
}
return $this->escapeQuotes(implode(',', $categoryNames));
} else {
return null;
}
}
public function getValue()
{
$product = $this->registry->registry('current_product');
if ($product && $product->getId()) {
$price = $product->getFinalPrice();
$priceHelper = $this->fbeHelper->getObject(\Magento\Framework\Pricing\Helper\Data::class);
return $priceHelper->currency($price, false, false);
} else {
return null;
}
}
/**
* @return string
*/
public function getEventToObserveName()
{
return 'facebook_businessextension_ssapi_view_content';
}
}
# Code of Conduct
Facebook has adopted a Code of Conduct that we expect project participants to adhere to.
Please read the [full text](https://code.fb.com/codeofconduct/)
so that you can understand what actions will and will not be tolerated.
# Contributing to Facebook Business Extension For Magento2
We want to make contributing to this project as easy and transparent as
possible.
## Pull Requests
We actively welcome your pull requests.
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests.
3. If you've changed APIs, update the documentation.
4. Make sure your code lints.
5. If you haven't already, complete the Contributor License Agreement ("CLA").
## Contributor License Agreement ("CLA")
In order to accept your pull request, we need you to submit a CLA. You only need
to do this once to work on any of Facebook's open source projects.
Complete your CLA here: <https://code.facebook.com/cla>
## Issues
We use GitHub issues to track public bugs. Please ensure your description is
clear and has sufficient instructions to be able to reproduce the issue.
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
disclosure of security bugs. In those cases, please go through the process
outlined on that page and do not file a public issue.
## Coding Style
* 4 spaces for indentation rather than tabs
* 80 character line length
## License
By contributing to Facebook Business Extension For Magento2, you agree that your contributions
will be licensed under the LICENSE file in the root directory of
this source tree.
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Magento\Security\Model\AdminSessionsManager;
abstract class AbstractAjax extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Framework\Controller\Result\JsonFactory
*/
protected $_resultJsonFactory;
protected $_fbeHelper;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context);
$this->_resultJsonFactory = $resultJsonFactory;
$this->_fbeHelper = $fbeHelper;
}
abstract protected function executeForJson();
public function execute()
{
$result = $this->_resultJsonFactory->create();
// TODO : Move all String objects to constants.
$admin_session = $this->_fbeHelper
->createObject(AdminSessionsManager::class)
->getCurrentSession();
if (!$admin_session && $admin_session->getStatus() != 1) {
throw new \Exception('Oops, this endpoint is for logged in admin and ajax only!');
} else {
try {
$json = $this->executeForJson();
return $result->setData($json);
} catch (\Exception $e) {
// Uncomment once the logger is added
// $this->_fbeHelper->logException($e);
throw new Exception(
'Oops, there was error while processing your request.' .
' Please contact admin for more details.'
);
}
}
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Exception;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Feed\CategoryCollection;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
class CategoryUpload extends AbstractAjax
{
/**
* @var CategoryCollection
*/
protected $categoryCollection;
public function __construct(
Context $context,
JsonFactory $resultJsonFactory,
FBEHelper $fbeHelper,
CategoryCollection $categoryCollection
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
$this->categoryCollection = $categoryCollection;
}
public function executeForJson()
{
$response = [];
if (!$this->_fbeHelper->getAccessToken()) {
$response['success'] = false;
$response['message'] = __('Set up the extension before uploading category.');
return $response;
}
try {
$feedPushResponse = $this->categoryCollection->pushAllCategoriesToFbCollections();
$response['success'] = true;
$response['feed_push_response'] = $feedPushResponse;
} catch (Exception $e) {
$response['success'] = false;
$response['message'] = $e->getMessage();
}
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
class Fbaamsettings extends AbstractAjax
{
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
}
public function executeForJson()
{
$response = [
'success' => false,
'settings' => null,
];
$pixelId = $this->getRequest()->getParam('pixelId');
if ($pixelId) {
$settingsAsString = $this->_fbeHelper->fetchAndSaveAAMSettings($pixelId);
if ($settingsAsString) {
$response['success'] = true;
$response['settings'] = $settingsAsString;
}
}
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Facebook\BusinessExtension\Model\Feed\CategoryCollection;
class Fbcategorypush extends AbstractAjax
{
private $_customerSession;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $helper,
\Magento\Customer\Model\Session $customerSession
) {
parent::__construct($context, $resultJsonFactory, $helper);
$this->_customerSession = $customerSession;
}
public function executeForJson()
{
$response = [];
try {
$catalog_id = $this->getRequest()->getParam('catalogId');
$category_obj = $this->_fbeHelper->getObject(CategoryCollection::class);
$category_obj->saveCatalogId($catalog_id);
$category_obj->pushAllCategoriesToFbCollections();
$response['success'] = true;
return $response;
} catch (\Exception $e) {
$response['success'] = false;
$response['message'] = $e->getMessage();
$this->_fbeHelper->logException($e);
return $response;
}
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
class Fbdeleteasset extends AbstractAjax
{
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
}
public function executeForJson()
{
return $this->_fbeHelper->deleteConfigKeys();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Facebook\BusinessExtension\Model\Product\Feed\Method\BatchApi;
class Fbfeedpush extends AbstractAjax
{
/**
* @var BatchApi
*/
protected $batchApi;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $helper,
BatchApi $batchApi
) {
parent::__construct($context, $resultJsonFactory, $helper);
$this->batchApi = $batchApi;
}
public function executeForJson()
{
$response = [];
$external_business_id = $this->_fbeHelper->getConfigValue('fbe/external/id');
$this->_fbeHelper->log("Existing external business id --- ". $external_business_id);
if ($external_business_id) {
$response['success'] = false;
$response['message'] = 'One time feed push is completed at the time of setup';
return $response;
}
try {
/* even the rest code failed, we should store external business id and catalog id,
because user can push feed sync button in configuration*/
$access_token = $this->getRequest()->getParam('accessToken');
$external_business_id = $this->getRequest()->getParam('externalBusinessId');
$this->saveExternalBusinessId($external_business_id);
$catalog_id = $this->getRequest()->getParam('catalogId');
$this->saveCatalogId($catalog_id);
if ($access_token) {
$feed_push_response = $this->batchApi->generateProductRequestData($access_token);
$response['success'] = true;
$response['feed_push_response'] = $feed_push_response;
return $response;
}
} catch (\Exception $e) {
$response['success'] = false;
$response['message'] = $e->getMessage();
$this->_fbeHelper->logException($e);
return $response;
}
}
public function saveCatalogId($catalog_id)
{
if ($catalog_id != null) {
$this->_fbeHelper->saveConfig('fbe/catalog/id', $catalog_id);
$this->_fbeHelper->log("Catalog id saved on instance --- ". $catalog_id);
}
}
public function saveExternalBusinessId($external_business_id)
{
if ($external_business_id != null) {
$this->_fbeHelper->saveConfig('fbe/external/id', $external_business_id);
$this->_fbeHelper->log("External business id saved on instance --- ". $external_business_id);
}
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Magento\Framework\Stdlib\DateTime\DateTime;
class Fbpixel extends AbstractAjax
{
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
}
// Yet to verify how to use the pii info, hence have commented the part of code.
public function executeForJson()
{
$old_pixel_id = $this->_fbeHelper->getConfigValue('fbpixel/id');
$response = [
'success' => false,
'pixelId' => $old_pixel_id
//'pixelUsePii' => $this->_fbeHelper->getConfigValue('fbpixel/pixel_use_pii')
];
$pixel_id = $this->getRequest()->getParam('pixelId');
//$pixel_use_pii = $this->getRequest()->getParam('pixelUsePii');
if ($pixel_id && $this->_fbeHelper->isValidFBID($pixel_id)) {
$this->_fbeHelper->saveConfig('fbpixel/id', $pixel_id);
$this->_fbeHelper->saveConfig('fbe/installed', true);
// $this->_fbeHelper->saveConfig('fbpixel/pixel_use_pii', $pixel_use_pii === 'true'? '1' : '0');
$response['success'] = true;
$response['pixelId'] = $pixel_id;
// $response['pixelUsePii'] = $pixel_use_pii;
if ($old_pixel_id != $pixel_id) {
$this->_fbeHelper->log(sprintf("Pixel id updated from %d to %d", $old_pixel_id, $pixel_id));
$datetime = $this->_fbeHelper->createObject(DateTime::class);
$this->_fbeHelper->saveConfig(
'fbpixel/install_time',
$datetime->gmtDate('Y-m-d H:i:s')
);
}
}
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Magento\Framework\Stdlib\DateTime\DateTime;
class Fbprofiles extends AbstractAjax
{
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
}
public function executeForJson()
{
$old_profiles = $this->_fbeHelper->getConfigValue('fbprofile/ids');
$response = [
'success' => false,
'profiles' => $old_profiles
];
$profiles = $this->getRequest()->getParam('profiles');
if ($profiles) {
$this->_fbeHelper->saveConfig('fbprofile/ids', $profiles);
$response['success'] = true;
$response['profiles'] = $profiles;
if ($old_profiles != $profiles) {
$datetime = $this->_fbeHelper->createObject(DateTime::class);
$this->_fbeHelper->saveConfig(
'fbprofiles/creation_time',
$datetime->gmtDate('Y-m-d H:i:s')
);
}
}
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Magento\Framework\Stdlib\DateTime\DateTime;
class Fbtoken extends AbstractAjax
{
// phpcs:disable Generic.CodeAnalysis.UselessOverridingMethod
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
}
public function executeForJson()
{
$old_access_token = $this->_fbeHelper->getConfigValue('fbaccess/token');
$response = [
'success' => false,
'accessToken' => $old_access_token
];
$access_token = $this->getRequest()->getParam('accessToken');
if ($access_token) {
$this->_fbeHelper->saveConfig('fbaccess/token', $access_token);
$response['success'] = true;
$response['accessToken'] = $access_token;
if ($old_access_token != $access_token) {
$this->_fbeHelper->log("Updated Access token...");
$datetime = $this->_fbeHelper->createObject(DateTime::class);
$this->_fbeHelper->saveConfig(
'fbaccesstoken/creation_time',
$datetime->gmtDate('Y-m-d H:i:s')
);
}
}
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Ajax;
use Exception;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\Uploader;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
class ProductFeedUpload extends AbstractAjax
{
/**
* @var Uploader
*/
protected $uploader;
public function __construct(
Context $context,
JsonFactory $resultJsonFactory,
FBEHelper $fbeHelper,
Uploader $uploader
) {
parent::__construct($context, $resultJsonFactory, $fbeHelper);
$this->uploader = $uploader;
}
public function executeForJson()
{
$response = [];
if (!$this->_fbeHelper->getAccessToken()) {
$response['success'] = false;
$response['message'] = __('Set up the extension before uploading products.');
return $response;
}
try {
$feedPushResponse = $this->uploader->uploadFullCatalog();
$response['success'] = true;
$response['feed_push_response'] = $feedPushResponse;
} catch (Exception $e) {
$response['success'] = false;
$response['message'] = $e->getMessage();
}
return $response;
}
}
<?php
namespace Facebook\BusinessExtension\Controller\Adminhtml\Info;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
/**
* Class Index
*/
class Index extends \Magento\Backend\App\Action
{
/**
* @var PageFactory
*/
protected $resultPageFactory;
/**
* Index constructor.
*
* @param Context $context
* @param PageFactory $resultPageFactory
*/
public function __construct(
Context $context,
PageFactory $resultPageFactory
) {
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}
/**
* Load the page defined in view/adminhtml/layout/exampleadminnewpage_helloworld_index.xml
*
* @return Page
*/
public function execute()
{
$resultPage = $this->resultPageFactory->create();
$resultPage->getConfig()->getTitle()->prepend(__('Info'));
return $resultPage;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Adminhtml\Setup;
use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
class Index extends \Magento\Backend\App\Action
{
/**
* @var PageFactory
*/
protected $resultPageFactory;
/**
* Constructor
*
* @param Context $context
* @param PageFactory $resultPageFactory
*/
public function __construct(
Context $context,
PageFactory $resultPageFactory
) {
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
}
/**
* Load the page defined in view/adminhtml/layout/fbeadmin_setup_index.xml
*
* @return Page
*/
public function execute()
{
return $resultPage = $this->resultPageFactory->create();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Controller\Pixel;
use Facebook\BusinessExtension\Helper\EventIdGenerator;
use Facebook\BusinessExtension\Helper\FBEHelper;
class ProductInfoForAddToCart extends \Magento\Framework\App\Action\Action
{
protected $_resultJsonFactory;
protected $_productFactory;
protected $_fbeHelper;
protected $_formKeyValidator;
protected $_magentoDataHelper;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
\Magento\Catalog\Model\ProductFactory $productFactory,
FBEHelper $helper,
\Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
\Facebook\BusinessExtension\Helper\MagentoDataHelper $magentoDataHelper
) {
parent::__construct($context);
$this->_resultJsonFactory = $resultJsonFactory;
$this->_productFactory = $productFactory;
$this->_fbeHelper = $helper;
$this->_formKeyValidator = $formKeyValidator;
$this->_magentoDataHelper = $magentoDataHelper;
}
private function getCategory($product)
{
$category_ids = $product->getCategoryIds();
if (count($category_ids) > 0) {
$category_names = [];
$category_model = $this->_fbeHelper->getObject(\Magento\Catalog\Model\Category::class);
foreach ($category_ids as $category_id) {
$category = $category_model->load($category_id);
$category_names[] = $category->getName();
}
return addslashes(implode(',', $category_names));
} else {
return null;
}
}
private function getValue($product)
{
if ($product && $product->getId()) {
$price = $product->getFinalPrice();
$price_helper = $this->_fbeHelper->getObject(\Magento\Framework\Pricing\Helper\Data::class);
return $price_helper->currency($price, false, false);
} else {
return null;
}
}
private function getProductInfo($product_sku)
{
$response_data = [];
$product = $this->_magentoDataHelper->getProductWithSku($product_sku);
if ($product->getId()) {
$response_data['id'] = $product->getId();
$response_data['name'] = $product->getName();
$response_data['category'] = $this->getCategory($product);
$response_data['value'] = $this->getValue($product);
}
return $response_data;
}
public function execute()
{
$product_sku = $this->getRequest()->getParam('product_sku', null);
if ($this->_formKeyValidator->validate($this->getRequest()) && $product_sku) {
$response_data = $this->getProductInfo($product_sku);
// If the sku is valid
// The event id is added in the response
// And a CAPI event is created
if (count($response_data) > 0) {
$event_id = EventIdGenerator::guidv4();
$response_data['event_id'] = $event_id;
$this->trackServerEvent($event_id);
$result = $this->_resultJsonFactory->create();
$result->setData(array_filter($response_data));
return $result;
}
} else {
$this->_redirect('noroute');
}
}
public function trackServerEvent($eventId)
{
$this->_eventManager->dispatch(
'facebook_businessextension_ssapi_add_to_cart',
['eventId' => $eventId]
);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Cron;
class AAMSettingsCron
{
/**
* @var \Facebook\BusinessExtension\Helper\FBEHelper
*/
protected $fbeHelper;
/**
* AAMSettingsCron constructor
*
* @param \Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
*/
public function __construct(
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
) {
$this->fbeHelper = $fbeHelper;
}
public function execute()
{
$pixelId = $this->fbeHelper->getPixelID();
$settingsAsString = null;
if ($pixelId) {
$settingsAsString = $this->fbeHelper->fetchAndSaveAAMSettings($pixelId);
if (!$settingsAsString) {
$this->fbeHelper->log('Error saving settings. Currently:', $settingsAsString);
}
}
return $settingsAsString;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Cron;
use Facebook\BusinessExtension\Model\Feed\CategoryCollection;
use Facebook\BusinessExtension\Model\System\Config as SystemConfig;
class CategorySyncCron
{
/**
* @var \Facebook\BusinessExtension\Helper\FBEHelper
*/
protected $fbeHelper;
/**
* @var CategoryCollection
*/
protected $categoryCollection;
/**
* @var SystemConfig
*/
protected $systemConfig;
/**
* CategorySyncCron constructor
*
* @param \Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper
* @param CategoryCollection $categoryCollection
* @param SystemConfig $systemConfig
*/
public function __construct(
\Facebook\BusinessExtension\Helper\FBEHelper $fbeHelper,
CategoryCollection $categoryCollection,
SystemConfig $systemConfig
) {
$this->fbeHelper = $fbeHelper;
$this->categoryCollection = $categoryCollection;
$this->systemConfig = $systemConfig;
}
public function execute()
{
if ($this->systemConfig->isActiveCatalogSync() == true) {
$this->categoryCollection->pushAllCategoriesToFbCollections();
return true;
}
return false;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
use FacebookAds\Object\ServerSide\Normalizer;
use FacebookAds\Object\ServerSide\Util;
/**
* Helper to extract and filter aam fields
*/
class AAMFieldsExtractorHelper
{
/**
* @var MagentoDataHelper
*/
protected $magentoDataHelper;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* Constructor
* @param MagentoDataHelper $magentoDataHelper
* @param FBEHelper $fbeHelper
*/
public function __construct(
MagentoDataHelper $magentoDataHelper,
FBEHelper $fbeHelper
) {
$this->magentoDataHelper = $magentoDataHelper;
$this->fbeHelper = $fbeHelper;
}
/**
* Filters user data according to AAM settings and normalizes the fields
* Reads user data from session when no user data was passed
* @param string[] $userDataArray
* @return string[]
*/
public function getNormalizedUserData($userDataArray = null)
{
if (!$userDataArray) {
$userDataArray = $this->magentoDataHelper->getUserDataFromSession();
}
$aamSettings = $this->fbeHelper->getAAMSettings();
if (!$userDataArray || !$aamSettings || !$aamSettings->getEnableAutomaticMatching()) {
return null;
}
//Removing fields not enabled in AAM settings
foreach ($userDataArray as $key => $value) {
if (!in_array($key, $aamSettings->getEnabledAutomaticMatchingFields())) {
unset($userDataArray[$key]);
}
}
// Normalizing gender and date of birth
// According to https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching
if (array_key_exists(AAMSettingsFields::GENDER, $userDataArray)
&& !empty($userDataArray[AAMSettingsFields::GENDER])
) {
$userDataArray[AAMSettingsFields::GENDER] = $userDataArray[AAMSettingsFields::GENDER][0];
}
if (array_key_exists(AAMSettingsFields::DATE_OF_BIRTH, $userDataArray)
) {
// strtotime() and date() return false for invalid parameters
$unixTimestamp = strtotime($userDataArray[AAMSettingsFields::DATE_OF_BIRTH]);
if (!$unixTimestamp) {
unset($userDataArray[AAMSettingsFields::DATE_OF_BIRTH]);
} else {
$formattedDate = date("Ymd", $unixTimestamp);
if (!$formattedDate) {
unset($userDataArray[AAMSettingsFields::DATE_OF_BIRTH]);
} else {
$userDataArray[AAMSettingsFields::DATE_OF_BIRTH] = $formattedDate;
}
}
}
// Given that the format of advanced matching fields is the same in
// the Pixel and the Conversions API,
// we can use the business sdk for normalization
// Compare the documentation:
// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters/customer-information-parameters
// https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching
foreach ($userDataArray as $field => $data) {
try {
$normalizedValue = Normalizer::normalize($field, $data);
$userDataArray[$field] = $normalizedValue;
} catch (\Exception $e) {
unset($userDataArray[$field]);
}
}
return $userDataArray;
}
/**
* @param $event
* @param null $userDataArray
* @return mixed
*/
public function setUserData($event, $userDataArray = null)
{
$userDataArray = self::getNormalizedUserData($userDataArray);
if (empty($userDataArray)) {
return $event;
}
$userData = $event->getUserData();
if (array_key_exists(AAMSettingsFields::EMAIL, $userDataArray)
) {
$userData->setEmail(
$userDataArray[AAMSettingsFields::EMAIL]
);
}
if (array_key_exists(AAMSettingsFields::FIRST_NAME, $userDataArray)
) {
$userData->setFirstName(
$userDataArray[AAMSettingsFields::FIRST_NAME]
);
}
if (array_key_exists(AAMSettingsFields::LAST_NAME, $userDataArray)
) {
$userData->setLastName(
$userDataArray[AAMSettingsFields::LAST_NAME]
);
}
if (array_key_exists(AAMSettingsFields::GENDER, $userDataArray)
) {
$userData->setGender(
$userDataArray[AAMSettingsFields::GENDER]
);
}
if (array_key_exists(AAMSettingsFields::DATE_OF_BIRTH, $userDataArray)
) {
$userData->setDateOfBirth($userDataArray[AAMSettingsFields::DATE_OF_BIRTH]);
}
if (array_key_exists(AAMSettingsFields::EXTERNAL_ID, $userDataArray)
) {
$userData->setExternalId(
Util::hash($userDataArray[AAMSettingsFields::EXTERNAL_ID])
);
}
if (array_key_exists(AAMSettingsFields::PHONE, $userDataArray)
) {
$userData->setPhone(
$userDataArray[AAMSettingsFields::PHONE]
);
}
if (array_key_exists(AAMSettingsFields::CITY, $userDataArray)
) {
$userData->setCity(
$userDataArray[AAMSettingsFields::CITY]
);
}
if (array_key_exists(AAMSettingsFields::STATE, $userDataArray)
) {
$userData->setState(
$userDataArray[AAMSettingsFields::STATE]
);
}
if (array_key_exists(AAMSettingsFields::ZIP_CODE, $userDataArray)
) {
$userData->setZipCode(
$userDataArray[AAMSettingsFields::ZIP_CODE]
);
}
if (array_key_exists(AAMSettingsFields::COUNTRY, $userDataArray)
) {
$userData->setCountryCode(
$userDataArray[AAMSettingsFields::COUNTRY]
);
}
return $event;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
/**
* Class that contains the keys used to identify each field in AAMSettings
*/
abstract class AAMSettingsFields
{
const EMAIL = 'em';
const FIRST_NAME = 'fn';
const LAST_NAME = 'ln';
const GENDER = 'ge';
const PHONE = 'ph';
const CITY = 'ct';
const STATE = 'st';
const ZIP_CODE = 'zp';
const DATE_OF_BIRTH = 'db';
const COUNTRY = 'country';
const EXTERNAL_ID = 'external_id';
/**
* @return array
*/
public static function getAllFields()
{
return [
self::EMAIL,
self::FIRST_NAME,
self::LAST_NAME,
self::GENDER,
self::PHONE,
self::CITY,
self::STATE,
self::ZIP_CODE,
self::DATE_OF_BIRTH,
self::COUNTRY,
self::EXTERNAL_ID,
];
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
class EventIdGenerator
{
/**
* @return string A 36 character string containing dashes.
*/
public static function guidv4()
{
$data = openssl_random_pseudo_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
use Zend\Http\Headers;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Http\Client;
/**
* Helper class to handle api request.
*/
class HttpClient
{
/**
* @var FBEHelper
*/
private $fbeHelper;
/**
* Constructor
* @param FBEHelper $helper
*/
public function __construct(
FBEHelper $helper
) {
$this->fbeHelper = $helper;
}
/**
* @param string $uri
* the curl does not support delete api call, so have to use this low level lib
* https://devdocs.magento.com/guides/v2.3/get-started/gs-web-api-request.html
* @return string|null
*/
public function makeDeleteHttpCall(string $uri)
{
$httpHeaders = new Headers();
$httpHeaders->addHeaders([
'Accept' => 'application/json',
]);
$request = new Request();
$request->setHeaders($httpHeaders);
$request->setUri($uri);
$request->setMethod(Request::METHOD_DELETE);
$client = new Client();
$res = $client->send($request);
$response = Response::fromString($res);
$this->fbeHelper->log("response:", $response);
return $response->getBody();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
/**
* Helper class for generating and organizing log files.
*/
namespace Facebook\BusinessExtension\Helper;
class LogOrganization
{
// 4096 -- Good balance for tracking backwards
const BUFFER = 4096;
static $criticalLines = array();
public static function organizeLogs() {
$arrayOfFiles = array("var/log/debug.log", "var/log/cron.log", "var/log/magento.cron.log", "var/log/system.log");
$countCrit = 0;
foreach($arrayOfFiles as $value) {
if (!file_exists($value)) {
continue;
}
$fp = fopen($value, 'r');
$pos = -2; // Skip final new line character (Set to -1 if not present)
$currentLine = '';
while (-1 !== fseek($fp, $pos, SEEK_END)) {
$char = fgetc($fp);
if ("\n" == $char) {
if (substr($currentLine, 0, 3) == "[20") {
$time = strtotime(substr($currentLine, 1, 20));
if ($time > strtotime('-7 day')) {
break;
}
// Saving only critical log entries with "Facebook" phrase
if (strpos($currentLine, "CRITICAL") !== false &&
strpos($currentLine, "Facebook") !== false) {
self::$criticalLines[] = $currentLine;
$countCrit++;
}
$currentLine = '';
if ($countCrit == 500) {
break;
}
}
} else {
$currentLine = $char . $currentLine;
}
$pos--;
}
if (substr($currentLine, 0, 3) == "[20") {
$time = strtotime(substr($currentLine, 1, 20));
if ($time > strtotime('-7 day')) {
break;
}
if (strpos($currentLine, "CRITICAL") !== false &&
strpos($currentLine, "Facebook") !== false) {
self::$criticalLines[] = $currentLine;
$countCrit++;
}
$currentLine = '';
}
$countCrit = 0;
}
fclose($fp);
$amuLogs = self::tailCustom("var/log/facebook-business-extension.log", 100);
$amuLogsArr = explode("\n", $amuLogs);
self::$criticalLines = array_merge(self::$criticalLines, $amuLogsArr);
usort(self::$criticalLines, function ($x, $y) {
$t1 = strtotime(substr($x, 1, 19));
$t2 = strtotime(substr($y, 1, 19));
return ($t1 - $t2);
});
return self::$criticalLines;
}
public static function tailCustom($filepath, $lines) {
$f = fopen($filepath, "rb");
if ($f === false) {
return false;
}
fseek($f, -1, SEEK_END);
if (fread($f, 1) != "\n") {
$lines -= 1;
}
$output = '';
$chunk = '';
while (ftell($f) > 0 && $lines >= 0) {
$seek = min(ftell($f), self::BUFFER);
fseek($f, -$seek, SEEK_CUR);
$output = ($chunk = fread($f, $seek)) . $output;
fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
$lines -= substr_count($chunk, "\n");
}
while ($lines++ < 0) {
$output = substr($output, strpos($output, "\n") + 1);
}
fclose($f);
return trim($output);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\EventRequest;
use FacebookAds\Object\ServerSide\UserData;
use FacebookAds\Object\ServerSide\CustomData;
use FacebookAds\Object\ServerSide\Content;
use FacebookAds\Object\ServerSide\Util;
/**
* Factory class for generating new ServerSideAPI events with default parameters.
*/
class ServerEventFactory
{
/**
* @param $eventName
* @param null $eventId
* @return mixed
*/
public static function newEvent($eventName, $eventId = null)
{
// Capture default user-data parameters passed down from the client browser.
$userData = (new UserData())
->setClientIpAddress(self::getIpAddress())
->setClientUserAgent(Util::getHttpUserAgent())
->setFbp(Util::getFbp())
->setFbc(Util::getFbc());
$event = (new Event())
->setEventName($eventName)
->setEventTime(time())
->setEventSourceUrl(Util::getRequestUri())
->setActionSource('website')
->setUserData($userData)
->setCustomData(new CustomData());
if ($eventId == null) {
$event->setEventId(EventIdGenerator::guidv4());
} else {
$event->setEventId($eventId);
}
return $event;
}
/**
* Get the IP address from the $_SERVER variable
*
* @return string|null
*/
private static function getIpAddress()
{
$HEADERS_TO_SCAN = [
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR'
];
foreach ($HEADERS_TO_SCAN as $header) {
if (array_key_exists($header, $_SERVER)) {
$ipList = explode(',', $_SERVER[$header]);
foreach ($ipList as $ip) {
$trimmedIp = trim($ip);
if (self::isValidIpAddress($trimmedIp)) {
return $trimmedIp;
}
}
}
}
return null;
}
/**
* Check if the given ip address is valid
*
* @param $ipAddress
* @return mixed
*/
private static function isValidIpAddress($ipAddress)
{
return filter_var(
$ipAddress,
FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4
| FILTER_FLAG_IPV6
| FILTER_FLAG_NO_PRIV_RANGE
| FILTER_FLAG_NO_RES_RANGE
);
}
/**
* Fill customData member of $event with array $data
*
* @param $event
* @param $data
* @return mixed
*/
private static function addCustomData($event, $data)
{
$custom_data = $event->getCustomData();
if (!empty($data['currency'])) {
$custom_data->setCurrency($data['currency']);
}
if (!empty($data['value'])) {
$custom_data->setValue($data['value']);
}
if (!empty($data['content_ids'])) {
$custom_data->setContentIds($data['content_ids']);
}
if (!empty($data['content_type'])) {
$custom_data->setContentType($data['content_type']);
}
if (!empty($data['content_name'])) {
$custom_data->setContentName($data['content_name']);
}
if (!empty($data['content_category'])) {
$custom_data->setContentCategory($data['content_category']);
}
if (!empty($data['search_string'])) {
$custom_data->setSearchString($data['search_string']);
}
if (!empty($data['num_items'])) {
$custom_data->setNumItems($data['num_items']);
}
if (!empty($data['contents'])) {
$contents = [];
foreach ($data['contents'] as $content) {
$contents[] = new Content($content);
}
$custom_data->setContents($contents);
}
if (!empty($data['order_id'])) {
$custom_data->setOrderId($data['order_id']);
}
return $event;
}
/**
* Create a server side event
*
* @param $eventName
* @param $data
* @param null $eventId
* @return mixed
*/
public static function createEvent($eventName, $data, $eventId = null)
{
$event = self::newEvent($eventName, $eventId);
$event = self::addCustomData($event, $data);
return $event;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Helper;
use FacebookAds\Api;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\EventRequestAsync;
use FacebookAds\Exception\Exception;
use GuzzleHttp\Exception\RequestException;
/**
* Helper to fire ServerSide Event.
*/
class ServerSideHelper
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var AAMFieldsExtractorHelper
*/
protected $aamFieldsExtractorHelper;
/**
* @var array
*/
protected $trackedEvents = [];
/**
* Constructor
*
* @param FBEHelper $fbeHelper
* @param AAMFieldsExtractorHelper $aamFieldsExtractorHelper
*/
public function __construct(
FBEHelper $fbeHelper,
AAMFieldsExtractorHelper $aamFieldsExtractorHelper
) {
$this->fbeHelper = $fbeHelper;
$this->aamFieldsExtractorHelper = $aamFieldsExtractorHelper;
}
/**
* @param $event
* @param null $userDataArray
*/
public function sendEvent($event, $userDataArray = null)
{
try {
$api = Api::init(null, null, $this->fbeHelper->getAccessToken());
$event = $this->aamFieldsExtractorHelper->setUserData($event, $userDataArray);
$this->trackedEvents[] = $event;
$events = [];
array_push($events, $event);
$request = (new EventRequestAsync($this->fbeHelper->getPixelID()))
->setEvents($events)
->setPartnerAgent($this->fbeHelper->getPartnerAgent());
$this->fbeHelper->log('Sending event ' . $event->getEventId());
$request->execute()
->then(
null,
function (RequestException $e) {
$this->fbeHelper->log("RequestException: " . $e->getMessage());
}
);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
}
/**
* @return array
*/
public function getTrackedEvents()
{
return $this->trackedEvents;
}
}
Copyright (c) 2004-present, Facebook, Inc. All rights reserved.
You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
copy, modify, and distribute this software in source code or binary form for use
in connection with the web services and APIs provided by Facebook.
As with any software that integrates with the Facebook platform, your use of
this software is subject to the Facebook Platform Policy
[http://developers.facebook.com/policy/]. This copyright notice shall be
included in all copies or substantial portions of the software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Logger;
use Monolog\Logger;
class Handler extends \Magento\Framework\Logger\Handler\Base
{
/**
* Logging level
* @var int
*/
protected $loggerType = Logger::INFO;
/**
* File name
* @var string
*/
protected $fileName = '/var/log/facebook-business-extension.log';
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Logger;
use Magento\Framework\ObjectManagerInterface;
class Logger extends \Monolog\Logger
{
/**
* Logger constructor
*
* @param ObjectManagerInterface $objectManager
*/
public function __construct(
ObjectManagerInterface $objectManager
) {
$handler = $objectManager->create(Handler::class);
parent::__construct('FBE', [$handler]);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\Model\AbstractModel;
class Config extends AbstractModel implements IdentityInterface
{
const CACHE_TAG = 'facebook_business_extension';
protected function _construct()
{
$this->_init('Facebook\BusinessExtension\Model\ResourceModel\Config');
}
/**
* @return array
*/
public function getIdentities()
{
return [self::CACHE_TAG . '_' . $this->getConfigKey()];
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Config\Source\Product;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
class AgeGroup extends AbstractSource
{
/**
* Get all options
*
* @return array
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['value' => '', 'label' => __('Please Select')],
['value' => 'adult', 'label' => __('adult')],
['value' => 'all ages', 'label' => __('all ages')],
['value' => 'teen', 'label' => __('teen')],
['value' => 'kids', 'label' => __('kids')],
['value' => 'toddler', 'label' => __('toddler')],
['value' => 'infant', 'label' => __('infant')],
['value' => 'newborn', 'label' => __('newborn')],
];
}
return $this->_options;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Config\Source\Product;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
class Assembly extends AbstractSource
{
/**
* Get all options
*
* @return array
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['value' => '', 'label' => __('Please Select')],
['value' => 'yes', 'label' => __('Yes')],
['value' => 'no', 'label' => __('No')],
];
}
return $this->_options;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Config\Source\Product;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
class DecorStyle extends AbstractSource
{
/**
* Get all options
*
* @return array
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['value' => '', 'label' => __('Please Select')],
['value' => 'Bohemian', 'label' => __('Bohemian')],
['value' => 'Contemporary', 'label' => __('Contemporary')],
['value' => 'Industrial', 'label' => __('Industrial')],
['value' => 'Mid-Century', 'label' => __('Mid-Century')],
['value' => 'Modern', 'label' => __('Modern')],
['value' => 'Rustic', 'label' => __('Rustic')],
['value' => 'Vintage', 'label' => __('Vintage')],
];
}
return $this->_options;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Config\Source\Product;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
class Gender extends AbstractSource
{
/**
* Get all options
*
* @return array
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['value' => '', 'label' => __('Please Select')],
['value' => 'Male', 'label' => __('Male')],
['value' => 'Female', 'label' => __('Female')],
['value' => 'Unisex', 'label' => __('Unisex')],
];
}
return $this->_options;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Config\Source\Product;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
class Pattern extends AbstractSource
{
/**
* Get all options
*
* @return array
*/
public function getAllOptions()
{
if ($this->_options === null) {
$this->_options = [
['value' => '', 'label' => __('Please Select')],
['value' => 'Plaid', 'label' => __('Plaid')],
['value' => 'Polka', 'label' => __('Polka')],
['value' => 'Dot', 'label' => __('Dot')],
['value' => 'Gingham', 'label' => __('Gingham')],
['value' => 'Chevron', 'label' => __('Chevron')],
];
}
return $this->_options;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Feed;
use Facebook\BusinessExtension\Model\Config\ProductAttributes;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Magento\Catalog\Model\Product;
class EnhancedCatalogHelper
{
/**
* @var FBEHelper
*/
private $fbeHelper;
/**
* @var ProductAttributes
*/
private $attributeConfig;
/**
* EnhancedCatalogHelper constructor
*
* @param FBEHelper $fbeHelper
* @param ProductAttributes $attributeConfig
*/
public function __construct(FBEHelper $fbeHelper, ProductAttributes $attributeConfig)
{
$this->attributeConfig = $attributeConfig;
$this->fbeHelper = $fbeHelper;
}
/**
* @param Product $product
* @param array $requests
* @return null
*/
public function assignECAttribute(Product $product, array &$requests)
{
$attrConfig = $this->attributeConfig->getAttributesConfig();
foreach ($attrConfig as $attrCode => $config) {
$data = $product->getData($attrCode);
if ($data) {
// facebook_capacity -> capacity
$trimmedAttrCode = substr($attrCode, 9);
$requests[$trimmedAttrCode] = $data;
}
}
return null;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\Builder;
use Facebook\BusinessExtension\Model\System\Config as SystemConfig;
use Magento\Catalog\Model\Product;
use Magento\CatalogInventory\Api\Data\StockItemInterface;
use Magento\CatalogInventory\Api\StockConfigurationInterface;
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
class Inventory
{
const STATUS_IN_STOCK = 'in stock';
const STATUS_OUT_OF_STOCK = 'out of stock';
const UNMANAGED_STOCK_QTY = 9999;
/**
* @var StockItemRepositoryInterface
*/
private $stockItemRepository;
/**
* @var StockItemCriteriaInterfaceFactory
*/
private $stockItemCriteriaInterfaceFactory;
/**
* @var StockConfigurationInterface
*/
private $stockConfigurationInterface;
/**
* @var Product
*/
private $product;
/**
* @var SystemConfig
*/
protected $systemConfig;
/**
* @var StockItemInterface
*/
protected $productStock;
/**
* @param StockItemRepositoryInterface $stockItemRepository
* @param StockItemCriteriaInterfaceFactory $stockItemCriteriaInterfaceFactory
* @param StockConfigurationInterface $stockConfigurationInterface
* @param SystemConfig $systemConfig
*/
public function __construct(
StockItemRepositoryInterface $stockItemRepository,
StockItemCriteriaInterfaceFactory $stockItemCriteriaInterfaceFactory,
StockConfigurationInterface $stockConfigurationInterface,
SystemConfig $systemConfig
) {
$this->stockItemRepository = $stockItemRepository;
$this->stockItemCriteriaInterfaceFactory = $stockItemCriteriaInterfaceFactory;
$this->stockConfigurationInterface = $stockConfigurationInterface;
$this->systemConfig = $systemConfig;
}
/**
* @param Product $product
* @return StockItemInterface|null
*/
public function getStockItem(Product $product)
{
$criteria = $this->stockItemCriteriaInterfaceFactory->create();
$criteria->setProductsFilter($product->getId());
$stocksItems = $this->stockItemRepository->getList($criteria)->getItems();
return array_shift($stocksItems);
}
/**
* @param Product $product
* @return $this
*/
public function initInventoryForProduct(Product $product)
{
$this->product = $product;
$this->productStock = $this->getStockItem($product);
return $this;
}
/**
* @return string
*/
public function getAvailability()
{
return $this->productStock && $this->productStock->getIsInStock()
&& ($this->getInventory() - $this->systemConfig->getOutOfStockThreshold() > 0)
? self::STATUS_IN_STOCK : self::STATUS_OUT_OF_STOCK;
}
/**
* @return int
*/
public function getInventory()
{
if (!$this->productStock) {
return 0;
}
if (!$this->productStock->getManageStock()) {
return self::UNMANAGED_STOCK_QTY; // Fake Quantity to make product available if Manage Stock is off.
}
return (int)$this->productStock->getQty();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\Builder;
use Exception;
use Magento\Framework\Currency;
use Magento\Framework\Pricing\PriceCurrencyInterface;
class Tools
{
/**
* @var PriceCurrencyInterface
*/
protected $priceCurrency;
/**
* @param PriceCurrencyInterface $priceCurrency
*/
public function __construct(PriceCurrencyInterface $priceCurrency)
{
$this->priceCurrency = $priceCurrency;
}
/**
* @param $string
* @return false|string|string[]|null
*/
public function lowercaseIfAllCaps($string)
{
// if contains lowercase, don't update string
if (!preg_match('/[a-z]/', $string)) {
if (mb_strtoupper($string, 'utf-8') === $string) {
return mb_strtolower($string, 'utf-8');
}
}
return $string;
}
/**
* @param $value
* @return string
*/
public function htmlDecode($value)
{
return strip_tags(html_entity_decode($value));
}
/**
* Return formatted price with currency code. Example: "9.99 USD"
*
* @param $price
* @return string
*/
public function formatPrice($price)
{
try {
return sprintf(
'%s %s',
$this->priceCurrency->getCurrency()->formatTxt($price, ['display' => Currency::NO_SYMBOL]),
$this->priceCurrency->getCurrency()->getCode()
);
} catch (Exception $e) {
return '';
}
}
/**
* Facebook product feed validator will throw an error
* if a local URL like https://localhost/product.html was provided
* so replacing with a dummy URL to allow for local testing
*
* @param string $url
* @return string
*/
public function replaceLocalUrlWithDummyUrl($url)
{
return str_replace('localhost', 'magento.com', $url);
}
}
<?php /** @noinspection PhpUndefinedFieldInspection */
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\Method;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\Builder;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever\Configurable as ConfigurableProductRetriever;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever\Simple as SimpleProductRetriever;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetrieverInterface;
use Magento\Catalog\Model\Product;
use Magento\Framework\Exception\LocalizedException;
class BatchApi
{
const ATTR_METHOD = 'method';
const ATTR_UPDATE = 'UPDATE';
const ATTR_DATA = 'data';
// Process only the maximum allowed by API per request
const BATCH_MAX = 4999;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ProductRetrieverInterface[]
*/
protected $productRetrievers;
/**
* @var Builder
*/
protected $builder;
/**
* @param FBEHelper $helper
* @param SimpleProductRetriever $simpleProductRetriever
* @param ConfigurableProductRetriever $configurableProductRetriever
* @param Builder $builder
*/
public function __construct(
FBEHelper $helper,
SimpleProductRetriever $simpleProductRetriever,
ConfigurableProductRetriever $configurableProductRetriever,
Builder $builder
) {
$this->fbeHelper = $helper;
$this->productRetrievers = [
$simpleProductRetriever,
$configurableProductRetriever
];
$this->builder = $builder;
}
/**
* @param Product $product
* @param string $method
* @return array
* @throws LocalizedException
*/
public function buildProductRequest(Product $product, $method = self::ATTR_UPDATE)
{
return [
self::ATTR_METHOD => $method,
self::ATTR_DATA => $this->builder->buildProductEntry($product)
];
}
/**
* @param null $accessToken
* @return array
* @throws \Exception
*/
public function generateProductRequestData($accessToken = null)
{
$currentBatch = 1;
$requests = [];
$responses = [];
$exceptions = 0;
foreach ($this->productRetrievers as $productRetriever) {
$offset = 0;
$limit = $productRetriever->getLimit();
do {
$products = $productRetriever->retrieve($offset);
$offset += $limit;
if (empty($products)) {
break;
}
foreach ($products as $product) {
try {
$requests[] = $this->buildProductRequest($product);
} catch (\Exception $e) {
$exceptions++;
// Don't overload the logs, log the first 3 exceptions
if ($exceptions <= 3) {
$this->fbeHelper->logException($e);
}
// If it looks like a systemic failure : stop feed generation
if ($exceptions > 100) {
throw $e;
}
}
if (count($requests) === self::BATCH_MAX) {
$this->fbeHelper->log(
sprintf('Pushing batch %d with %d products', $currentBatch, count($requests))
);
$response = $this->fbeHelper->makeHttpRequest($requests, $accessToken);
$this->fbeHelper->log('Product push response ' . json_encode($response));
$responses[] = $response;
unset($requests);
$currentBatch++;
}
}
} while (true);
}
if (!empty($requests)) {
$this->fbeHelper->log(sprintf('Pushing batch %d with %d products', $currentBatch, count($requests)));
$response = $this->fbeHelper->makeHttpRequest($requests, $accessToken);
$this->fbeHelper->log('Product push response ' . json_encode($response));
$responses[] = $response;
}
return $responses;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetrieverInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
use Magento\Framework\Exception\LocalizedException;
class Configurable implements ProductRetrieverInterface
{
const LIMIT = 200;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var CollectionFactory
*/
protected $productCollectionFactory;
/**
* @param FBEHelper $fbeHelper
* @param CollectionFactory $productCollectionFactory
*/
public function __construct(FBEHelper $fbeHelper, CollectionFactory $productCollectionFactory)
{
$this->fbeHelper = $fbeHelper;
$this->productCollectionFactory = $productCollectionFactory;
}
/**
* @inheritDoc
*/
public function getProductType()
{
return ConfigurableType::TYPE_CODE;
}
/**
* @inheritDoc
* @throws LocalizedException
*/
public function retrieve($offset = 1, $limit = self::LIMIT): array
{
$storeId = $this->fbeHelper->getStore()->getId();
$configurableCollection = $this->productCollectionFactory->create();
$configurableCollection->addAttributeToSelect('*')
->addAttributeToFilter('status', Status::STATUS_ENABLED)
->addAttributeToFilter('visibility', ['neq' => Visibility::VISIBILITY_NOT_VISIBLE])
->addAttributeToFilter('type_id', $this->getProductType())
->setStoreId($storeId);
$configurableCollection->getSelect()->limit($limit, $offset);
$simpleProducts = [];
foreach ($configurableCollection as $product) {
/** @var Product $product */
/** @var ConfigurableType $configurableType */
$configurableType = $product->getTypeInstance();
$configurableAttributes = $configurableType->getConfigurableAttributes($product);
foreach ($configurableType->getUsedProducts($product) as $childProduct) {
/** @var Product $childProduct */
$configurableSettings = ['item_group_id' => $product->getId()];
foreach ($configurableAttributes as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$attributeCode = $productAttribute->getAttributeCode();
$attributeValue = $childProduct->getData($productAttribute->getAttributeCode());
$attributeLabel = $productAttribute->getSource()->getOptionText($attributeValue);
$configurableSettings[$attributeCode] = $attributeLabel;
}
$childProduct->setConfigurableSettings($configurableSettings);
$childProduct->setParentProductUrl($product->getProductUrl());
$simpleProducts[] = $childProduct;
}
}
return $simpleProducts;
}
/**
* @inheritDoc
*/
public function getLimit()
{
return self::LIMIT;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed\ProductRetriever;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\ProductRetrieverInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Type as ProductType;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
class Simple implements ProductRetrieverInterface
{
const LIMIT = 2000;
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var CollectionFactory
*/
protected $productCollectionFactory;
/**
* @param FBEHelper $fbeHelper
* @param CollectionFactory $productCollectionFactory
*/
public function __construct(FBEHelper $fbeHelper, CollectionFactory $productCollectionFactory)
{
$this->fbeHelper = $fbeHelper;
$this->productCollectionFactory = $productCollectionFactory;
}
/**
* @inheritDoc
*/
public function getProductType()
{
return ProductType::TYPE_SIMPLE;
}
/**
* @param int $offset
* @param int $limit
* @return array
*/
public function retrieve($offset = 1, $limit = self::LIMIT): array
{
$storeId = $this->fbeHelper->getStore()->getId();
$collection = $this->productCollectionFactory->create();
$collection->addAttributeToSelect('*')
->addAttributeToFilter('status', Status::STATUS_ENABLED)
->addAttributeToFilter('visibility', ['neq' => Visibility::VISIBILITY_NOT_VISIBLE])
->addAttributeToFilter('type_id', $this->getProductType())
->setStoreId($storeId);
$collection
->getSelect()->joinLeft(['l' => 'catalog_product_super_link'], 'e.entity_id = l.product_id')
->where('l.product_id IS NULL')
->order(new \Zend_Db_Expr('e.updated_at desc'))
->limit($limit, $offset);
return $collection->getItems();
}
/**
* @inheritDoc
*/
public function getLimit()
{
return self::LIMIT;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed;
use Magento\Catalog\Api\Data\ProductInterface;
interface ProductRetrieverInterface
{
/**
* @return string
*/
public function getProductType();
/**
* @param int $offset
* @param int $limit
* @return ProductInterface[]
*/
public function retrieve($offset = 1, $limit = 100): array;
/**
* @return int
*/
public function getLimit();
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\Product\Feed;
use Exception;
use Facebook\BusinessExtension\Model\Product\Feed\Method\BatchApi as MethodBatchApi;
class Uploader
{
/**
* @var MethodBatchApi
*/
protected $methodBatchApi;
/**
* @param MethodBatchApi $methodBatchApi
*/
public function __construct(MethodBatchApi $methodBatchApi)
{
$this->methodBatchApi = $methodBatchApi;
}
/**
* @return array
* @throws Exception
*/
public function uploadFullCatalog()
{
return $this->methodBatchApi->generateProductRequestData();
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\ResourceModel;
use \Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Config extends AbstractDb
{
protected function _construct()
{
$this->_init('facebook_business_extension_config', 'config_key');
$this->_isPkAutoIncrement = false;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\ResourceModel\Config;
use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
class Collection extends AbstractCollection
{
protected function _construct()
{
$this->_init(
'Facebook\BusinessExtension\Model\Config',
'Facebook\BusinessExtension\Model\ResourceModel\Config'
);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Model\System;
use Magento\Config\Model\ResourceModel\Config as ResourceConfig;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\StoreManagerInterface;
class Config
{
const XML_PATH_FACEBOOK_COLLECTIONS_SYNC_IS_ACTIVE = 'facebook/catalog_management/collections_sync';
const XML_PATH_FACEBOOK_CATALOG_SYNC_IS_ACTIVE = 'facebook/catalog_management/catalog_sync';
const XML_PATH_FACEBOOK_OUT_OF_STOCK_THRESHOLD = 'facebook/inventory_management/out_of_stock_threshold';
/**
* @var StoreManagerInterface
*/
private $storeManager;
/**
* @var ScopeConfigInterface
*/
private $scopeConfig;
/**
* @var ResourceConfig
*/
private $resourceConfig;
/**
* @var TypeListInterface
*/
private $cacheTypeList;
/**
* @method __construct
* @param StoreManagerInterface $storeManager
* @param ScopeConfigInterface $scopeConfig
* @param ResourceConfig $resourceConfig
* @param TypeListInterface $cacheTypeList
*/
public function __construct(
StoreManagerInterface $storeManager,
ScopeConfigInterface $scopeConfig,
ResourceConfig $resourceConfig,
TypeListInterface $cacheTypeList
) {
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
$this->resourceConfig = $resourceConfig;
$this->cacheTypeList = $cacheTypeList;
}
/**
* @method isSingleStoreMode
* @return bool
*/
public function isSingleStoreMode()
{
return $this->storeManager->isSingleStoreMode();
}
/**
* @param $path
* @param $value
* @return $this
*/
public function saveConfig($path, $value)
{
$this->resourceConfig->saveConfig($path, $value);
return $this;
}
/**
* @param $path
* @return $this
*/
public function deleteConfig($path)
{
$this->resourceConfig->deleteConfig($path);
return $this;
}
/**
* @return $this
*/
public function cleanCache()
{
$this->cacheTypeList->cleanType(\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER);
return $this;
}
/**
* @return bool
*/
public function isActiveCollectionsSync()
{
return $this->scopeConfig->isSetFlag(self::XML_PATH_FACEBOOK_COLLECTIONS_SYNC_IS_ACTIVE);
}
/**
* @return bool
*/
public function isActiveCatalogSync()
{
return $this->scopeConfig->isSetFlag(self::XML_PATH_FACEBOOK_CATALOG_SYNC_IS_ACTIVE);
}
/**
* @return mixed
*/
public function getOutOfStockThreshold()
{
return $this->scopeConfig->getValue(self::XML_PATH_FACEBOOK_OUT_OF_STOCK_THRESHOLD);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class AddToCart implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var MagentoDataHelper
*/
protected $magentoDataHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* @var RequestInterface
*/
protected $request;
/**
* Constructor
* @param FBEHelper $fbeHelper
* @param MagentoDataHelper $magentoDataHelper
* @param ServerSideHelper $serverSideHelper
* @param RequestInterface $request
*/
public function __construct(
FBEHelper $fbeHelper,
MagentoDataHelper $magentoDataHelper,
ServerSideHelper $serverSideHelper,
RequestInterface $request
) {
$this->fbeHelper = $fbeHelper;
$this->magentoDataHelper = $magentoDataHelper;
$this->serverSideHelper = $serverSideHelper;
$this->request = $request;
}
/**
* Execute action method for the Observer
*
* @param Observer $observer
* @return $this
*/
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$productSku = $this->request->getParam('product_sku', null);
$product = $this->magentoDataHelper->getProductWithSku($productSku);
if ($product->getId()) {
$customData = [
'currency' => $this->magentoDataHelper->getCurrency(),
'value' => $this->magentoDataHelper->getValueForProduct($product),
'content_type' => 'product',
'content_ids' => [$product->getId()],
'content_category' => $this->magentoDataHelper->getCategoriesForProduct($product),
'content_name' => $product->getName()
];
$event = ServerEventFactory::createEvent('AddToCart', $customData, $eventId);
$this->serverSideHelper->sendEvent($event);
}
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class InitiateCheckout implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var MagentoDataHelper
*/
protected $magentoDataHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* InitiateCheckout constructor
*
* @param FBEHelper $fbeHelper
* @param MagentoDataHelper $magentoDataHelper
* @param ServerSideHelper $serverSideHelper
*/
public function __construct(
FBEHelper $fbeHelper,
MagentoDataHelper $magentoDataHelper,
ServerSideHelper $serverSideHelper
) {
$this->fbeHelper = $fbeHelper;
$this->magentoDataHelper = $magentoDataHelper;
$this->serverSideHelper = $serverSideHelper;
}
/**
* Execute action method for the Observer
*
* @param Observer $observer
* @return $this
*/
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$customData = [
'currency' => $this->magentoDataHelper->getCurrency(),
'value' => $this->magentoDataHelper->getCartTotal(),
'content_type' => 'product',
'content_ids' => $this->magentoDataHelper->getCartContentIds(),
'num_items' => $this->magentoDataHelper->getCartNumItems(),
'contents' => $this->magentoDataHelper->getCartContents()
];
$event = ServerEventFactory::createEvent('InitiateCheckout', array_filter($customData), $eventId);
$this->serverSideHelper->sendEvent($event);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Feed\CategoryCollection;
use Facebook\BusinessExtension\Model\System\Config as SystemConfig;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Helper\Context;
class ProcessCategoryAfterDeleteEventObserver implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var SystemConfig
*/
protected $systemConfig;
/**
* Constructor
* @param FBEHelper $helper
* @param SystemConfig $systemConfig
*/
public function __construct(
FBEHelper $helper,
SystemConfig $systemConfig
) {
$this->fbeHelper = $helper;
$this->systemConfig = $systemConfig;
}
/**
* Call an API to category delete from facebook catalog
* after delete category from Magento
*
* @param Observer $observer
*/
public function execute(Observer $observer)
{
if ($this->systemConfig->isActiveCatalogSync() == false) {
return;
}
$category = $observer->getEvent()->getCategory();
$this->fbeHelper->log("delete category: ".$category->getName());
/** @var CategoryCollection $categoryObj */
$categoryObj = $this->fbeHelper->getObject(CategoryCollection::class);
$categoryObj->deleteCategoryAndSubCategoryFromFB($category);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Feed\CategoryCollection;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProcessCategoryAfterSaveEventObserver implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $_fbeHelper;
/**
* Constructor
* @param FBEHelper $helper
*/
public function __construct(
FBEHelper $helper
) {
$this->_fbeHelper = $helper;
}
/**
* Call an API to category save from facebook catalog
* after save category from Magento
*
* @param Observer $observer
* @return
*/
public function execute(Observer $observer)
{
$category = $observer->getEvent()->getCategory();
$this->_fbeHelper->log("save category: ".$category->getName());
/** @var CategoryCollection $categoryObj */
$categoryObj = $this->_fbeHelper->getObject(CategoryCollection::class);
$syncEnabled =$category->getData("sync_to_facebook_catalog");
if ($syncEnabled === "0") {
$this->_fbeHelper->log("user disabled category sync");
return;
}
$response = $categoryObj->makeHttpRequestAfterCategorySave($category);
return $response;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\Method\BatchApi;
use Facebook\BusinessExtension\Model\System\Config as SystemConfig;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Helper\Context;
class ProcessProductAfterDeleteEventObserver implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var BatchApi
*/
protected $batchApi;
/**
* @var SystemConfig
*/
protected $systemConfig;
/**
* Constructor
* @param FBEHelper $helper
* @param BatchApi $batchApi
* @param SystemConfig $systemConfig
*/
public function __construct(
FBEHelper $helper,
BatchApi $batchApi,
SystemConfig $systemConfig
) {
$this->fbeHelper = $helper;
$this->batchApi = $batchApi;
$this->systemConfig = $systemConfig;
}
/**
* Call an API to product delete from facebook catalog
* after delete product from Magento
*
* @param Observer $observer
*/
public function execute(Observer $observer)
{
if ($this->systemConfig->isActiveCatalogSync() == false) {
return;
}
$product = $observer->getEvent()->getProduct();
if ($product->getId()) {
try {
$this->fbeHelper->log("deleting product: ". $product->getId());
$requestData = $this->batchApi->buildProductRequest($product, $method='DELETE');
$requestParams = [];
$requestParams[0] = $requestData;
$this->fbeHelper->log(json_encode($requestParams));
$response = $this->fbeHelper->makeHttpRequest($requestParams, null);
$this->fbeHelper->log("deletion responses: ".json_encode($response));
} catch (\Exception $e) {
$this->fbeHelper->logException($e);
}
}
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Exception;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Model\Product\Feed\Method\BatchApi;
use Facebook\BusinessExtension\Model\System\Config as SystemConfig;
use Magento\Catalog\Model\Product;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
class ProcessProductAfterSaveEventObserver implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var BatchApi
*/
protected $batchApi;
/**
* @var SystemConfig
*/
protected $systemConfig;
/**
* Constructor
* @param FBEHelper $helper
* @param BatchApi $batchApi
* @param SystemConfig $systemConfig
*/
public function __construct(
FBEHelper $helper,
BatchApi $batchApi,
SystemConfig $systemConfig
) {
$this->fbeHelper = $helper;
$this->batchApi = $batchApi;
$this->systemConfig = $systemConfig;
}
/**
* Call an API to product save from facebook catalog
* after save product from Magento
*
* @param Observer $observer
*/
public function execute(Observer $observer)
{
if ($this->systemConfig->isActiveCatalogSync() == false) {
return;
}
/** @var Product $product */
$product = $observer->getEvent()->getProduct();
if (!$product->getId()) {
return;
}
$storeId = $product->getStoreId();
$product->setStoreId($this->fbeHelper->getStore()->getId());
try {
$requestData = $this->batchApi->buildProductRequest($product);
$requestParams = [];
$requestParams[0] = $requestData;
$this->fbeHelper->makeHttpRequest($requestParams, null);
} catch (Exception $e) {
$this->fbeHelper->logException($e);
}
$product->setStoreId($storeId);
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class Purchase implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var MagentoDataHelper
*/
protected $magentoDataHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* Purchase constructor
*
* @param FBEHelper $fbeHelper
* @param MagentoDataHelper $magentoDataHelper
* @param ServerSideHelper $serverSideHelper
*/
public function __construct(
FBEHelper $fbeHelper,
MagentoDataHelper $magentoDataHelper,
ServerSideHelper $serverSideHelper
) {
$this->fbeHelper = $fbeHelper;
$this->magentoDataHelper = $magentoDataHelper;
$this->serverSideHelper = $serverSideHelper;
}
/**
* Execute action method for the Observer
*
* @param Observer $observer
* @return $this
*/
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$customData = [
'currency' => $this->magentoDataHelper->getCurrency(),
'value' => $this->magentoDataHelper->getOrderTotal(),
'content_type' => 'product',
'content_ids' => $this->magentoDataHelper->getOrderContentIds(),
'contents' => $this->magentoDataHelper->getOrderContents(),
'order_id' => (string)$this->magentoDataHelper->getOrderId()
];
$event = ServerEventFactory::createEvent('Purchase', array_filter($customData), $eventId);
$userDataFromOrder = $this->magentoDataHelper->getUserDataFromOrder();
$this->serverSideHelper->sendEvent($event, $userDataFromOrder);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class Search implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* @var RequestInterface
*/
protected $request;
/**
* Search constructor
*
* @param FBEHelper $fbeHelper
* @param ServerSideHelper $serverSideHelper
* @param RequestInterface $request
*/
public function __construct(
FBEHelper $fbeHelper,
ServerSideHelper $serverSideHelper,
RequestInterface $request
) {
$this->fbeHelper = $fbeHelper;
$this->request = $request;
$this->serverSideHelper = $serverSideHelper;
}
/**
* @return string
*/
public function getSearchQuery()
{
return htmlspecialchars(
$this->request->getParam('q'),
ENT_QUOTES,
'UTF-8'
);
}
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$customData = [
'search_string' => $this->getSearchQuery()
];
$event = ServerEventFactory::createEvent('Search', $customData, $eventId);
$this->serverSideHelper->sendEvent($event);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class ViewCategory implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* \Magento\Framework\Registry
*/
protected $registry;
public function __construct(
FBEHelper $fbeHelper,
ServerSideHelper $serverSideHelper,
\Magento\Framework\Registry $registry
) {
$this->fbeHelper = $fbeHelper;
$this->registry = $registry;
$this->serverSideHelper = $serverSideHelper;
}
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$customData = [];
$category = $this->registry->registry('current_category');
if ($category) {
$customData['content_category'] = addslashes($category->getName());
}
$event = ServerEventFactory::createEvent('ViewCategory', $customData, $eventId);
$this->serverSideHelper->sendEvent($event);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Observer;
use Facebook\BusinessExtension\Helper\FBEHelper;
use Facebook\BusinessExtension\Helper\MagentoDataHelper;
use Facebook\BusinessExtension\Helper\ServerSideHelper;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Facebook\BusinessExtension\Helper\ServerEventFactory;
class ViewContent implements ObserverInterface
{
/**
* @var FBEHelper
*/
protected $fbeHelper;
/**
* @var ServerSideHelper
*/
protected $serverSideHelper;
/**
* \Magento\Framework\Registry
*/
protected $registry;
/**
* @var MagentoDataHelper
*/
protected $_magentoDataHelper;
public function __construct(
FBEHelper $fbeHelper,
ServerSideHelper $serverSideHelper,
MagentoDataHelper $magentoDataHelper,
\Magento\Framework\Registry $registry
) {
$this->fbeHelper = $fbeHelper;
$this->registry = $registry;
$this->serverSideHelper = $serverSideHelper;
$this->_magentoDataHelper = $magentoDataHelper;
}
public function execute(Observer $observer)
{
try {
$eventId = $observer->getData('eventId');
$customData = [
'currency' => $this->_magentoDataHelper->getCurrency()
];
$product = $this->registry->registry('current_product');
if ($product && $product->getId()) {
$customData['value'] = $this->_magentoDataHelper->getValueForProduct($product);
$customData['content_ids'] = [$product->getId()];
$customData['content_category'] = $this->_magentoDataHelper->getCategoriesForProduct($product);
$customData['content_name'] = $product->getName();
$customData['contents'] = [
[
'product_id' => $product->getId(),
'item_price' => $this->_magentoDataHelper->getValueForProduct($product)
]
];
$customData['content_type'] = ($product->getTypeId() == Configurable::TYPE_CODE) ?
'product_group' : 'product';
}
$event = ServerEventFactory::createEvent('ViewContent', array_filter($customData), $eventId);
$this->serverSideHelper->sendEvent($event);
} catch (\Exception $e) {
$this->fbeHelper->log(json_encode($e));
}
return $this;
}
}
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Plugin;
use Facebook\BusinessExtension\Helper\ServerSideHelper\Interceptor;
use FacebookAds\Object\ServerSide\Event;
class CAPIEventsModifierPlugin
{
/**
* Updates the CAPI event if needed
*
* @param Interceptor $subject
* @param Event $event
* @param string[] $user_data
* @return array
*/
public function beforeSendEvent($subject, $event, $user_data = null)
{
/**
* You can enrich the event depending on your needs
* For example, if you want to set the data processing options you can do:
* $event->setDataProcessingOptions(['LDU'])
* ->setDataProcessingOptionsCountry(1)
* ->setDataProcessingOptionsState(1000);
* Read more about data processing options in:
* https://developers.facebook.com/docs/marketing-apis/data-processing-options
*/
return [$event, $user_data];
}
}
# Facebook Business Extension For Magento2
## Facebook Connects Businesses with People
Marketing on Facebook helps your business build lasting relationships with people, find new customers and increase sales for your online store. With this Facebook ad extension, we make it easy to reach the people who matter to your business and track the results of your advertising across devices. This extension will help you:
### Reach the right people
Set up the Facebook pixel to find new customers, optimize your ads for people likely to buy and reach people with relevant ads on Facebook after they've visited your website.
### Show them the right products
Connect your product catalog to Facebook to use dynamic ads. Reach shoppers when they're on Facebook with ads for the products they viewed on your website.
### Measure the results of your ads
When you have the Facebook pixel set up, you can use Facebook ads reporting to understand the sales and revenue that resulted from your ads.
Many online retailers have found success using the Facebook pixel to track the performance of their ads and run dynamic ads:
“The ability to measure sales was the first sign that our business would be a success. Our first day of breaking 100-plus sales always sticks out. Point blank, our marketing plan is Facebook, Facebook, and more Facebook... Facebook is 100% the backbone of our customer acquisition efforts and it's been made even better with the improved Facebook pixel” — Ali Najafian, co-founder, Trendy Butler
“I'm thrilled with the results we've seen since launching dynamic ads. We saw a rise in conversions almost immediately after launch and have been able to scale the program at an impressive pace over the past 6 months. These ads have proven to be a key component of our marketing efforts” — Megan Lang, Digital Marketing Manager, Food52
“With dynamic ads, Target has been able to easily engage consumers with highly relevant creative. The early results have exceeded expectations. Performance has been especially strong on mobile devices — an important and fast-growing area for Target — where we're seeing two times the conversion rate” — Kristi Argyilan, Senior Vice President, Media and Guest Engagement at Target
## What's included?
### (a) Pixel installer
Installing the Facebook pixel allows you to access the features below:
Conversion tracking: See how successful your ad is by seeing what happened as a direct result of your ad (including conversions and sales)
Optimization: Show your ads to people most likely to take a specific action after clicking on them, like adding an item to their cart or making a purchase
Remarketing: When people visit your website, reach them again and remind them of your business with a Facebook ad
### (b) Product catalog integration
Importing your product catalog to Facebook allows you to use dynamic ads. Dynamic ads look identical to other link ads or carousel-format ads that are available on Facebook. However, instead of individually creating an ad for each of your products, Facebook creates the ads for you and personalizes them for each of your customers.
Scale: Use dynamic ads to promote all your products without needing to create individual ads for each item
Highly relevant: Show people ads for products they're interested in to increase the likelihood of a purchase
Always-on: Set up your campaigns once and continually reach people with the right product at the right time
Cross-device: Reach people with ads on any device they use, regardless of where they first see your products
## Usage Instructions
Facebook Business Extension - Installation steps
INSTALL FACEBOOK BUSINESS EXTENSION FROM ZIP FILE ON YOUR DEV INSTANCE. TEST THAT THE EXTENSION
WAS INSTALLED CORRECTLY BEFORE SHIPPING THE CODE TO PRODUCTION
Before installing, verify your Magento cron job is up and running, read more about it on [this](https://devdocs.magento.com/guides/v2.3/config-guide/cli/config-cli-subcommands-cron.html) page.
Login to your server instance.
### INSTALLATION
#### Magento Marketplace Installation
You can download and install our extension in [Magento marketplace](https://marketplace.magento.com/facebook-facebook-for-magento2.html) if you have a marketplace account.
#### Composer Installation
* Go to your magento root path
* Execute command `cd /var/www/Magento` or
`cd /var/www/html/Magento` based on your server Centos or Ubuntu.
* run composer command: `composer require facebook/facebook-for-magento2`
- To enable module execute `php bin/magento module:enable Facebook_BusinessExtension`
- Execute `php bin/magento setup:upgrade`
- Optional `php bin/magento setup:static-content:deploy`
- Execute `php bin/magento setup:di:compile`
- Execute `php bin/magento cache:clean`
- Execute `php bin/magento cron:run` three times
#### Manual Installation
* extract files from an archive.
* Execute command `cd /var/www/Magento/app/code` or
`cd /var/www/html/Magento/app/code` based on your server Centos or Ubuntu.
* Move files into Magento2 folder `app/code/Facebook/BusinessExtension`. If you downloaded zip file on github, you need to
create directory `app/code/Facebook/BusinessExtension`. If you downloaded zip from facebook, those two folders are included.
##### ENABLE EXTENSION
* Make sure you have correct read/write permissions on your Magento root directory.
Read about them [here](https://magento.stackexchange.com/questions/91870/magento-2-folder-file-permissions).
* Move to magento root folder by executing command `cd ../../`
###### Enable Extension By Running Script
You can install the extension with a bash script.
- Copy the install-facebook-business-extension.sh script to your Magento root folder.
- Give it execute permission with `chmod +x install-facebook-business-extension.sh` (you may have to log in as root user to do it).
- Switch to Magento files owner user and run: `./install-facebook-business-extension.sh`.
- You should read `Installation finished` when the script is done.
- Optional. If you don't switch to Magento files owner user run:
`chmod -R 755 ./`
`chmod -R 777 var/`
`chmod -R 777 pub/`
`chmod -R 777 app/etc`
`chmod -R 777 generated`
###### Enable Extension By Running Commands Manually
7. Execute the following commands to manually install Facebook Business Extension.
- Install the Facebook Business SDK for PHP: `composer require facebook/php-business-sdk`. This dependency is used by the extension.
- You will see a message similar to: `Installing facebook/php-business-sdk (8.0.0): Downloading (100%)`
- Execute `php bin/magento module:status`
- You must see Facebook_BusinessExtension in the list of disabled modules.
- To enable module execute `php bin/magento module:enable Facebook_BusinessExtension`
- Execute `php bin/magento setup:upgrade`
- Optional `php bin/magento setup:static-content:deploy`
- Execute `php bin/magento setup:di:compile`
- Execute `php bin/magento cache:clean`
- Execute `php bin/magento cron:run` three times
- Optional. If you are not the owner of Magento files:
`chmod -R 755 ./`
`chmod -R 777 var/`
`chmod -R 777 pub/`
`chmod -R 777 app/etc`
`chmod -R 777 generated`
### Verify Installation
- Upon successful installation, login to your Magento Admin panel.
- Click the Stores icon in the main menu.
- There should be a section named Facebook -> Setup
- Click on 'Setup' to go to the Extension Installation Page.
## Testing before installing
If you want to test this extension in a separate environment, without making changes in your production server, you can use the files provided in tests folder.
Follow `docker-installation-instructions.txt` file to run a Magento 2 store with the extension installed, using Docker, so you can test in your local machine.
## Need help?
Visit Facebook's [Advertiser Help Center](https://www.facebook.com/business/help/532749253576163).
## Requirements
Facebook Business Extension For Magento2 requires
* Magento version 2.0 and above
* PHP 7.0 or greater
* Memory limit of 1 GB or greater (2 GB or higher is preferred)
## Contributing
See the CONTRIBUTING file for how to help out.
## License
Facebook Business Extension For Magento2 is Platform-licensed.
<?php
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*/
namespace Facebook\BusinessExtension\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface
{
const FBE_CONFIG_TABLE_NAME = "facebook_business_extension_config";
public function install(SchemaSetupInterface $installer, ModuleContextInterface $context)
{
$installer->startSetup();
$installer->getConnection()->dropTable($installer->getTable(self::FBE_CONFIG_TABLE_NAME));
$table = $installer->getConnection()->newTable(
$installer->getTable(self::FBE_CONFIG_TABLE_NAME)
)->addColumn(
'config_key',
\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
255,
['nullable' => false, 'primary' => true],
'Config Key'
)->addColumn(
'config_value',
\Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
255,
['nullable' => false, 'default' => ''],
'Config Value'
)->addColumn(
'creation_time',
\Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
null,
[
],
'Creation Time'
)->addColumn(
'update_time',
\Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
null,
[
],
'Modification Time'
);
$installer->getConnection()->createTable($table);
$installer->endSetup();
}
}
<?php
namespace Facebook\BusinessExtension\Setup;
use Facebook\BusinessExtension\Model\Config\ProductAttributes;
use Facebook\BusinessExtension\Model\Config\Source\Product\GoogleProductCategory;
use Magento\Catalog\Model\Category;
use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Attribute;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\UninstallInterface;
class Uninstall implements UninstallInterface
{
/**
* EAV setup factory
*
* @var EavSetupFactory
*/
private $eavSetupFactory;
/**
* @var ProductAttributes
*/
private $productAttributes;
/**
* Uninstall constructor
*
* @param EavSetupFactory $eavSetupFactory
* @param ProductAttributes $productAttributes
*/
public function __construct(EavSetupFactory $eavSetupFactory, ProductAttributes $productAttributes)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->productAttributes = $productAttributes;
}
/**
* @param SchemaSetupInterface $setup
* @param ModuleContextInterface $context
*
* @return void
* @throws LocalizedException
*/
public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$setup->getConnection()->dropTable('facebook_business_extension_config');
$setup->getConnection()->delete('core_config_data', "path LIKE 'facebook/%'");
$eavSetup = $this->eavSetupFactory->create();
$productTypeId = $eavSetup->getEntityTypeId(Product::ENTITY);
$categoryTypeId = $eavSetup->getEntityTypeId(Category::ENTITY);
// delete "google_product_category" product attribute if installed by this extension
if ($eavSetup->getAttributeId(Product::ENTITY, 'google_product_category')) {
/** @var Attribute $attribute */
$attribute = $eavSetup->getAttribute($productTypeId, 'google_product_category');
if (isset($attribute['source_model']) && $attribute['source_model'] === GoogleProductCategory::class) {
$eavSetup->removeAttribute($productTypeId, 'google_product_category');
}
}
// delete product attributes based on configuration
$attributesConfig = $this->productAttributes->getAttributesConfig();
foreach ($attributesConfig as $attrCode => $config) {
if ($eavSetup->getAttributeId(Product::ENTITY, $attrCode)) {
$eavSetup->removeAttribute($productTypeId, $attrCode);
}
}
// delete unit price attributes if exist
if (method_exists($this->productAttributes, 'getUnitPriceAttributesConfig')) {
$attributesConfig = $this->productAttributes->getUnitPriceAttributesConfig();
foreach ($attributesConfig as $attrCode => $config) {
if ($eavSetup->getAttributeId(Product::ENTITY, $attrCode)) {
$eavSetup->removeAttribute($productTypeId, $attrCode);
}
}
}
// delete "Facebook Attribute Group" from all product attribute sets
$setup->getConnection()->delete(
'eav_attribute_group',
['attribute_group_name = ?' => $this->productAttributes->getAttributeGroupName()]
);
// delete "sync_to_facebook_catalog category" attribute
if ($eavSetup->getAttributeId(Category::ENTITY, 'sync_to_facebook_catalog')) {
$eavSetup->removeAttribute($categoryTypeId, 'sync_to_facebook_catalog');
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment