├── Api ├── ConfigProviderInterface.php ├── Data │ ├── Dcc │ │ ├── CatalogData │ │ │ ├── CatalogProduct │ │ │ │ ├── CategoryPathBuilderInterface.php │ │ │ │ ├── CategoryPathInterface.php │ │ │ │ ├── FamilyBuilderInterface.php │ │ │ │ └── FamilyInterface.php │ │ │ ├── CatalogProductBuilderInterface.php │ │ │ └── CatalogProductInterface.php │ │ ├── CatalogDataBuilderInterface.php │ │ └── CatalogDataInterface.php │ └── IndexInterface.php ├── DccInterface.php ├── IndexRepositoryInterface.php └── StringFormatterInterface.php ├── Block ├── Adminhtml │ └── System │ │ └── Config │ │ └── Sftp │ │ └── TestConnection.php └── System │ └── Config │ └── Button.php ├── Console └── Command │ ├── Index.php │ ├── Product.php │ ├── Purchase.php │ └── PurchaseTest.php ├── Controller ├── Adminhtml │ ├── Bvfeed │ │ ├── Rebuildproduct.php │ │ ├── Runproduct.php │ │ └── Runpurchase.php │ ├── Bvindex │ │ └── Index.php │ └── Config │ │ └── Sftp │ │ └── TestConnection.php ├── Index.php ├── Pixel │ └── Test.php └── Submission │ └── Container.php ├── LICENSE.md ├── Logger ├── Handler.php └── Logger.php ├── Model ├── BVSEOSDK │ ├── BV.php │ ├── BVFooter.php │ ├── BVUtility.php │ ├── Base.php │ ├── CHANGELOG.md │ ├── ExampleQuestionsGetContent.php │ ├── ExampleReviewsGetAggregateRating.php │ ├── ExampleReviewsGetContent.php │ ├── ExampleReviewsGetReviews.php │ ├── ExampleSEOGetContent.php │ ├── ExampleSellerratingsGetContent.php │ ├── ExampleSpotlightsGetContent.php │ ├── ExampleStoriesGetContent.php │ ├── LICENSE │ ├── OWNERS │ ├── Questions.php │ ├── README.md │ ├── Reviews.php │ ├── SellerRatings.php │ ├── Spotlights.php │ ├── Stories.php │ ├── archive-assembly.xml │ └── pom.xml ├── Backend │ └── Remote.php ├── Config │ └── Version.php ├── ConfigProvider.php ├── Cron.php ├── CurrentProductProvider.php ├── Dcc.php ├── Dcc │ ├── CatalogData.php │ ├── CatalogData │ │ ├── CatalogProduct.php │ │ ├── CatalogProduct │ │ │ ├── CategoryPath.php │ │ │ ├── CategoryPathBuilder.php │ │ │ ├── Family.php │ │ │ └── FamilyBuilder.php │ │ └── CatalogProductBuilder.php │ └── CatalogDataBuilder.php ├── Feed │ ├── Feed.php │ ├── Product │ │ ├── Brand.php │ │ ├── Category.php │ │ └── Product.php │ ├── ProductFeed.php │ └── PurchaseFeed.php ├── Filesystem │ └── Io │ │ └── Sftp.php ├── Index.php ├── IndexRepository.php ├── Indexer │ ├── Eav.php │ ├── Flat.php │ └── Indexer.php ├── Notification.php ├── ResourceModel │ ├── Index.php │ └── Index │ │ └── Collection.php ├── SeoContent.php ├── Source │ ├── Category.php │ ├── Environment.php │ ├── ProductAttribute.php │ ├── ProductList.php │ ├── Scope.php │ ├── SftpHost.php │ └── Trigger.php ├── StringFormatter.php └── XMLWriter.php ├── OWNERS ├── Observer └── Config.php ├── Plugin ├── Disable.php └── ProductList │ ├── Category.php │ ├── Crosssell.php │ ├── Item.php │ ├── NewProductsWidget.php │ ├── Related.php │ ├── Search.php │ ├── Upsell.php │ └── Widget.php ├── README.md ├── Setup ├── Patch │ └── Data │ │ ├── InstallBvAttribute.php │ │ └── UpgradeBvDataAtttribute.php └── Uninstall.php ├── Test └── Unit │ └── Model │ └── DccTest.php ├── Ui ├── Component │ └── Listing │ │ ├── Column │ │ ├── Bvproductindex │ │ │ └── PageActions.php │ │ ├── Json.php │ │ └── Thumbnail.php │ │ └── DataProviders │ │ └── Bv │ │ └── Product │ │ └── Index.php └── ReviewStaging │ └── Review.php ├── ViewModel ├── Header.php ├── Pixel.php ├── Product.php ├── Questions.php └── Reviews.php ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ ├── di.xml │ ├── menu.xml │ ├── routes.xml │ └── system.xml ├── config.xml ├── crontab.xml ├── csp_whitelist.xml ├── db_schema.xml ├── di.xml ├── events.xml ├── frontend │ └── routes.xml ├── indexer.xml ├── module.xml ├── mview.xml └── webapi.xml ├── phpdox.xml ├── phpunit.xml ├── registration.php └── view ├── adminhtml ├── layout │ └── adminhtml_bvindex_index.xml ├── requirejs-config.js ├── templates │ └── system │ │ └── config │ │ └── testconnection.phtml ├── ui_component │ └── bv_product_index.xml └── web │ └── js │ └── testconnection.js └── frontend ├── layout ├── bazaarvoice_pixel_test.xml ├── bazaarvoice_submission_container.xml ├── catalog_product_view.xml ├── checkout_onepage_success.xml ├── customer_account.xml └── default.xml └── templates ├── checkout └── onepage │ └── success │ └── bvpixel.phtml ├── header.phtml ├── productheader.phtml ├── qa └── questions.phtml └── rr ├── reviews.phtml └── summary.phtml /Api/Data/Dcc/CatalogData/CatalogProduct/CategoryPathBuilderInterface.php: -------------------------------------------------------------------------------- 1 | setTemplate('Bazaarvoice_Connector::system/config/testconnection.phtml'); 12 | return $this; 13 | } 14 | 15 | public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element) 16 | { 17 | $element = clone $element; 18 | $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue(); 19 | return parent::render($element); 20 | } 21 | 22 | protected function _getElementHtml(\Magento\Framework\Data\Form\Element\AbstractElement $element) 23 | { 24 | $originalData = $element->getOriginalData(); 25 | $this->addData( 26 | [ 27 | 'button_label' => __($originalData['button_label']), 28 | 'html_id' => $element->getHtmlId(), 29 | 'ajax_url' => $this->_urlBuilder->getUrl('adminhtml/config_sftp/testconnection'), 30 | 'field_mapping' => str_replace('"', '\\"', json_encode($this->_getFieldMapping())) 31 | ] 32 | ); 33 | 34 | return $this->_toHtml(); 35 | } 36 | 37 | protected function _getFieldMapping() 38 | { 39 | return [ 40 | 'username' => 'bazaarvoice_feeds_sftp_username', 41 | 'password' => 'bazaarvoice_feeds_sftp_password', 42 | 'host' => 'bazaarvoice_feeds_sftp_host_name' 43 | ]; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /Block/System/Config/Button.php: -------------------------------------------------------------------------------- 1 | getForm()->getLayout()->createBlock(\Magento\Backend\Block\Widget\Button::class); 33 | 34 | $originalData = $element->getOriginalData(); 35 | 36 | $buttonLabel = !empty($originalData['button_label']) ? $originalData['button_label'] : __('Run Feed'); 37 | $buttonId = !empty($originalData['id']) ? $originalData['id'] : 'bv_export'; 38 | $url = !empty($originalData['button_url']) ? $originalData['button_url'] : '*/bvfeed/runpurchase'; 39 | $url = $this->getUrl($url); 40 | 41 | $data = [ 42 | 'id' => $buttonId, 43 | 'label' => $buttonLabel, 44 | 'onclick' => "window.open('".$url."')", 45 | ]; 46 | 47 | $html = $buttonBlock->setData($data)->toHtml(); 48 | 49 | return $html; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Console/Command/Index.php: -------------------------------------------------------------------------------- 1 | indexer = $indexer; 39 | } 40 | 41 | protected function configure() 42 | { 43 | $this->setName('bv:index')->setDescription('Clear Bazaarvoice Product Feed Index.'); 44 | } 45 | 46 | /** 47 | * @param \Symfony\Component\Console\Input\InputInterface $input 48 | * @param \Symfony\Component\Console\Output\OutputInterface $output 49 | * 50 | * @return int|void|null 51 | */ 52 | protected function execute(InputInterface $input, OutputInterface $output) 53 | { 54 | $returnValue = Cli::RETURN_SUCCESS; 55 | try { 56 | $this->indexer->executeFull(); 57 | } catch (Exception $e) { 58 | print_r($e->getMessage()."\n".$e->getTraceAsString()); 59 | $returnValue = Cli::RETURN_FAILURE; 60 | } 61 | return $returnValue; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Console/Command/Product.php: -------------------------------------------------------------------------------- 1 | _productFeed = $productFeed; 38 | } 39 | 40 | protected function configure() 41 | { 42 | $this->setName('bv:product')->setDescription('Generates Bazaarvoice Product Feed.'); 43 | } 44 | 45 | /** 46 | * @param \Symfony\Component\Console\Input\InputInterface $input 47 | * @param \Symfony\Component\Console\Output\OutputInterface $output 48 | * 49 | * @return int|void|null 50 | */ 51 | protected function execute(InputInterface $input, OutputInterface $output) 52 | { 53 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 54 | try { 55 | $this->_productFeed->generateFeed(); 56 | } catch (Exception $e) { 57 | print_r($e->getMessage()."\n".$e->getTraceAsString()); 58 | } 59 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Console/Command/Purchase.php: -------------------------------------------------------------------------------- 1 | _purchaseFeed = $purchaseFeed; 37 | } 38 | 39 | protected function configure() 40 | { 41 | $this->setName('bv:purchase')->setDescription('Generates Bazaarvoice Purchase Feed.'); 42 | } 43 | 44 | /** 45 | * @param \Symfony\Component\Console\Input\InputInterface $input 46 | * @param \Symfony\Component\Console\Output\OutputInterface $output 47 | * 48 | * @return int|void|null 49 | */ 50 | protected function execute(InputInterface $input, OutputInterface $output) 51 | { 52 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 53 | $this->_purchaseFeed->generateFeed(); 54 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Console/Command/PurchaseTest.php: -------------------------------------------------------------------------------- 1 | _purchaseFeed = $purchaseFeed; 37 | } 38 | 39 | protected function configure() 40 | { 41 | $this->setName('bv:purchasetest')->setDescription('Generates Bazaarvoice Test Purchase Feed.'); 42 | } 43 | 44 | /** 45 | * @param \Symfony\Component\Console\Input\InputInterface $input 46 | * @param \Symfony\Component\Console\Output\OutputInterface $output 47 | * 48 | * @return int|void|null 49 | */ 50 | protected function execute(InputInterface $input, OutputInterface $output) 51 | { 52 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 53 | $this->_purchaseFeed->setTest(true)->generateFeed(); 54 | print_r("\n".'Memory usage: '.memory_get_usage()."\n"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Bvfeed/Rebuildproduct.php: -------------------------------------------------------------------------------- 1 | indexer = $indexer; 33 | } 34 | 35 | /** 36 | * @return void 37 | * @throws \Exception 38 | */ 39 | public function execute() 40 | { 41 | try { 42 | $this->indexer->executeFull(); 43 | $this->messageManager->addSuccessMessage(__('Product Feed Index is being rebuilt.')); 44 | } catch (Exception $e) { 45 | $this->messageManager->addErrorMessage($e->__toString()); 46 | } 47 | 48 | $this->_redirect('adminhtml/bvindex/index'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Bvfeed/Runproduct.php: -------------------------------------------------------------------------------- 1 | productFeed = $productFeed; 36 | parent::__construct($context); 37 | } 38 | 39 | /** 40 | * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void 41 | */ 42 | public function execute() 43 | { 44 | print_r('
');
45 |         $force = (bool) $this->getRequest()->getParam('force', false);
46 |         $this->productFeed->setForce($force)->generateFeed();
47 |     }
48 | }
49 | 


--------------------------------------------------------------------------------
/Controller/Adminhtml/Bvfeed/Runpurchase.php:
--------------------------------------------------------------------------------
 1 | purchaseFeed = $purchaseFeed;
38 |     }
39 | 
40 |     /**
41 |      * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
42 |      */
43 |     public function execute()
44 |     {
45 |         print_r('
');
46 |         $this->purchaseFeed->setForce(true)->generateFeed();
47 |     }
48 | }
49 | 


--------------------------------------------------------------------------------
/Controller/Adminhtml/Bvindex/Index.php:
--------------------------------------------------------------------------------
 1 | _scopeConfig = $scopeConfig;
44 |         $this->_resultPageFactory = $resultPageFactory;
45 |         parent::__construct($context);
46 |     }
47 | 
48 |     /**
49 |      * Index action
50 |      *
51 |      * @return \Magento\Backend\Model\View\Result\Page
52 |      */
53 |     public function execute()
54 |     {
55 |         /**
56 |         * @var Page $resultPage 
57 |         */
58 |         $resultPage = $this->_resultPageFactory->create();
59 |         $resultPage->setActiveMenu('Magento_Catalog::inventory');
60 |         $resultPage->getConfig()->getTitle()->prepend(__('Bazaarvoice Product Feed'));
61 | 
62 |         return $resultPage;
63 |     }
64 | }
65 | 


--------------------------------------------------------------------------------
/Controller/Adminhtml/Config/Sftp/TestConnection.php:
--------------------------------------------------------------------------------
  1 | sftp = $sftp;
 73 |         $this->storeManager = $storeManager;
 74 | 
 75 |         $this->configProvider = $configProvider;
 76 |         $this->resultJsonFactory = $resultJsonFactory;
 77 |         $this->tagFilter = $tagFilter;
 78 | 
 79 |         parent::__construct($context);
 80 |     }
 81 | 
 82 |     public function execute()
 83 |     {
 84 |         $result = [
 85 |             'success' => false,
 86 |             'errorMessage' => '',
 87 |         ];
 88 | 
 89 |         $options = $this->getRequest()->getParams();
 90 | 
 91 |         try {
 92 |             if(empty($options['username']) || empty($options['password']) || empty($options['host'])) {
 93 |                 throw new \Magento\Framework\Exception\LocalizedException(
 94 |                     __('Missing SFTP credentials.')
 95 |                 );
 96 |             }
 97 | 
 98 |             $params = [
 99 |                 'host'  => $this->configProvider->getSftpHost($this->storeManager->getStore()->getId(), ScopeInterface::SCOPE_STORE, $options['host']),
100 |                 'username'  => $options['username'],
101 |                 'password' => $this->configProvider->getSftpPassword($this->storeManager->getStore()->getId())
102 |             ];
103 | 
104 |             if($options['password'] != '******') {
105 |                 $params['password'] = $options['password'];
106 |             }
107 | 
108 |             $this->sftp->open($params);
109 |             $this->sftp->close();
110 | 
111 |             $result['success'] = true;
112 | 
113 |         }catch (\Magento\Framework\Exception\LocalizedException $e) {
114 |             $result['errorMessage'] = $e->getMessage();
115 |         } catch (\Exception $e) {
116 |             $message = __($e->getMessage());
117 |             $result['errorMessage'] = $this->tagFilter->filter($message);
118 |         }
119 | 
120 | 
121 |         /**
122 |         * @var \Magento\Framework\Controller\Result\Json $resultJson 
123 |         */
124 |         $resultJson = $this->resultJsonFactory->create();
125 |         return $resultJson->setData($result);
126 |     }
127 | 
128 | }


--------------------------------------------------------------------------------
/Controller/Index.php:
--------------------------------------------------------------------------------
 1 | _pageFactory = $pageFactory;
36 | 
37 |         return parent::__construct($context);
38 |     }
39 | 
40 |     /**
41 |      * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|\Magento\Framework\View\Result\Page
42 |      */
43 |     public function execute()
44 |     {
45 |         $page = $this->_pageFactory->create();
46 | 
47 |         return $page;
48 |     }
49 | }
50 | 


--------------------------------------------------------------------------------
/Controller/Pixel/Test.php:
--------------------------------------------------------------------------------
 1 | getRequest()->getParam('order_increment_id');
26 |         $orderId = $this->getRequest()->getParam('order_id');
27 |         $session = $this->getOnepage()->getCheckout();
28 |         $session->setLastRealOrderId($orderIncrementId);
29 |         $session->setLastOrderId($orderId);
30 |         $session->setLastSuccessQuoteId('dummy_value');
31 |         $session->setLastQuoteId('dummy_value');
32 |         return parent::execute();
33 |     }
34 | }
35 | 


--------------------------------------------------------------------------------
/Controller/Submission/Container.php:
--------------------------------------------------------------------------------
 1 | _view->loadLayout();
26 |         $this->_view->renderLayout();
27 |     }
28 | }
29 | 


--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright 2019 Bazaarvoice, Inc.
2 | 
3 | Bazaarvoice copyright materials may not be reproduced in whole or in part by
4 | persons, organizations or corporations other than Bazaarvoice, Inc., its
5 | affiliates and divisions without the prior written permission of the Legal
6 | Department at Bazaarvoice, Inc.
7 | 


--------------------------------------------------------------------------------
/Logger/Handler.php:
--------------------------------------------------------------------------------
 1 | filesystem = $filesystem;
52 |         parent::__construct($filesystem);
53 |         $this->setFormatter(new LineFormatter($this->_format, null, true));
54 |     }
55 | }
56 | 


--------------------------------------------------------------------------------
/Logger/Logger.php:
--------------------------------------------------------------------------------
 1 | admin = $state->getAreaCode() === 'adminhtml';
51 |         } catch (Exception $e) {
52 |         }
53 |         parent::__construct($name, $handlers);
54 |         $this->configProvider = $configProvider;
55 |         /** @codingStandardsIgnoreEnd */
56 |     }
57 | 
58 |     /**
59 |      * @param string|array $message
60 |      * @param array        $context
61 |      *
62 |      * @return bool
63 |      */
64 |     public function debug($message, array $context = []): void
65 |     {
66 |         if ($this->configProvider->isDebugEnabled()) {
67 |             if (is_array($message)) {
68 |                 $message = json_encode($message);
69 |             }
70 |             $this->addRecord(static::DEBUG, strval($message),$context);
71 |         }
72 |     }
73 | 
74 |     /**
75 |      * @param int    $level
76 |      * @param string $message
77 |      * @param array  $context
78 |      * @return bool
79 |      */
80 |     public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool
81 |     {
82 |         if (is_array($message)) {
83 |             $message = print_r($message, $return = true);
84 |         }
85 | 
86 |         if (php_sapi_name() == "cli" || $this->admin) {
87 |             print_r($message."\n");
88 |         }
89 | 
90 |         return parent::addRecord($level, $message, $context);
91 |     }
92 | }
93 | 


--------------------------------------------------------------------------------
/Model/BVSEOSDK/BVFooter.php:
--------------------------------------------------------------------------------
  1 | base = $base;
 43 |         $this->access_method = $access_method;
 44 |         $this->msg = $msg;
 45 |     }
 46 | 
 47 |     /**
 48 |      * buildSDKFooter
 49 |      *
 50 |      * Returns hidden SDK footer.
 51 |      *
 52 |      * @access public
 53 |      * @return string Html formatted footer.
 54 |      */
 55 |     public function buildSDKFooter()
 56 |     {
 57 |         $method_type = !empty($this->base->config['internal_file_path']) ? 'LOCAL' : 'CLOUD';
 58 |         $access_method = $this->access_method;
 59 |         $time_end = microtime(true);
 60 | 
 61 |         if (!empty($this->base->start_time)) {
 62 |             $exec_time = round(($time_end - $this->base->start_time) * 1000, 2);
 63 |         } else {
 64 |             $exec_time = 0;
 65 |         }
 66 |         $content_type = mb_strtoupper($this->base->config['content_type']);
 67 |         $subject_type = mb_strtoupper($this->base->config['subject_type']);
 68 | 
 69 |         $footer = "\n".'';
 77 | 
 78 |         return $footer;
 79 |     }
 80 | 
 81 |     /**
 82 |      * buildSDKDebugFooter
 83 |      *
 84 |      * Returns hidden SDK debug footer.
 85 |      *
 86 |      * @access public
 87 |      * @return string Html formatted debug footer.
 88 |      */
 89 |     public function buildSDKDebugFooter()
 90 |     {
 91 |         $staging = !empty($this->base->config['staging']) ? 'TRUE' : 'FALSE';
 92 |         $testing = !empty($this->base->config['testing']) ? 'TRUE' : 'FALSE';
 93 |         $sdk_enabled = !empty($this->base->config['seo_sdk_enabled']) ? 'TRUE' : 'FALSE';
 94 |         $ssl_enabled = !empty($this->base->config['ssl_enabled']) ? 'TRUE' : 'FALSE';
 95 |         $proxy_host = !empty($this->base->config['proxy_host']) ? $this->base->config['proxy_host'] : 'none';
 96 |         $proxy_port = !empty($this->base->config['proxy_port']) ? $this->base->config['proxy_port'] : '0';
 97 |         $local_seo_file_root = (!empty($this->base->config['load_seo_files_locally']))
 98 |             ? $this->base->config['local_seo_file_root'] : 'FALSE';
 99 |         $content_type = mb_strtoupper($this->base->config['content_type']);
100 |         $subject_type = mb_strtoupper($this->base->config['subject_type']);
101 |         if (!empty($this->base->config['page_params']['subject_id'])
102 |             && !empty($this->base->config['page_params']['content_type'])
103 |             && $this->base->config['page_params']['content_type'] == $this->base->config['content_type']) {
104 |             $subject_id = $this->base->config['page_params']['subject_id'];
105 |         } else {
106 |             $subject_id = $this->base->config['subject_id'];
107 |         }
108 | 
109 |         $footer = "\n".'';
151 | 
152 |         return $footer;
153 |     }
154 | 
155 | }
156 | 


--------------------------------------------------------------------------------
/Model/BVSEOSDK/CHANGELOG.md:
--------------------------------------------------------------------------------
 1 | # Changelog
 2 | 
 3 | ## 3.2.1
 4 | * Removed tick_timer function as timeouts are handled via curl options.
 5 | * Switched to CURLOPT_TIMEOUT_MS option for better granularity.
 6 | 
 7 | ## 3.2.0
 8 | 
 9 | * Pass-through of User Agent to gather statistics.
10 | 
11 | ## 3.1.0
12 | 
13 | * Seller Ratings support.
14 | 
15 | ## 3.0.0
16 |  * Security updates:
17 |    * No longer infer page or base URL.
18 |    * Sanitize pagination links.
19 |  * Adopt semver versioning.
20 | 
21 | ## 2.4.0.0
22 | 
23 | * Fix sp_mt metadata value and incorrect variable names.
24 | 
25 | ## 2.3.0.1
26 | 
27 | * Support gzip htm(html) download.
28 | * bvstate support, with fragment support.
29 | * Support for multi-byte urls.
30 | * Fix getAggregateRating and getReviews when botnet is detected.
31 | 
32 | ## 2.2.0.2
33 | 
34 | * Spotlights support.
35 | * PHP SDK refactoring and consistent variable naming.
36 | * Stories support.
37 | * Charset support.
38 | * Botnet support with configuration for timeouts for botnet requests and non-botnet requests.
39 | 


--------------------------------------------------------------------------------
/Model/BVSEOSDK/ExampleQuestionsGetContent.php:
--------------------------------------------------------------------------------
 1 |  '',
11 |     'subject_id'     => '',
12 |     'cloud_key'      => '',
13 |     'page_url'       => '',
14 |     ]
15 | );
16 | ?>
17 | 
18 | 
19 |     BV SDK PHP Example - Questions: GetContent
20 | 
21 | 
22 | This is a test page for Questions: getContent
23 | This will return questions and answers content

24 | 25 |
26 | questions->getContent()); ?> 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleReviewsGetAggregateRating.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | 'page_url' => '', 14 | ] 15 | ); 16 | ?> 17 | 18 | 19 | BV SDK PHP Example - getAggregateRating 20 | 21 | 22 | This is a test page for Reviews: getAggregateRating()
23 | This will return aggregate rating content

24 |
25 | reviews->getAggregateRating()); ?> 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleReviewsGetContent.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | 'page_url' => '', 14 | ] 15 | ); 16 | ?> 17 | 18 | 19 | BV SDK PHP Example - GetContent 20 | 21 | 22 | This is a test page for Reviews: getContent()
23 | GetContent() will return reviews and aggregate content

24 | 25 |
26 | reviews->getContent()); ?> 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleReviewsGetReviews.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | 'page_url' => '', 14 | ] 15 | ); 16 | ?> 17 | 18 | 19 | BV SDK PHP Example - getReviews 20 | 21 | 22 | This is a test page for Reviews: getReviews()
23 | This will return review content

24 | 25 |
26 | reviews->getReviews()); ?> 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleSEOGetContent.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | 'content_type' => 'questions', 14 | 'subject_type' => 'category', 15 | 'staging' => true, 16 | ] 17 | ); 18 | ?> 19 | 20 | 21 | BV SDK PHP Example - SEO: GetContent 22 | 23 | 24 | This is a test page for SEO getContent
25 | This will return questions and answers content

26 | 27 |
28 | SEO->getContent()); ?> 29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleSellerratingsGetContent.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'cloud_key' => '', 12 | 'page_url' => '', 13 | 'subject_id' => 'seller', 14 | ] 15 | ); 16 | ?> 17 | 18 | 19 | BV SDK PHP Example - GetContent 20 | 21 | 22 | This is a test page for SellerRatings: getContent()
23 | GetContent() will return seller ratings content

24 | 25 |
26 | sellerratings->getContent()); ?> 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleSpotlightsGetContent.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | 'page_url' => '', 14 | ] 15 | ); 16 | ?> 17 | 18 | 19 | BV SDK PHP Example - GetContent 20 | 21 | 22 | This is a test page for Spotlights: getContent()
23 | GetContent() will return spotlights content

24 | 25 |
26 | spotlights->getContent()); ?> 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/ExampleStoriesGetContent.php: -------------------------------------------------------------------------------- 1 | '', 11 | 'subject_id' => '', 12 | 'cloud_key' => '', 13 | // either STORIES_LIST or STORIES_GRID 14 | 'content_sub_type' => 'stories_grid', 15 | 'staging' => true, 16 | ] 17 | ); 18 | ?> 19 | 20 | 21 | BV SDK PHP Example - GetContent 22 | 23 | 24 | This is a test page for Stories: getContent()
25 | GetContent() will return stories_grid content

26 | 27 |
28 | stories->getContent()); ?> 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/LICENSE: -------------------------------------------------------------------------------- 1 | copyright 2015 Bazaarvoice, Inc. 2 | 3 | Bazaarvoice copyright materials may not be reproduced in whole or in part by 4 | persons, organizations or corporations other than Bazaarvoice, Inc., its 5 | affiliates and divisions without the prior written permission of the Legal 6 | Department at Bazaarvoice, Inc. 7 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/OWNERS: -------------------------------------------------------------------------------- 1 | # Owning team. 2 | seo-sdk-owners@bazaarvoice.com 3 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/Questions.php: -------------------------------------------------------------------------------- 1 | config['content_type'] = 'questions'; 29 | } 30 | 31 | public function getContent() 32 | { 33 | $payload = $this->_renderSEO('getContent'); 34 | if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) { 35 | $subject_id = $this->config['page_params']['subject_id']; 36 | } else { 37 | $subject_id = $this->config['subject_id']; 38 | } 39 | // if they want to power display integration as well 40 | // then we need to include the JS integration code 41 | if ($this->config['include_display_integration_code']) { 42 | 43 | $payload .= ' 44 | 49 | '; 50 | } 51 | 52 | return $payload; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/README.md: -------------------------------------------------------------------------------- 1 | # Bazaarvoice SEO SDK for PHP 2 | 3 | This repository contains the codebase for the Bazaarvoice SEO SDK for PHP. Find 4 | out more about Bazaarvoice SEO at [Bazaarvoice Knowledge][1]. 5 | 6 | ## Documentation and Packaged Releases 7 | 8 | The latest SDK documentation and links to releases are available at 9 | [Bazaarvoice Knowledge][1]. 10 | 11 | [1]: http://knowledge.bazaarvoice.com/bvseo/ 12 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/Reviews.php: -------------------------------------------------------------------------------- 1 | config['content_type'] = 'reviews'; 29 | 30 | // for reviews subject type will always 31 | // need to be product 32 | $this->config['subject_type'] = 'product'; 33 | } 34 | 35 | public function getAggregateRating() 36 | { 37 | return $this->_renderAggregateRating(); 38 | } 39 | 40 | public function getReviews() 41 | { 42 | return $this->_renderReviews(); 43 | } 44 | 45 | public function getContent() 46 | { 47 | $payload = $this->_renderSEO('getContent'); 48 | 49 | if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) { 50 | $subject_id = $this->config['page_params']['subject_id']; 51 | } else { 52 | $subject_id = $this->config['subject_id']; 53 | } 54 | // if they want to power display integration as well 55 | // then we need to include the JS integration code 56 | if ($this->config['include_display_integration_code']) { 57 | $payload .= ' 58 | 63 | '; 64 | } 65 | 66 | return $payload; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/SellerRatings.php: -------------------------------------------------------------------------------- 1 | config['content_type'] = 'reviews'; 25 | 26 | // for seller rating subject type will always 27 | // need to be seller 28 | $this->config['subject_type'] = 'seller'; 29 | 30 | } 31 | 32 | public function getContent() 33 | { 34 | return $this->_renderSEO('getContent'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/Spotlights.php: -------------------------------------------------------------------------------- 1 | config['content_type'] = 'spotlights'; 24 | 25 | // for spotlights subject type will always 26 | // need to be category 27 | $this->config['subject_type'] = 'category'; 28 | } 29 | 30 | public function getContent() 31 | { 32 | return $this->_renderSEO('getContent'); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/Stories.php: -------------------------------------------------------------------------------- 1 | config['content_type'] = 'stories'; 29 | 30 | // for stories subject type will always 31 | // need to be product 32 | $this->config['subject_type'] = 'product'; 33 | 34 | // for stories we have to set content sub type 35 | // the sub type is configured as either STORIES_LIST or STORIES_GRID 36 | // the folder names are "stories" and "storiesgrid" respectively. 37 | if (isset($this->config['content_sub_type']) 38 | && $this->config['content_sub_type'] == "stories_grid") { 39 | $this->config['content_sub_type'] = "storiesgrid"; 40 | } else { 41 | $this->config['content_sub_type'] = "stories"; 42 | } 43 | } 44 | 45 | public function getContent() 46 | { 47 | $payload = $this->_renderSEO('getContent'); 48 | if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) { 49 | $subject_id = $this->config['page_params']['subject_id']; 50 | } else { 51 | $subject_id = $this->config['subject_id']; 52 | } 53 | // if they want to power display integration as well 54 | // then we need to include the JS integration code 55 | if ($this->config['include_display_integration_code']) { 56 | $payload .= ' 57 | 62 | '; 63 | } 64 | 65 | return $payload; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/archive-assembly.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | assembly 8 | 9 | zip 10 | 11 | 15 | false 16 | 17 | 18 | \ 19 | 22 | 23 | target/ 24 | .gitignore 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Model/BVSEOSDK/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 4.0.0 8 | com.bazaarvoice 9 | bv-seo-sdk-php 10 | 3.2.1 11 | bv-seo-sdk-php 12 | Bazaarvoice SEO SDK for PHP. 13 | 14 | 19 | ${scm.connection.url} 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.apache.maven.scm 27 | maven-scm-provider-gitexe 28 | 1.9.2 29 | 30 | 31 | 32 | 33 | 36 | 37 | org.apache.maven.plugins 38 | maven-deploy-plugin 39 | 2.7 40 | 41 | true 42 | 43 | 44 | 49 | 50 | maven-assembly-plugin 51 | 2.5.4 52 | 53 | 54 | archive-assembly.xml 55 | 56 | 57 | 58 | 62 | 63 | com.bazaarvoice.maven.plugins 64 | s3-upload-maven-plugin 65 | 1.4 66 | 67 | 68 | deploy 69 | 70 | s3-upload 71 | 72 | 73 | ${destination.bucket} 74 | 75 | ${artifact.source}/${project.name}-${project.version}-assembly.zip 76 | 77 | 78 | ${s3.repo.path}/php_v${project.version}.zip 79 | 80 | false 81 | 82 | 83 | 84 | 85 | 89 | 90 | org.apache.maven.plugins 91 | maven-scm-plugin 92 | 1.9.2 93 | 94 | connection 95 | Release_v${project.version} 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Model/Backend/Remote.php: -------------------------------------------------------------------------------- 1 | getPath() == 'bazaarvoice/feeds/product_filename') { 27 | $value = 'productfeed.xml'; 28 | } elseif ($this->getPath() == 'bazaarvoice/feeds/product_path') { 29 | $value = '/import-inbox'; 30 | } 31 | } 32 | 33 | return parent::setValue($value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Model/Config/Version.php: -------------------------------------------------------------------------------- 1 | componentRegistrar = $componentRegistrar; 48 | $this->readFactory = $readFactory; 49 | parent::__construct( 50 | $context, 51 | $registry, 52 | $config, 53 | $cacheTypeList, 54 | $resource, 55 | $resourceCollection, 56 | $data 57 | ); 58 | } 59 | 60 | /** 61 | * Get current module version from composer.json 62 | * 63 | * @return string 64 | * @throws \Magento\Framework\Exception\FileSystemException 65 | */ 66 | public function getModuleVersion() 67 | { 68 | /** 69 | * @var string $composerJsonData 70 | */ 71 | 72 | /** 73 | * @var string[] $data 74 | */ 75 | 76 | /** 77 | * @var ReadInterface $directoryRead 78 | */ 79 | 80 | /** 81 | * @var null|string $path 82 | */ 83 | 84 | /** 85 | * @var string $version 86 | */ 87 | 88 | $path = $this->componentRegistrar->getPath( 89 | \Magento\Framework\Component\ComponentRegistrar::MODULE, 90 | 'Bazaarvoice_Connector' 91 | ); 92 | $directoryRead = $this->readFactory->create($path); 93 | $composerJsonData = $directoryRead->readFile('composer.json'); 94 | $data = json_decode($composerJsonData); 95 | if (!empty($data->version)) { 96 | $version = $data->version; 97 | } 98 | 99 | return $version ?? __('Could not retrieve extension version.'); 100 | } 101 | 102 | /** 103 | * @return void 104 | * @throws \Magento\Framework\Exception\FileSystemException 105 | */ 106 | public function afterLoad() 107 | { 108 | $version = $this->getModuleVersion(); 109 | $this->setValue($version); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Model/Cron.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 57 | $this->configProvider = $configProvider; 58 | $this->purchaseFeed = $purchaseFeed; 59 | $this->productFeed = $productFeed; 60 | } 61 | 62 | public function sendPurchaseFeed() 63 | { 64 | $this->logger->info('Begin Purchase Feed Cron'); 65 | $this->purchaseFeed->generateFeed(); 66 | 67 | $this->logger->info('End Purchase Feed Cron'); 68 | } 69 | 70 | public function sendProductFeed() 71 | { 72 | $this->logger->info('Begin Product Feed Cron'); 73 | $this->productFeed->generateFeed(); 74 | $this->logger->info('End Product Feed Cron'); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Model/CurrentProductProvider.php: -------------------------------------------------------------------------------- 1 | registry = $registry; 51 | $this->productRepository = $productRepository; 52 | $this->bvLogger = $bvLogger; 53 | } 54 | 55 | /** 56 | * Get current product. Currently uses the registry, which has been deprecated since Magento 2.3. 57 | * Will be modified when Magento implements the replacement. 58 | * 59 | * @return bool|\Magento\Catalog\Model\Product|\Magento\Catalog\Api\Data\ProductInterface 60 | */ 61 | public function getProduct() 62 | { 63 | if (empty($this->currentProduct)) { 64 | try { 65 | $product = $this->registry->registry('product'); 66 | if ($product === null) { 67 | throw new NoSuchEntityException(); 68 | } 69 | $this->currentProduct = $this->productRepository->getById($product->getId()); 70 | } catch (Exception $e) { 71 | $this->bvLogger->critical($e->getMessage()."\n".$e->getTraceAsString()); 72 | 73 | return false; 74 | } 75 | } 76 | 77 | return $this->currentProduct; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Model/Dcc.php: -------------------------------------------------------------------------------- 1 | stringFormatter = $stringFormatter; 64 | $this->logger = $logger; 65 | $this->productRepository = $productRepository; 66 | $this->currentProductProvider = $currentProductProvider; 67 | $this->catalogDataBuilder = $catalogDataBuilder; 68 | parent::__construct($data); 69 | } 70 | 71 | /** 72 | * @param int|null $productId 73 | * @param int|null $storeId 74 | * 75 | * @return string 76 | */ 77 | public function getJson($productId = null, $storeId = null) 78 | { 79 | $product = $this->getProduct($productId, $storeId); 80 | if ($product) { 81 | $this->build($product); 82 | return $this->stringFormatter->jsonEncode($this->getData()); 83 | } 84 | 85 | return ''; 86 | } 87 | 88 | /** 89 | * @param \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $product 90 | * 91 | * @return $this 92 | */ 93 | private function build($product) 94 | { 95 | $dccCatalogData = $this->catalogDataBuilder->build($product); 96 | $this->setCatalogData($dccCatalogData->getData()); 97 | 98 | return $this; 99 | } 100 | 101 | /** 102 | * @param int|null $productId 103 | * @param int|null $storeId 104 | * 105 | * @return bool|\Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product 106 | */ 107 | private function getProduct($productId = null, $storeId = null) 108 | { 109 | try { 110 | if ($productId && $storeId) { 111 | return $this->productRepository->getById($productId, $editMode = false, $storeId); 112 | } 113 | 114 | return $this->currentProductProvider->getProduct(); 115 | } catch (NoSuchEntityException $e) { 116 | $this->logger->critical( 117 | "Product does not exist. ID: $productId and store: $storeId. " 118 | ."Error: {$e->getTraceAsString()}" 119 | ); 120 | } 121 | 122 | return false; 123 | } 124 | 125 | /** 126 | * @return \Bazaarvoice\Connector\Api\Data\Dcc\CatalogDataInterface 127 | */ 128 | private function getCatalogData() 129 | { 130 | return $this->getData('catalogData'); 131 | } 132 | 133 | /** 134 | * @param \Bazaarvoice\Connector\Api\Data\Dcc\CatalogDataInterface $catalogData 135 | * 136 | * @return \Bazaarvoice\Connector\Model\Dcc 137 | */ 138 | private function setCatalogData($catalogData) 139 | { 140 | return $this->setData('catalogData', $catalogData); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /Model/Dcc/CatalogData.php: -------------------------------------------------------------------------------- 1 | getData('catalogProducts'); 27 | } 28 | 29 | /** 30 | * @param array $catalogProducts 31 | * 32 | * @return \Bazaarvoice\Connector\Api\Data\Dcc\CatalogDataInterface|\Bazaarvoice\Connector\Model\Dcc\CatalogData 33 | */ 34 | public function setCatalogProducts(array $catalogProducts) 35 | { 36 | return $this->setData('catalogProducts', $catalogProducts); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Model/Dcc/CatalogData/CatalogProduct.php: -------------------------------------------------------------------------------- 1 | getData('productId'); 34 | } 35 | 36 | /** 37 | * @param string $productId 38 | * 39 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 40 | */ 41 | public function setProductId(string $productId = null): CatalogProduct 42 | { 43 | return $this->setData('productId', $productId); 44 | } 45 | 46 | /** 47 | * @return string|null 48 | */ 49 | public function getProductName() 50 | { 51 | return $this->getData('productName'); 52 | } 53 | 54 | /** 55 | * @param string $productName 56 | * 57 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 58 | */ 59 | public function setProductName(string $productName = null): CatalogProduct 60 | { 61 | return $this->setData('productName', $productName); 62 | } 63 | 64 | /** 65 | * @return string|null 66 | */ 67 | public function getProductDescription() 68 | { 69 | return $this->getData('productDescription'); 70 | } 71 | 72 | /** 73 | * @param string $productDescription 74 | * 75 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 76 | */ 77 | public function setProductDescription(string $productDescription = null): CatalogProduct 78 | { 79 | return $this->setData('productDescription', $productDescription); 80 | } 81 | 82 | /** 83 | * @return string|null 84 | */ 85 | public function getProductImageURL() 86 | { 87 | return $this->getData('productImageURL'); 88 | } 89 | 90 | /** 91 | * @param string $productImageURL 92 | * 93 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 94 | */ 95 | public function setProductImageURL(string $productImageURL = null): CatalogProduct 96 | { 97 | return $this->setData('productImageURL', $productImageURL); 98 | } 99 | 100 | /** 101 | * @return string|null 102 | */ 103 | public function getProductPageURL() 104 | { 105 | return $this->getData('productPageURL'); 106 | } 107 | 108 | /** 109 | * @param string $productPageUrl 110 | * 111 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 112 | */ 113 | public function setProductPageURL(string $productPageUrl = null): CatalogProduct 114 | { 115 | return $this->setData('productPageURL', $productPageUrl); 116 | } 117 | 118 | /** 119 | * @return string|null 120 | */ 121 | public function getBrandId() 122 | { 123 | return $this->getData('brandId'); 124 | } 125 | 126 | /** 127 | * @param string $brandId 128 | * 129 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 130 | */ 131 | public function setBrandId($brandId): CatalogProduct 132 | { 133 | return $this->setData('brandId', $brandId); 134 | } 135 | 136 | /** 137 | * @return string|null 138 | */ 139 | public function getBrandName() 140 | { 141 | return $this->getData('brandName'); 142 | } 143 | 144 | /** 145 | * @param string $brandName 146 | * 147 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 148 | */ 149 | public function setBrandName($brandName): CatalogProduct 150 | { 151 | return $this->setData('brandName', $brandName); 152 | } 153 | 154 | /** 155 | * @return array|null 156 | */ 157 | public function getCategoryPath() 158 | { 159 | return $this->getData('categoryPath'); 160 | } 161 | 162 | /** 163 | * @param array $categoryPath 164 | * 165 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 166 | */ 167 | public function setCategoryPath(array $categoryPath = null): CatalogProduct 168 | { 169 | return $this->setData('categoryPath', $categoryPath); 170 | } 171 | 172 | /** 173 | * @return array|null 174 | */ 175 | public function getManufacturerPartNumbers() 176 | { 177 | return $this->getData('manufacturerPartNumbers'); 178 | } 179 | 180 | /** 181 | * @param array $categoryPath 182 | * 183 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 184 | */ 185 | public function setManufacturerPartNumbers(array $categoryPath = null): CatalogProduct 186 | { 187 | return $this->setData('manufacturerPartNumbers', $categoryPath); 188 | } 189 | 190 | /** 191 | * @return array|null 192 | */ 193 | public function getModelNumbers() 194 | { 195 | return $this->getData('modelNumbers'); 196 | } 197 | 198 | /** 199 | * @param array $categoryPath 200 | * 201 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 202 | */ 203 | public function setModelNumbers(array $categoryPath = null): CatalogProduct 204 | { 205 | return $this->setData('modelNumbers', $categoryPath); 206 | } 207 | 208 | /** 209 | * @return bool|null 210 | */ 211 | public function getInactive() 212 | { 213 | return $this->getData('inactive'); 214 | } 215 | 216 | /** 217 | * @param bool $inactive 218 | * 219 | * @return \Bazaarvoice\Connector\Model\Dcc\CatalogData\CatalogProduct 220 | */ 221 | public function setInactive(bool $inactive): CatalogProduct 222 | { 223 | return $this->setData('inactive', $inactive); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /Model/Dcc/CatalogData/CatalogProduct/CategoryPath.php: -------------------------------------------------------------------------------- 1 | stringFormatter = $stringFormatter; 55 | $this->escaper = $escaper; 56 | $this->dccCategoryPathFactory = $dccCategoryPathFactory; 57 | $this->configProvider = $configProvider; 58 | } 59 | 60 | /** 61 | * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Catalog\Model\Category $category 62 | * 63 | * @return \Bazaarvoice\Connector\Api\Data\Dcc\CatalogData\CatalogProduct\CategoryPathInterface 64 | */ 65 | public function build($category) 66 | { 67 | $dccCategoryPath = $this->dccCategoryPathFactory->create(); 68 | $dccCategoryPath->setId($this->getCategoryId($category)); 69 | $dccCategoryPath->setName($this->getCategoryName($category)); 70 | return $dccCategoryPath; 71 | } 72 | 73 | /** 74 | * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Catalog\Model\Category $category 75 | * 76 | * @return string 77 | */ 78 | private function getCategoryId($category): string 79 | { 80 | $prefix = $this->configProvider->getCategoryPrefix($category->getStoreId()); 81 | return $prefix . $this->stringFormatter->getFormattedCategoryPath($category); 82 | } 83 | 84 | /** 85 | * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Catalog\Model\Category $category 86 | * 87 | * @return string 88 | */ 89 | private function getCategoryName($category): string 90 | { 91 | $prefix = $this->configProvider->getCategoryPrefix($category->getStoreId()); 92 | return $prefix . $this->escaper->escapeHtml($category->getName()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Model/Dcc/CatalogData/CatalogProduct/Family.php: -------------------------------------------------------------------------------- 1 | stringFormatter = $stringFormatter; 47 | $this->configProvider = $configProvider; 48 | $this->dccFamilyFactory = $dccFamilyFactory; 49 | } 50 | 51 | /** 52 | * @param null|\Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $product 53 | * @param string $familyCode 54 | * 55 | * @return \Bazaarvoice\Connector\Api\Data\Dcc\CatalogData\CatalogProduct\FamilyInterface 56 | */ 57 | public function build($product, $familyCode) 58 | { 59 | $dccFamily = $this->dccFamilyFactory->create(); 60 | $dccFamily->setId($familyCode); 61 | $dccFamily->setExpand($this->configProvider->isFamiliesExpandEnabled($product->getStoreId())); 62 | $dccFamily->setMembers([$this->getFamilyMember($product)]); 63 | 64 | return $dccFamily; 65 | } 66 | 67 | /** 68 | * @param \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $product 69 | * 70 | * @return string 71 | */ 72 | private function getFamilyMember($product): string 73 | { 74 | $prefix = ''; 75 | if ($this->configProvider->isProductPrefixEnabled($product->getStoreId())) { 76 | $prefix = $this->configProvider->getPrefix($product->getStoreId()); 77 | } 78 | return $prefix . $this->stringFormatter->getFormattedProductSku($product->getSku()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Model/Dcc/CatalogDataBuilder.php: -------------------------------------------------------------------------------- 1 | configProvider = $configProvider; 60 | $this->stringFormatter = $stringFormatter; 61 | $this->catalogProductBuilder = $catalogProductBuilder; 62 | $this->catalogDataFactory = $catalogDataFactory; 63 | } 64 | 65 | /** 66 | * @param \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $product 67 | * 68 | * @return \Bazaarvoice\Connector\Api\Data\Dcc\CatalogDataInterface 69 | */ 70 | public function build($product) 71 | { 72 | $dccCatalogData = $this->catalogDataFactory->create(); 73 | $dccCatalogData->setLocale($this->configProvider->getLocale($product->getStoreId())); 74 | $dccCatalogData->setCatalogProducts($this->getCatalogProducts($product)); 75 | return $dccCatalogData; 76 | } 77 | 78 | /** 79 | * @param \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $parentProduct 80 | * 81 | * @return array|null 82 | */ 83 | private function getCatalogProducts($parentProduct) 84 | { 85 | $parentData = $this->getCatalogProduct($parentProduct); 86 | $productData = [$parentData]; 87 | if ($parentProduct->getTypeId() == Configurable::TYPE_CODE 88 | && $this->configProvider->isFamiliesEnabled($parentProduct->getStoreId()) 89 | ) { 90 | $children = $parentProduct->getTypeInstance()->getUsedProducts($parentProduct); 91 | foreach ($children as $childProduct) { 92 | $childData = $this->getCatalogProduct($childProduct, $parentProduct); 93 | $productData[] = $childData; 94 | } 95 | } 96 | 97 | return $productData; 98 | } 99 | 100 | /** 101 | * @param \Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $product 102 | * @param null|\Magento\Catalog\Api\Data\ProductInterface|\Magento\Catalog\Model\Product $parentProduct 103 | * 104 | * @return array 105 | */ 106 | private function getCatalogProduct($product, $parentProduct = null) 107 | { 108 | $dccCatalogProduct = $this->catalogProductBuilder->build($product, $parentProduct); 109 | 110 | return $this->prepareOutput($dccCatalogProduct); 111 | } 112 | 113 | /** 114 | * @param $object 115 | * 116 | * @return array 117 | */ 118 | private function prepareOutput($object) 119 | { 120 | /** 121 | * @var \Magento\Framework\Model\AbstractModel $object 122 | */ 123 | return $this->stringFormatter->stripEmptyValues($object->getData()); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Model/Filesystem/Io/Sftp.php: -------------------------------------------------------------------------------- 1 | _connection->put($filename, $source, $mode); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Model/Indexer/Indexer.php: -------------------------------------------------------------------------------- 1 | eavIndexer = $eavIndexer; 48 | $this->flatIndexer = $flatIndexer; 49 | $this->scopeConfig = $scopeConfig; 50 | } 51 | 52 | /** 53 | * @throws \Exception 54 | */ 55 | public function executeFull() 56 | { 57 | if ($this->useFlatIndexer()) { 58 | $this->flatIndexer->executeFull(); 59 | } else { 60 | $this->eavIndexer->executeFull(); 61 | } 62 | } 63 | 64 | /** 65 | * @param array $ids 66 | * 67 | * @throws \Exception 68 | */ 69 | public function execute($ids = []) 70 | { 71 | if ($this->useFlatIndexer()) { 72 | $this->flatIndexer->execute($ids); 73 | } else { 74 | $this->eavIndexer->execute($ids); 75 | } 76 | } 77 | 78 | /** 79 | * @param array|\int[] $ids 80 | * 81 | * @return mixed 82 | */ 83 | public function executeList(array $ids) 84 | { 85 | return true; 86 | } 87 | 88 | /** 89 | * @param int $id 90 | * 91 | * @return mixed 92 | */ 93 | public function executeRow($id) 94 | { 95 | return true; 96 | } 97 | 98 | /** 99 | * @return bool 100 | */ 101 | protected function useFlatIndexer(): bool 102 | { 103 | return $this->scopeConfig->getValue('catalog/frontend/flat_catalog_product') 104 | && $this->scopeConfig->getValue('catalog/frontend/flat_catalog_category'); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Model/Notification.php: -------------------------------------------------------------------------------- 1 | _scheduleFactory = $scheduleFactory; 34 | } 35 | 36 | /** 37 | * @return mixed 38 | */ 39 | public function getIdentity() 40 | { 41 | return hash('sha256', 'bazaarvoice_cron'); 42 | } 43 | 44 | /** 45 | * @return mixed 46 | */ 47 | public function isDisplayed() 48 | { 49 | /** 50 | * TODO: Cron schedule does not keep long enough records 51 | * for this to be reliable. Find another way to track it. 52 | */ 53 | return false; 54 | } 55 | 56 | /** 57 | * @return mixed 58 | */ 59 | public function getText() 60 | { 61 | return __( 62 | 'Bazaarvoice PIE Feed doesn\'t appear to be running, please make sure your Magento cron job is running.', 63 | 'http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-cron.html#config-cli-cron-bkg' 64 | ); 65 | } 66 | 67 | /** 68 | * @return mixed 69 | */ 70 | public function getSeverity() 71 | { 72 | return MessageInterface::SEVERITY_MAJOR; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Model/ResourceModel/Index.php: -------------------------------------------------------------------------------- 1 | _init('bazaarvoice_index_product', 'entity_id'); 23 | } 24 | 25 | /** 26 | * @param array $attributes 27 | * 28 | * @return array 29 | * @throws \Magento\Framework\Exception\LocalizedException 30 | */ 31 | public function loadBy($attributes) 32 | { 33 | $adapter = $this->_resources->getConnection('core_read'); 34 | $where = []; 35 | foreach ($attributes as $attributeCode => $value) { 36 | $where[] = sprintf('%s=:%s', $attributeCode, $attributeCode); 37 | } 38 | 39 | $select = $adapter->select() 40 | ->from($this->getMainTable()) 41 | ->where(implode(' AND ', $where)); 42 | 43 | $binds = $attributes; 44 | 45 | return $adapter->fetchRow($select, $binds); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Model/ResourceModel/Index/Collection.php: -------------------------------------------------------------------------------- 1 | addFieldToFilter('store_id', $store->getId()); 28 | 29 | return $this; 30 | } 31 | 32 | protected function _construct() 33 | { 34 | $this->_init(IndexModel::class, IndexResourceModel::class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Model/Source/Category.php: -------------------------------------------------------------------------------- 1 | categoryCollection = $categoryCollection; 40 | } 41 | 42 | /** 43 | * @param int|string $value 44 | * 45 | * @return bool|string 46 | */ 47 | public function getOptionText($value) 48 | { 49 | return $value; 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public function toOptionArray() 56 | { 57 | return array_merge([['value' => '', 'label' => __('-- Please Select --')]], $this->getCategories()); 58 | } 59 | 60 | /** 61 | * @return array 62 | */ 63 | public function getAllOptions() 64 | { 65 | return $this->toOptionArray(); 66 | } 67 | 68 | /** 69 | * @return array 70 | */ 71 | public function getFlatColumns() 72 | { 73 | return [ 74 | ProductFeed::CATEGORY_EXTERNAL_ID => [ 75 | 'unsigned' => false, 76 | 'default' => null, 77 | 'extra' => null, 78 | 'type' => Table::TYPE_INTEGER, 79 | 'nullable' => true, 80 | 'comment' => 'Bazaarvoice Category ID', 81 | ], 82 | ]; 83 | } 84 | 85 | /** 86 | * @return array 87 | * @throws \Magento\Framework\Exception\LocalizedException 88 | */ 89 | private function getCategories() 90 | { 91 | if (!$this->categories) { 92 | $this->categories = []; 93 | $this->categoryCollection->addAttributeToSelect('name'); 94 | $this->categoryCollection->addAttributeToFilter('level', ['gt' => 1]); 95 | /** 96 | * @var \Magento\Catalog\Model\Category $category 97 | */ 98 | foreach ($this->categoryCollection as $category) { 99 | $names = []; 100 | foreach ($category->getParentCategories() as $parent) { 101 | $names[$parent->getId()] = $parent->getName(); 102 | } 103 | $names[$category->getId()] = $category->getName(); 104 | $name = implode('/', $names); 105 | $this->categories[] = [ 106 | 'value' => $category->getId(), 107 | 'label' => $name, 108 | ]; 109 | } 110 | } 111 | 112 | return $this->categories; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Model/Source/Environment.php: -------------------------------------------------------------------------------- 1 | self::STAGING, 29 | 'label' => __('Staging'), 30 | ], 31 | [ 32 | 'value' => self::PRODUCTION, 33 | 'label' => __('Production'), 34 | ], 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Model/Source/ProductAttribute.php: -------------------------------------------------------------------------------- 1 | productAttributeCollectionFactory = $attributeCollectionFactory; 34 | } 35 | 36 | /** 37 | * @param bool $isMultiselect 38 | * 39 | * @return array 40 | */ 41 | public function toOptionArray($isMultiselect = false) 42 | { 43 | $attributeOptions = []; 44 | if (!$isMultiselect) { 45 | $attributeOptions[] = [ 46 | 'label' => __('-- Please Select --'), 47 | 'value' => '' 48 | ]; 49 | } 50 | 51 | /** 52 | * @var AttributeCollection $attributes 53 | */ 54 | $attributes = $this->productAttributeCollectionFactory->create(); 55 | $attributes->addFieldToFilter('used_in_product_listing', '1'); 56 | 57 | /** 58 | * @var Attribute $attribute 59 | */ 60 | foreach ($attributes as $attribute) { 61 | $attributeOptions[] = [ 62 | 'label' => $attribute->getFrontendLabel(), 63 | 'value' => $attribute->getAttributeCode(), 64 | ]; 65 | } 66 | 67 | return $attributeOptions; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Model/Source/ProductList.php: -------------------------------------------------------------------------------- 1 | '', 38 | 'label' => __('None'), 39 | ], 40 | [ 41 | 'value' => self::CATEGORY, 42 | 'label' => __('Category and Search Result Pages'), 43 | ], 44 | [ 45 | 'value' => self::UPSELL, 46 | 'label' => __('Up-Sell Products on Product Pages'), 47 | ], 48 | [ 49 | 'value' => self::RELATED, 50 | 'label' => __('Related Products on Product Pages'), 51 | ], 52 | [ 53 | 'value' => self::CROSSSELL, 54 | 'label' => __('Cross-Sell Products on Cart Page'), 55 | ], 56 | [ 57 | 'value' => self::CATALOG_PRODUCTS_LIST_WIDGET, 58 | 'label' => __('Product List Widget'), 59 | ], 60 | [ 61 | 'value' => self::CATALOG_NEW_PRODUCTS_LIST_WIDGET, 62 | 'label' => __('Product New List Widget'), 63 | ], 64 | ]; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Model/Source/Scope.php: -------------------------------------------------------------------------------- 1 | self::SCOPE_GLOBAL, 31 | 'label' => __('Global'), 32 | ], 33 | [ 34 | 'value' => self::WEBSITE, 35 | 'label' => __('Magento Website'), 36 | ], 37 | [ 38 | 'value' => self::STORE_GROUP, 39 | 'label' => __('Magento Store / Store Group'), 40 | ], 41 | [ 42 | 'value' => self::STORE_VIEW, 43 | 'label' => __('Magento Store View'), 44 | ], 45 | ]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Model/Source/SftpHost.php: -------------------------------------------------------------------------------- 1 | self::BASE, 29 | 'label' => __('Non-European Clients (C1-C6)'), 30 | ], 31 | [ 32 | 'value' => self::EUROPE, 33 | 'label' => __('European Clients (C7)'), 34 | ], 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Model/Source/Trigger.php: -------------------------------------------------------------------------------- 1 | self::SHIPPING, 29 | 'label' => __('Shipping'), 30 | ], 31 | [ 32 | 'value' => self::PURCHASE, 33 | 'label' => __('Purchase'), 34 | ], 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Model/StringFormatter.php: -------------------------------------------------------------------------------- 1 | configProvider = $configProvider; 34 | } 35 | 36 | /** 37 | * This unique ID can only contain alphanumeric characters (letters and numbers 38 | * only) and also the asterisk, hyphen, and underscore characters. If your 39 | * product IDs contain invalid characters, simply replace them with an alternate 40 | * character like an underscore. This will only be used in the feed and not for 41 | * any customer facing purpose. 42 | * 43 | * @param string $rawId 44 | * 45 | * @return mixed 46 | */ 47 | public function replaceIllegalCharacters($rawId) 48 | { 49 | /** 50 | * Customizations go here 51 | */ 52 | $rawProductId = preg_replace_callback( 53 | '/\./s', function ($match) { 54 | return "_bv".ord($match[0])."_"; 55 | }, $rawId 56 | ); 57 | /** 58 | * No further customizations after this 59 | */ 60 | 61 | /** 62 | * We need to use a reversible replacement so that we can reconstruct the original ID later. 63 | * Example rawId = qwerty$%@#asdf 64 | * Example encoded = qwerty_bv36__bv37__bv64__bv35_asdf 65 | */ 66 | return preg_replace_callback( 67 | '/[^\w\d\*\-_]/s', function ($match) { 68 | return "_bv".ord($match[0])."_"; 69 | }, $rawProductId 70 | ); 71 | } 72 | 73 | /** 74 | * Get the uniquely identifying category ID for a catalog category. 75 | * 76 | * This is the unique, category or subcategory ID (duplicates are unacceptable). 77 | * This ID should be stable: it should not change for the same logical category even 78 | * if the category's name changes. 79 | * 80 | * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Catalog\Model\Category $category 81 | * @param int $storeId 82 | * 83 | * @return string The unique category ID to be used with Bazaarvoice 84 | */ 85 | public function getFormattedCategoryId($category, $storeId = null) 86 | { 87 | if ($this->configProvider->isCategoryIdUseUrlPathEnabled($storeId)) { 88 | $rawCategoryId = $category->getUrlPath(); 89 | $rawCategoryId = str_replace('/', '-', $rawCategoryId); 90 | $rawCategoryId = str_replace('.html', '', $rawCategoryId); 91 | return $this->replaceIllegalCharacters($rawCategoryId); 92 | } else { 93 | return $this->configProvider->getCategoryPrefix($storeId) . $category->getId(); 94 | } 95 | } 96 | 97 | /** 98 | * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Catalog\Model\Category $category 99 | * 100 | * @return mixed 101 | */ 102 | public function getFormattedCategoryPath($category) 103 | { 104 | return str_replace('/', '-', $category->getPath()); 105 | } 106 | 107 | /** 108 | * Get the uniquely identifying product ID for a catalog product. 109 | * 110 | * This is the unique, product family-level id (duplicates are unacceptable). 111 | * If a product has its own page, this is its product ID. It is not necessarily 112 | * the SKU ID, as we do not collect separate Ratings & Reviews for different 113 | * styles of product - i.e. the 'Blue' vs. 'Red Widget'. 114 | * 115 | * @param mixed $product a reference to a catalog product object 116 | * 117 | * @return string The unique product ID to be used with Bazaarvoice 118 | */ 119 | public function getFormattedProductSku($product) 120 | { 121 | if (is_object($product)) { 122 | $rawProductId = $product->getSku(); 123 | } else { 124 | $rawProductId = $product; 125 | } 126 | 127 | return $this->replaceIllegalCharacters($rawProductId); 128 | } 129 | 130 | /** 131 | * @param mixed $value 132 | * 133 | * @return string 134 | */ 135 | public function jsonEncode($value) 136 | { 137 | return json_encode($value, $options = JSON_UNESCAPED_UNICODE); 138 | } 139 | 140 | /** 141 | * json decode, sends original data if error 142 | * 143 | * @param $value 144 | * 145 | * @return mixed 146 | */ 147 | public function jsonDecode($value) 148 | { 149 | $result = json_decode($value, $assoc = true); 150 | if (json_last_error() != JSON_ERROR_NONE) { 151 | return $value; 152 | } 153 | 154 | return $result; 155 | } 156 | 157 | /** 158 | * @param string $delimeter 159 | * @param string $string 160 | * 161 | * @return array 162 | */ 163 | public function explodeAndTrim($delimeter, $string) 164 | { 165 | $data = explode($delimeter, $string); 166 | foreach ($data as $k => $v) { 167 | $data[$k] = trim($v); 168 | } 169 | 170 | return $data; 171 | } 172 | 173 | /** 174 | * @param array $data 175 | * 176 | * @return array 177 | */ 178 | public function stripEmptyValues($data) 179 | { 180 | return array_filter( 181 | $data, function ($a) { 182 | return !empty($a) || $a === false; //send false values 183 | } 184 | ); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /Model/XMLWriter.php: -------------------------------------------------------------------------------- 1 | startElement($name); 30 | $this->writeCdata($content); 31 | $this->endElement(); 32 | return true; 33 | } else { 34 | parent::writeElement($name, $content); 35 | return true; 36 | } 37 | } 38 | 39 | /** 40 | * @param null $content 41 | * @param bool $cdata 42 | * 43 | * @return bool|void 44 | */ 45 | public function writeRaw($content = null, $cdata = false): bool 46 | { 47 | $content = trim((string)$content); 48 | if ($cdata) { 49 | $this->writeCdata($content); 50 | return true; 51 | } else { 52 | parent::writeRaw($content); 53 | return true; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | partner-admin@bazaarvoice.com -------------------------------------------------------------------------------- /Observer/Config.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 48 | $this->indexer = $indexer; 49 | $this->messageManger = $messageManager; 50 | } 51 | 52 | /** 53 | * @param EventObserver $observer 54 | */ 55 | public function execute(EventObserver $observer) 56 | { 57 | $this->messageManger->addNoticeMessage(__('Some configuration changes may require rebuilding the Bazaarvoice Product Feed Index. This can be done by running the bv:index magento command or clicking Rebuild Index in Catalog > Bazaarvoice Product Feed')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Plugin/Disable.php: -------------------------------------------------------------------------------- 1 | configProvider = $configProvider; 34 | } 35 | 36 | /** 37 | * Prevents default Magento review functionality from displaying 38 | * 39 | * @param $subject 40 | * @param $result 41 | * 42 | * @return false|string 43 | */ 44 | public function afterToHtml($subject, $result) 45 | { 46 | if ($this->configProvider->isBvEnabled()) { 47 | return ''; 48 | } 49 | 50 | return $result; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Plugin/ProductList/Category.php: -------------------------------------------------------------------------------- 1 | configProvider = $configProvider; 47 | $this->stringFormatter = $stringFormatter; 48 | } 49 | 50 | /** 51 | * @param $subject 52 | * @param $product 53 | */ 54 | public function beforeGetProductPrice( 55 | /** @noinspection PhpUnusedParameterInspection */ 56 | // @codingStandardsIgnoreLine Squiz.Functions.MultiLineFunctionDeclaration.FirstParamSpacing 57 | $subject, 58 | $product 59 | ) { 60 | //todo: Combine with afterGetProductPrice into an around plugin? 61 | if ($this->isHostedInlineRatingsEnabled()) { 62 | $this->product = $product; 63 | } 64 | } 65 | 66 | /** 67 | * @return bool 68 | */ 69 | public function isHostedInlineRatingsEnabled() 70 | { 71 | if (!$this->configProvider->isRrEnabled()) { 72 | return false; 73 | } 74 | 75 | $inlineRatings = $this->configProvider->getInlineRatings(); 76 | 77 | if (!$inlineRatings) { 78 | return false; 79 | } 80 | 81 | $typesEnabled = explode(',', $inlineRatings); 82 | 83 | return in_array($this->type, $typesEnabled); 84 | } 85 | 86 | /** 87 | * @param $subject 88 | * @param $result 89 | * 90 | * @return string 91 | */ 92 | public function afterGetProductPrice( 93 | /** @noinspection PhpUnusedParameterInspection */ 94 | // @codingStandardsIgnoreLine Squiz.Functions.MultiLineFunctionDeclaration.FirstParamSpacing 95 | $subject, 96 | $result 97 | ) { 98 | //todo: Combine with afterGetProductPrice into an around plugin? 99 | if ($this->isHostedInlineRatingsEnabled()) { 100 | $productIdentifier = $this->stringFormatter->getFormattedProductSku($this->product); 101 | $productUrl = $this->product->getProductUrl(); 102 | $result = ' 103 | 104 |
'.$result; 108 | } 109 | 110 | return $result; 111 | } 112 | 113 | /** 114 | * @return string 115 | */ 116 | protected function getExtensionInjectionMessage() 117 | { 118 | return $this->configProvider->getExtensionInjectionMessage(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Plugin/ProductList/NewProductsWidget.php: -------------------------------------------------------------------------------- 1 | isHostedInlineRatingsEnabled()) { 36 | $this->product = $product; 37 | } 38 | } 39 | 40 | /** 41 | * @param $subject 42 | * @param $result 43 | * 44 | * @return string 45 | */ 46 | public function afterGetProductPriceHtml( 47 | /** @noinspection PhpUnusedParameterInspection */ 48 | // @codingStandardsIgnoreLine Squiz.Functions.MultiLineFunctionDeclaration.FirstParamSpacing 49 | $subject, 50 | $result 51 | ) { 52 | if ($this->isHostedInlineRatingsEnabled()) { 53 | $productIdentifier = $this->stringFormatter->getFormattedProductSku($this->product); 54 | $productUrl = $this->product->getProductUrl(); 55 | $result = ' 56 | 57 |
'.$result; 61 | } 62 | 63 | return $result; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Plugin/ProductList/Related.php: -------------------------------------------------------------------------------- 1 | isHostedInlineRatingsEnabled()) { 36 | $this->product = $product; 37 | } 38 | } 39 | 40 | /** 41 | * @param $subject 42 | * @param $result 43 | * 44 | * @return string 45 | */ 46 | public function afterGetProductPriceHtml( 47 | /** @noinspection PhpUnusedParameterInspection */ 48 | // @codingStandardsIgnoreLine Squiz.Functions.MultiLineFunctionDeclaration.FirstParamSpacing 49 | $subject, 50 | $result 51 | ) { 52 | if ($this->isHostedInlineRatingsEnabled()) { 53 | $productIdentifier = $this->stringFormatter->getFormattedProductSku($this->product); 54 | $productUrl = $this->product->getProductUrl(); 55 | $result = ' 56 | 57 |
'.$result; 61 | } 62 | 63 | return $result; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Bazaarvoice Magento 2 Integration Extension 2 | ============================================= 3 | 4 | [![Latest Stable Version](https://poser.pugx.org/bazaarvoice/bazaarvoice-magento2-ext/v/stable)](https://packagist.org/packages/bazaarvoice/bazaarvoice-magento2-ext) 5 | [![Total Downloads](https://poser.pugx.org/bazaarvoice/bazaarvoice-magento2-ext/downloads)](https://packagist.org/packages/bazaarvoice/bazaarvoice-magento2-ext) 6 | [![Latest Unstable Version](https://poser.pugx.org/bazaarvoice/bazaarvoice-magento2-ext/v/unstable)](https://packagist.org/packages/bazaarvoice/bazaarvoice-magento2-ext) 7 | [![License](https://poser.pugx.org/bazaarvoice/bazaarvoice-magento2-ext/license)](https://packagist.org/packages/bazaarvoice/bazaarvoice-magento2-ext) 8 | 9 | This is the official Magento 2 extension for Bazaarvoice. 10 | 11 | ## Getting Started 12 | 13 | Please visit our Bazaarvoice Knowledge website and start with our step-by-step integration guide for Magento 2: https://knowledge.bazaarvoice.com/wp-content/partnerintegrations/en_US/ecommerce.html#magento-2 14 | 15 | ## Installation via Composer 16 | 17 | You can install our Bazaarvoice Magento 2 extension via [Composer](http://getcomposer.org/). Please run these commands at the root of your Magento install: 18 | ```bash 19 | composer require bazaarvoice/bazaarvoice-magento2-ext 20 | php bin/magento module:enable Bazaarvoice_Connector 21 | php bin/magento setup:upgrade 22 | ``` 23 | 24 | ## Compatibility 25 | This extension is compatible with the newer Bazaarvoice Conversations offering. There is currently no extension available for the Magento 2 platform that is compatible with the older legacy Bazaarvoice Conversations PRR offering. 26 | 27 | Please go to https://knowledge.bazaarvoice.com/wp-content/partnerintegrations/en_US/ecommerce.html#magento-1x if you are looking for the Bazaarvoice Magento extension compatible with the older Magento 1 platform. 28 | -------------------------------------------------------------------------------- /Setup/Patch/Data/InstallBvAttribute.php: -------------------------------------------------------------------------------- 1 | salesSetupFactory = $salesSetupFactory; 51 | $this->moduleDataSetup = $moduleDataSetup; 52 | $this->eavSetupFactory = $eavSetupFactory; 53 | $this->categorySetupFactory = $categorySetupFactory; 54 | } 55 | 56 | /** 57 | * {@inheritdoc} 58 | */ 59 | public function apply() 60 | { 61 | $this->moduleDataSetup->getConnection()->startSetup(); 62 | /** @var SalesSetup $eavSetup */ 63 | $eavSetup = $this->salesSetupFactory->create(['setup' => $this->moduleDataSetup]); 64 | 65 | $eavSetup->addAttribute( 66 | Order::ENTITY, 67 | Connector\Model\Feed\PurchaseFeed::ALREADY_SENT_IN_FEED_FLAG, 68 | [ 69 | 'type' => Table::TYPE_INTEGER, 70 | 'visible' => false, 71 | 'required' => false, 72 | 'default' => 0, 73 | ] 74 | ); 75 | 76 | /** @var CategorySetup $eavSetup */ 77 | $eavSetup = $this->categorySetupFactory->create(['setup' => $this->moduleDataSetup]); 78 | 79 | $eavSetup->addAttribute( 80 | Product::ENTITY, 81 | Connector\Model\Feed\ProductFeed::INCLUDE_IN_FEED_FLAG, 82 | [ 83 | 'group' => 'Product Details', 84 | 'type' => 'int', 85 | 'frontend' => '', 86 | 'label' => 'Send in Bazaarvoice Product Feed', 87 | 'input' => 'boolean', 88 | 'class' => '', 89 | 'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean', 90 | 'global' => ScopedAttributeInterface::SCOPE_STORE, 91 | 'visible' => true, 92 | 'required' => false, 93 | 'user_defined' => false, 94 | 'default' => Boolean::VALUE_YES, 95 | 'apply_to' => '', 96 | 'visible_on_front' => false, 97 | 'is_used_in_grid' => true, 98 | 'is_visible_in_grid' => false, 99 | 'is_filterable_in_grid' => false, 100 | 'used_in_product_listing' => true 101 | ] 102 | ); 103 | 104 | $groupName = 'Autosettings'; 105 | $entityTypeId = $eavSetup->getEntityTypeId(Product::ENTITY); 106 | $attributeSetId = $eavSetup->getAttributeSetId($entityTypeId, 'Default'); 107 | 108 | $attribute = $eavSetup->getAttribute($entityTypeId, Connector\Model\Feed\ProductFeed::INCLUDE_IN_FEED_FLAG); 109 | if ($attribute && $attributeSetId) { 110 | $eavSetup->addAttributeToGroup( 111 | $entityTypeId, 112 | $attributeSetId, 113 | $groupName, 114 | $attribute['attribute_id'], 115 | 60 116 | ); 117 | } 118 | 119 | if ($attributeSetId && !$eavSetup->getAttributesNumberInGroup($entityTypeId, $attributeSetId, 'Product Details')) { 120 | $eavSetup->removeAttributeGroup($entityTypeId, $attributeSetId, 'Product Details'); 121 | } 122 | $this->moduleDataSetup->getConnection()->endSetup(); 123 | } 124 | 125 | /** 126 | * {@inheritdoc} 127 | */ 128 | public static function getDependencies() 129 | { 130 | return []; 131 | } 132 | 133 | /** 134 | * {@inheritdoc} 135 | */ 136 | public function getAliases() 137 | { 138 | return []; 139 | } 140 | 141 | /** 142 | * {@inheritdoc} 143 | */ 144 | public static function getVersion() 145 | { 146 | return '9.0.0'; 147 | } 148 | } -------------------------------------------------------------------------------- /Setup/Uninstall.php: -------------------------------------------------------------------------------- 1 | categorySetupFactory = $categorySetupFactory; 43 | $this->salesSetupFactory = $salesSetupFactory; 44 | } 45 | 46 | /** 47 | * Module uninstall code 48 | * 49 | * @param \Magento\Framework\Setup\SchemaSetupInterface $setup 50 | * @param \Magento\Framework\Setup\ModuleContextInterface $context 51 | * 52 | * @return void 53 | */ 54 | public function uninstall( 55 | SchemaSetupInterface $setup, 56 | ModuleContextInterface $context 57 | ) { 58 | $setup->startSetup(); 59 | 60 | $salesSetup = $this->salesSetupFactory->create(); 61 | $salesSetup->removeAttribute( 62 | Order::ENTITY, 63 | Connector\Model\Feed\PurchaseFeed::ALREADY_SENT_IN_FEED_FLAG 64 | ); 65 | 66 | $catalogSetup = $this->categorySetupFactory->create(); 67 | $entityTypeId = $catalogSetup->getEntityTypeId(Product::ENTITY); 68 | 69 | if ($catalogSetup->getAttribute($entityTypeId, 'bv_feed_exclude')) { 70 | $catalogSetup->removeAttribute($entityTypeId, 'bv_feed_exclude'); 71 | } 72 | 73 | if ($catalogSetup->getAttribute($entityTypeId, ProductFeed::INCLUDE_IN_FEED_FLAG)) { 74 | $catalogSetup->removeAttribute($entityTypeId, ProductFeed::INCLUDE_IN_FEED_FLAG); 75 | } 76 | 77 | if ($catalogSetup->getAttribute($entityTypeId, ProductFeed::CATEGORY_EXTERNAL_ID)) { 78 | $catalogSetup->removeAttribute($entityTypeId, ProductFeed::CATEGORY_EXTERNAL_ID); 79 | } 80 | 81 | $setup->endSetup(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Test/Unit/Model/DccTest.php: -------------------------------------------------------------------------------- 1 | objectManager->getConstructArguments($className); 36 | $dcc = $this->objectManager->getObject($className, $arguments); 37 | $result = $dcc->getJson(); 38 | 39 | $this->assertEmpty($result); 40 | } 41 | 42 | public function testBuildProductExistsSomeResult() 43 | { 44 | /** 45 | * @var \Bazaarvoice\Connector\Model\Dcc $dcc 46 | */ 47 | 48 | $currentProductProviderMock = $this->createPartialMock(CurrentProductProvider::class, ['getProduct']); 49 | $productMock = $this->getMockBuilder(ProductInterface::class) 50 | ->disableOriginalConstructor() 51 | ->getMockForAbstractClass(); 52 | $currentProductProviderMock->method('getProduct')->willReturn($productMock); 53 | 54 | $dccCatalogDataMock = $this->createPartialMock(CatalogData::class, ['getData']); 55 | $dccCatalogDataMock->method('getData')->willReturn('{}'); 56 | 57 | $dccCatalogDataBuilderMock = $this->createPartialMock(CatalogDataBuilder::class, ['build']); 58 | $dccCatalogDataBuilderMock->method('build')->willReturn($dccCatalogDataMock); 59 | 60 | $stringFormatterMock = $this->createPartialMock(StringFormatter::class, ['jsonEncode']); 61 | $stringFormatterMock->method('jsonEncode')->willReturn('{}'); 62 | 63 | $arguments = $this->objectManager->getConstructArguments(Dcc::class); 64 | $arguments['currentProductProvider'] = $currentProductProviderMock; 65 | $arguments['catalogDataBuilder'] = $dccCatalogDataBuilderMock; 66 | $arguments['stringFormatter'] = $stringFormatterMock; 67 | $dcc = $this->objectManager->getObject(Dcc::class, $arguments); 68 | $result = $dcc->getJson(); 69 | 70 | $this->assertNotEmpty($result); 71 | } 72 | 73 | protected function setUp() 74 | { 75 | $this->objectManager = new ObjectManager($this); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Ui/Component/Listing/Column/Bvproductindex/PageActions.php: -------------------------------------------------------------------------------- 1 | getData('name'); 28 | $id = 'X'; 29 | if (isset($item['entity_id'])) { 30 | $id = $item['entity_id']; 31 | } 32 | $item[$name]['view'] = [ 33 | 'href' => $this->getContext()->getUrl( 34 | 'adminhtml/bv_product_index/viewlog', 35 | ['id' => $id] 36 | ), 37 | 'label' => __('Edit'), 38 | ]; 39 | } 40 | } 41 | 42 | return $dataSource; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Ui/Component/Listing/Column/Json.php: -------------------------------------------------------------------------------- 1 | stringFormatter = $stringFormatter; 43 | parent::__construct($context, $uiComponentFactory, $components, $data); 44 | } 45 | 46 | /** 47 | * Prepare Data Source 48 | * 49 | * @param array $dataSource 50 | * 51 | * @return array 52 | */ 53 | public function prepareDataSource(array $dataSource) 54 | { 55 | if (isset($dataSource['data']['items'])) { 56 | $fieldName = $this->getData('name'); 57 | foreach ($dataSource['data']['items'] as & $item) { 58 | if (empty($item[$fieldName])) { 59 | continue; 60 | } 61 | $valueData = $this->stringFormatter->jsonDecode($item[$fieldName]); 62 | if (is_object($valueData) == true 63 | || is_array($valueData) == true 64 | ) { 65 | $html = ''; 66 | foreach ($valueData as $key => $value) { 67 | if (!is_numeric($key)) { 68 | $html .= "$key: "; 69 | } 70 | $html .= $this->truncate($value).'
'; 71 | } 72 | $item[$fieldName] = $html; 73 | } 74 | } 75 | } 76 | 77 | return $dataSource; 78 | } 79 | 80 | /** 81 | * @param $string 82 | * 83 | * @return string 84 | */ 85 | private function truncate($string) 86 | { 87 | if (strlen($string) > 45 && substr($string, 0, 4) != 'http') { 88 | $string = substr($string, 0, 45).'...'; 89 | } 90 | 91 | return $string; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Ui/Component/Listing/Column/Thumbnail.php: -------------------------------------------------------------------------------- 1 | getData('name'); 29 | foreach ($dataSource['data']['items'] as & $item) { 30 | $value = $item[$fieldName]; 31 | if ($value) { 32 | $item[$fieldName.'_src'] = $value; 33 | $item[$fieldName.'_alt'] = $fieldName; 34 | $item[$fieldName.'_link'] = $value; 35 | $item[$fieldName.'_orig_src'] = $value; 36 | } 37 | } 38 | } 39 | 40 | return $dataSource; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Ui/Component/Listing/DataProviders/Bv/Product/Index.php: -------------------------------------------------------------------------------- 1 | collection = $collectionFactory->create(); 38 | parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Ui/ReviewStaging/Review.php: -------------------------------------------------------------------------------- 1 | bvLogger = $bvLogger; 49 | $this->stringFormatter = $stringFormatter; 50 | $this->configProvider = $configProvider; 51 | } 52 | 53 | /** 54 | * @return ConfigProviderInterface 55 | */ 56 | public function getConfigProvider() 57 | { 58 | return $this->configProvider; 59 | } 60 | 61 | /** 62 | * @return mixed 63 | */ 64 | public function isBvEnabled() 65 | { 66 | return $this->configProvider->isBvEnabled(); 67 | } 68 | 69 | /** 70 | * @return mixed|string|null 71 | */ 72 | public function getExtensionInjectionMessage() 73 | { 74 | return $this->configProvider->getExtensionInjectionMessage(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /ViewModel/Questions.php: -------------------------------------------------------------------------------- 1 | bvLogger = $bvLogger; 63 | $this->configProvider = $configProvider; 64 | $this->stringFormatter = $stringFormatter; 65 | $this->seoContent = $seoContent; 66 | $this->currentProductProvider = $currentProductProvider; 67 | } 68 | 69 | /** 70 | * @return string 71 | */ 72 | public function getSeoContent() 73 | { 74 | return $this->seoContent->getQuestionAnswerSeoContent(); 75 | } 76 | 77 | /** 78 | * @return string 79 | */ 80 | public function getProductSku() 81 | { 82 | $currentProduct = $this->currentProductProvider->getProduct(); 83 | if ($currentProduct) { 84 | return $this->stringFormatter->getFormattedProductSku($currentProduct->getSku()); 85 | } 86 | 87 | return null; 88 | } 89 | 90 | /** 91 | * @return bool 92 | */ 93 | public function canShow() 94 | { 95 | return $this->configProvider->isQaEnabled(); 96 | } 97 | 98 | /** 99 | * @return string 100 | */ 101 | public function getExtensionInjectionMessage() 102 | { 103 | return $this->configProvider->getExtensionInjectionMessage(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ViewModel/Reviews.php: -------------------------------------------------------------------------------- 1 | bvLogger = $bvLogger; 63 | $this->configProvider = $configProvider; 64 | $this->stringFormatter = $stringFormatter; 65 | $this->seoContent = $seoContent; 66 | $this->currentProductProvider = $currentProductProvider; 67 | } 68 | 69 | /** 70 | * @return string 71 | */ 72 | public function getAggregateSEOContent() 73 | { 74 | return $this->seoContent->getAggregateSeoContent(); 75 | } 76 | 77 | /** 78 | * @return bool 79 | */ 80 | public function canShow() 81 | { 82 | return $this->configProvider->isRrEnabled(); 83 | } 84 | 85 | /** 86 | * @return false|string 87 | */ 88 | public function getSeoContent() 89 | { 90 | return $this->seoContent->getRatingsReviewsSeoContent(); 91 | } 92 | 93 | /** 94 | * @return string 95 | */ 96 | public function getProductSku() 97 | { 98 | $currentProduct = $this->currentProductProvider->getProduct(); 99 | if ($currentProduct) { 100 | return $this->stringFormatter->getFormattedProductSku($currentProduct->getSku()); 101 | } 102 | 103 | return null; 104 | } 105 | 106 | /** 107 | * @return string 108 | */ 109 | public function getExtensionInjectionMessage() 110 | { 111 | return $this->configProvider->getExtensionInjectionMessage(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bazaarvoice/bazaarvoice-magento2-ext", 3 | "description": "Bazaarvoice Magento 2 Integration Extension.", 4 | "type": "magento2-module", 5 | "license": [ 6 | "MIT" 7 | ], 8 | "version": "9.1.8", 9 | "autoload": { 10 | "files": [ 11 | "registration.php" 12 | ], 13 | "psr-4": { 14 | "Bazaarvoice\\Connector\\": "" 15 | } 16 | }, 17 | "require": { 18 | "php": "~7.0||~8.1.0||~8.2.0||~8.3.0" ,"magento/framework": "~100.1|~101.0|~102.0|~103.0|~104.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /etc/adminhtml/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Bazaarvoice\Connector\Model\Notification 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /etc/adminhtml/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /etc/adminhtml/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | main_site 12 | 1 13 | 0 14 | 15 | 16 | 1 17 | category,search 18 | 1 19 | 20 | 21 | 1 22 | 23 | 24 | 1 25 | purchase 26 | 30 27 | website 28 | productfeed.xml 29 | /import-inbox 30 | 1 31 | 1 32 | 0 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /etc/crontab.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 30 2 * * 6 11 | 12 | 13 | 0 1 * * * 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /etc/csp_whitelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | 11 | 12 | apps.bazaarvoice.com 13 | apps.nexus.bazaarvoice.com 14 | apps-stg.nexus.bazaarvoice.com 15 | analytics-static.ugc.bazaarvoice.com 16 | network.bazaarvoice.com 17 | network-stg.bazaarvoice.com 18 | display.ugc.bazaarvoice.com 19 | api.bazaarvoice.com 20 | stg.api.bazaarvoice.com 21 | mpsnare.iesnare.com 22 | 23 | 24 | 25 | 26 | api.bazaarvoice.com 27 | stg.api.bazaarvoice.com 28 | apps.bazaarvoice.com 29 | network.bazaarvoice.com 30 | network-stg.bazaarvoice.com 31 | 32 | 33 | 34 | 35 | display.ugc.bazaarvoice.com 36 | network.bazaarvoice.com 37 | network-stg.bazaarvoice.com 38 | network-a.bazaarvoice.com 39 | network-stg-a.bazaarvoice.com 40 | photos-uat-us.bazaarvoice.com 41 | img.youtube.com 42 | 43 | 44 | 45 | 46 | display.ugc.bazaarvoice.com 47 | 48 | 49 | 50 | 51 | display.ugc.bazaarvoice.com 52 | api.bazaarvoice.com 53 | stg.api.bazaarvoice.com 54 | 55 | 56 | 57 | 58 | api.bazaarvoice.com 59 | stg.api.bazaarvoice.com 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /etc/db_schema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /etc/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /etc/frontend/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /etc/indexer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | Bazaarvoice Product Feed Index 10 | Indexed data for Bazaarvoice Product Feed 11 | 12 | 13 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /etc/mview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /etc/webapi.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /phpdox.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | . 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /view/adminhtml/requirejs-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © Magento, Inc. All rights reserved. 3 | * See COPYING.txt for license details. 4 | */ 5 | 6 | var config = { 7 | map: { 8 | '*': { 9 | sftpTestConnection: 'Bazaarvoice_Connector/js/testconnection' 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /view/adminhtml/templates/system/config/testconnection.phtml: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /view/adminhtml/web/js/testconnection.js: -------------------------------------------------------------------------------- 1 | 2 | define( 3 | [ 4 | 'jquery', 5 | 'Magento_Ui/js/modal/alert', 6 | 'jquery/ui' 7 | ], function ($, alert) { 8 | 'use strict'; 9 | 10 | $.widget( 11 | 'mage.testConnection', { 12 | options: { 13 | url: '', 14 | elementId: '', 15 | successText: '', 16 | failedText: '', 17 | fieldMapping: '' 18 | }, 19 | 20 | /** 21 | * Bind handlers to events 22 | */ 23 | _create: function () { 24 | this._on( 25 | { 26 | 'click': $.proxy(this._connect, this) 27 | } 28 | ); 29 | }, 30 | 31 | /** 32 | * Method triggers an AJAX request to check SFTP connection 33 | * 34 | * @private 35 | */ 36 | _connect: function () { 37 | var result = this.options.failedText, 38 | element = $('#' + this.options.elementId), 39 | self = this, 40 | params = {}, 41 | msg = '', 42 | fieldToCheck = this.options.fieldToCheck || 'success'; 43 | 44 | element.removeClass('success').addClass('fail'); 45 | console.log($.parseJSON(this.options.fieldMapping)); 46 | $.each( 47 | $.parseJSON(this.options.fieldMapping), function (key, el) { 48 | params[key] = $('#' + el).val(); 49 | } 50 | ); 51 | console.log(params); 52 | $.ajax( 53 | { 54 | url: this.options.url, 55 | showLoader: true, 56 | data: params, 57 | headers: this.options.headers || {} 58 | } 59 | ).done( 60 | function (response) { 61 | if (response[fieldToCheck]) { 62 | element.removeClass('fail').addClass('success'); 63 | result = self.options.successText; 64 | } else { 65 | msg = response.errorMessage; 66 | 67 | if (msg) { 68 | alert( 69 | { 70 | content: msg 71 | } 72 | ); 73 | } 74 | } 75 | } 76 | ).always( 77 | function () { 78 | $('#' + self.options.elementId + '_result').text(result); 79 | } 80 | ); 81 | } 82 | } 83 | ); 84 | 85 | return $.mage.testConnection; 86 | } 87 | ); 88 | -------------------------------------------------------------------------------- /view/frontend/layout/bazaarvoice_pixel_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /view/frontend/layout/bazaarvoice_submission_container.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /view/frontend/layout/catalog_product_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Bazaarvoice\Connector\ViewModel\Product 13 | 14 | 15 | 16 | 17 | 18 | 19 | Bazaarvoice\Connector\ViewModel\Reviews 20 | 21 | 22 | 23 | 24 | 25 | 26 | Bazaarvoice\Connector\ViewModel\Reviews 27 | Reviews 28 | 100 29 | 30 | 31 | 32 | 33 | Bazaarvoice\Connector\ViewModel\Questions 34 | Questions 35 | 110 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /view/frontend/layout/checkout_onepage_success.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Bazaarvoice\Connector\ViewModel\Pixel 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /view/frontend/layout/customer_account.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /view/frontend/layout/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Bazaarvoice\Connector\ViewModel\Header 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /view/frontend/templates/checkout/onepage/success/bvpixel.phtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | getBvPixelEnabled()) : ?> 13 | 14 | canShowDebugDetails()) : ?> 15 | 16 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /view/frontend/templates/header.phtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | isBvEnabled()): ?> 13 | getConfigProvider()->getBvApiHostUrl(); ?> 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /view/frontend/templates/productheader.phtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | isBvEnabled() && $viewModel->getProduct()): ?> 13 | 14 | isConfigurable() && $viewModel->getConfigProvider()->isRrChildrenEnabled()): ?> 15 | 46 | 47 | isDccEnabled()) : ?> 48 | getDccConfig(); ?> 49 | canShowDebugDetails()) : ?> 50 | 51 | 52 | 53 | 79 | 80 | -------------------------------------------------------------------------------- /view/frontend/templates/qa/questions.phtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | canShow()) : ?> 13 | 14 | getSeoContent(); ?> 15 |
16 | 17 |
18 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | canShow()) : ?> 13 | 14 | getSeoContent(); ?> 15 |
16 | 17 |
18 | 7 | 8 | 9 | 10 | getViewModel(); ?> 11 | 12 | canShow()) : ?> 13 | 14 |
16 | getAggregateSEOContent() ?> 17 |
18 |