Version Notes
Plugin corresponds to version 6.0.2 of the Bazaarvoice platform
Download this release
Release Info
Developer | BV DTS |
Extension | Bazaarvoice_Connector |
Version | 6.3.3 |
Comparing to | |
See all releases |
Code changes from version 6.3.2.1 to 6.3.3
- app/code/local/Bazaarvoice/Connector/Block/Questions.php +8 -3
- app/code/local/Bazaarvoice/Connector/Block/Reviews.php +8 -3
- app/code/local/Bazaarvoice/Connector/Block/Roi/Beacon.php +1 -1
- app/code/local/Bazaarvoice/Connector/Model/ExportPurchaseFeed.php +1 -0
- app/code/local/Bazaarvoice/Connector/etc/config.xml +1 -1
- docs/{Integrations_Magento_for_Bazaarvoice_v6.3.2.1.pdf → Integrations_Magento_for_Bazaarvoice_v6.3.3.pdf} +0 -0
- lib/Bazaarvoice/BVFooter.php +129 -129
- lib/Bazaarvoice/BVUtility.php +254 -254
- lib/Bazaarvoice/bvseosdk.php +1048 -1041
- package.xml +4 -4
app/code/local/Bazaarvoice/Connector/Block/Questions.php
CHANGED
@@ -60,9 +60,14 @@ class Bazaarvoice_Connector_Block_Questions extends Mage_Core_Block_Template
|
|
60 |
if($this->getRequest()->getParam('bvreveal') == 'debug')
|
61 |
$params['bvreveal'] = 'debug';
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
|
68 |
return $seoContent;
|
60 |
if($this->getRequest()->getParam('bvreveal') == 'debug')
|
61 |
$params['bvreveal'] = 'debug';
|
62 |
|
63 |
+
try{
|
64 |
+
$bv = new BV($params);
|
65 |
+
$seoContent = $bv->questions->getContent();
|
66 |
+
$seoContent .= '<!-- BV Questions Parameters: ' . print_r($params, 1) . '-->';
|
67 |
+
} Catch (Exception $e) {
|
68 |
+
Mage::logException($e);
|
69 |
+
return;
|
70 |
+
}
|
71 |
}
|
72 |
|
73 |
return $seoContent;
|
app/code/local/Bazaarvoice/Connector/Block/Reviews.php
CHANGED
@@ -60,9 +60,14 @@ class Bazaarvoice_Connector_Block_Reviews extends Mage_Core_Block_Template
|
|
60 |
if($this->getRequest()->getParam('bvreveal') == 'debug')
|
61 |
$params['bvreveal'] = 'debug';
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
|
68 |
return $seoContent;
|
60 |
if($this->getRequest()->getParam('bvreveal') == 'debug')
|
61 |
$params['bvreveal'] = 'debug';
|
62 |
|
63 |
+
try{
|
64 |
+
$bv = new BV($params);
|
65 |
+
$seoContent = $bv->reviews->getContent();
|
66 |
+
$seoContent .= '<!-- BV Reviews Parameters: ' . print_r($params, 1) . '-->';
|
67 |
+
} Catch (Exception $e) {
|
68 |
+
Mage::logException($e);
|
69 |
+
return;
|
70 |
+
}
|
71 |
}
|
72 |
|
73 |
return $seoContent;
|
app/code/local/Bazaarvoice/Connector/Block/Roi/Beacon.php
CHANGED
@@ -86,7 +86,7 @@ class Bazaarvoice_Connector_Block_Roi_Beacon extends Mage_Core_Block_Template
|
|
86 |
}
|
87 |
$orderDetails['userId'] = $userId;
|
88 |
$orderDetails['email'] = $order->getCustomerEmail();
|
89 |
-
$orderDetails['nickname'] = $order->
|
90 |
// There is no 'deliveryDate' yet
|
91 |
$orderDetails['locale'] = Mage::getStoreConfig('bazaarvoice/general/locale', $order->getStoreId());
|
92 |
|
86 |
}
|
87 |
$orderDetails['userId'] = $userId;
|
88 |
$orderDetails['email'] = $order->getCustomerEmail();
|
89 |
+
$orderDetails['nickname'] = $order->getCustomerFirstname();
|
90 |
// There is no 'deliveryDate' yet
|
91 |
$orderDetails['locale'] = Mage::getStoreConfig('bazaarvoice/general/locale', $order->getStoreId());
|
92 |
|
app/code/local/Bazaarvoice/Connector/Model/ExportPurchaseFeed.php
CHANGED
@@ -490,6 +490,7 @@ class Bazaarvoice_Connector_Model_ExportPurchaseFeed extends Mage_Core_Model_Abs
|
|
490 |
$orderXml .= "<Interaction>\n";
|
491 |
// $orderXml .= ' <OrderID>' . $order->getIncrementId() . "</OrderID>\n";
|
492 |
$orderXml .= ' <EmailAddress>' . $order->getCustomerEmail() . "</EmailAddress>\n";
|
|
|
493 |
$orderXml .= ' <Locale>' . $store->getConfig('bazaarvoice/general/locale') . "</Locale>\n";
|
494 |
$orderXml .= ' <UserName>' . $order->getCustomerName() . "</UserName>\n";
|
495 |
if($order->getCustomerId()) {
|
490 |
$orderXml .= "<Interaction>\n";
|
491 |
// $orderXml .= ' <OrderID>' . $order->getIncrementId() . "</OrderID>\n";
|
492 |
$orderXml .= ' <EmailAddress>' . $order->getCustomerEmail() . "</EmailAddress>\n";
|
493 |
+
$orderXml .= ' <Nickname>' . $order->getCustomerFirstname() . "</Nickname>\n";
|
494 |
$orderXml .= ' <Locale>' . $store->getConfig('bazaarvoice/general/locale') . "</Locale>\n";
|
495 |
$orderXml .= ' <UserName>' . $order->getCustomerName() . "</UserName>\n";
|
496 |
if($order->getCustomerId()) {
|
app/code/local/Bazaarvoice/Connector/etc/config.xml
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
<config>
|
9 |
<modules>
|
10 |
<Bazaarvoice_Connector>
|
11 |
-
<version>6.3.
|
12 |
<depends>
|
13 |
<!-- no dependencies -->
|
14 |
</depends>
|
8 |
<config>
|
9 |
<modules>
|
10 |
<Bazaarvoice_Connector>
|
11 |
+
<version>6.3.3</version>
|
12 |
<depends>
|
13 |
<!-- no dependencies -->
|
14 |
</depends>
|
docs/{Integrations_Magento_for_Bazaarvoice_v6.3.2.1.pdf → Integrations_Magento_for_Bazaarvoice_v6.3.3.pdf}
RENAMED
Binary file
|
lib/Bazaarvoice/BVFooter.php
CHANGED
@@ -1,129 +1,129 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* BV PHP SEO SDK Footer
|
5 |
-
*/
|
6 |
-
class BVFooter {
|
7 |
-
const VERSION = '3.
|
8 |
-
|
9 |
-
private $base;
|
10 |
-
private $url;
|
11 |
-
private $access_method;
|
12 |
-
private $msg;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* BVFooter Class Constructor
|
16 |
-
*
|
17 |
-
* @access public
|
18 |
-
* @param array ($base) - base class parameters
|
19 |
-
* @param string ($url) - SEO url
|
20 |
-
* @param string ($access_method) - access method
|
21 |
-
* @param string ($msg) - build message
|
22 |
-
* @return object
|
23 |
-
*/
|
24 |
-
public function __construct($base, $access_method, $msg) {
|
25 |
-
$this->base = $base;
|
26 |
-
$this->access_method = $access_method;
|
27 |
-
$this->msg = $msg;
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* buildSDKFooter
|
32 |
-
*
|
33 |
-
* Returns hidden SDK footer.
|
34 |
-
*
|
35 |
-
* @access public
|
36 |
-
* @return string Html formatted footer.
|
37 |
-
*/
|
38 |
-
public function buildSDKFooter() {
|
39 |
-
$method_type = !empty($this->base->config['internal_file_path']) ? 'LOCAL' : 'CLOUD';
|
40 |
-
$access_method = $this->access_method;
|
41 |
-
$time_end = microtime(true);
|
42 |
-
|
43 |
-
if (!empty($this->base->start_time)) {
|
44 |
-
$exec_time = round(($time_end - $this->base->start_time) * 1000, 2);
|
45 |
-
} else {
|
46 |
-
$exec_time = 0;
|
47 |
-
}
|
48 |
-
$content_type = mb_strtoupper($this->base->config['content_type']);
|
49 |
-
$subject_type = mb_strtoupper($this->base->config['subject_type']);
|
50 |
-
|
51 |
-
$footer = "\n" . '<ul id="BVSEOSDK_meta" style="display:none !important;">';
|
52 |
-
$footer .= "\n" . ' <li data-bvseo="sdk">bvseo_sdk, p_sdk, ' . self::VERSION . '</li>';
|
53 |
-
$footer .= "\n" . ' <li data-bvseo="sp_mt">' . $method_type . ', ' . $access_method . ', ' . $exec_time . 'ms</li>';
|
54 |
-
$footer .= "\n" . ' <li data-bvseo="ct_st">' . $content_type . ', ' . $subject_type . '</li>';
|
55 |
-
if (!empty($this->msg)) {
|
56 |
-
$footer .= "\n" . ' <li data-bvseo="ms">bvseo-msg: ' . $this->msg . '</li>';
|
57 |
-
}
|
58 |
-
$footer .= "\n" . '</ul>';
|
59 |
-
|
60 |
-
return $footer;
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* buildSDKDebugFooter
|
65 |
-
*
|
66 |
-
* Returns hidden SDK debug footer.
|
67 |
-
*
|
68 |
-
* @access public
|
69 |
-
* @return string Html formatted debug footer.
|
70 |
-
*/
|
71 |
-
public function buildSDKDebugFooter() {
|
72 |
-
$staging = !empty($this->base->config['staging']) ? 'TRUE' : 'FALSE';
|
73 |
-
$testing = !empty($this->base->config['testing']) ? 'TRUE' : 'FALSE';
|
74 |
-
$sdk_enabled = !empty($this->base->config['seo_sdk_enabled']) ? 'TRUE' : 'FALSE';
|
75 |
-
$ssl_enabled = !empty($this->base->config['ssl_enabled']) ? 'TRUE' : 'FALSE';
|
76 |
-
$proxy_host = !empty($this->base->config['proxy_host']) ? $this->base->config['proxy_host'] : 'none';
|
77 |
-
$proxy_port = !empty($this->base->config['proxy_port']) ? $this->base->config['proxy_port'] : '0';
|
78 |
-
$local_seo_file_root = (!empty($this->base->config['load_seo_files_locally'])) ? $this->base->config['local_seo_file_root'] : 'FALSE';
|
79 |
-
$content_type = mb_strtoupper($this->base->config['content_type']);
|
80 |
-
$subject_type = mb_strtoupper($this->base->config['subject_type']);
|
81 |
-
if (!empty($this->base->config['page_params']['subject_id'])
|
82 |
-
&& !empty($this->base->config['page_params']['content_type'])
|
83 |
-
&& $this->base->config['page_params']['content_type'] == $this->base->config['content_type']) {
|
84 |
-
$subject_id = $this->base->config['page_params']['subject_id'];
|
85 |
-
} else {
|
86 |
-
$subject_id = $this->base->config['subject_id'];
|
87 |
-
}
|
88 |
-
|
89 |
-
$footer = "\n" . '<ul id="BVSEOSDK_DEBUG" style="display:none;">';
|
90 |
-
|
91 |
-
$footer .= "\n" . ' <li data-bvseo="staging">' . $staging . '</li>';
|
92 |
-
$footer .= "\n" . ' <li data-bvseo="testing">' . $testing . '</li>';
|
93 |
-
$footer .= "\n" . ' <li data-bvseo="seo.sdk.enabled">' . $sdk_enabled . '</li>';
|
94 |
-
if (!isset($this->base->config['subject_type']) || $this->base->config['subject_type'] != 'seller') {
|
95 |
-
$footer .= "\n" . ' <li data-bvseo="stagingS3Hostname">' . $this->base->bv_config['seo-domain']['staging'] . '</li>';
|
96 |
-
$footer .= "\n" . ' <li data-bvseo="productionS3Hostname">' . $this->base->bv_config['seo-domain']['production'] . '</li>';
|
97 |
-
$footer .= "\n" . ' <li data-bvseo="testingStagingS3Hostname">' . $this->base->bv_config['seo-domain']['testing_staging'] . '</li>';
|
98 |
-
$footer .= "\n" . ' <li data-bvseo="testingProductionS3Hostname">' . $this->base->bv_config['seo-domain']['testing_production'] . '</li>';
|
99 |
-
}
|
100 |
-
$footer .= "\n" . ' <li data-bvseo="proxyHost">' . $proxy_host . '</li>';
|
101 |
-
$footer .= "\n" . ' <li data-bvseo="proxyPort">' . $proxy_port . '</li>';
|
102 |
-
$footer .= "\n" . ' <li data-bvseo="seo.sdk.execution.timeout.bot">' . $this->base->config['execution_timeout_bot'] . '</li>';
|
103 |
-
$footer .= "\n" . ' <li data-bvseo="seo.sdk.execution.timeout">' . $this->base->config['execution_timeout'] . '</li>';
|
104 |
-
$footer .= "\n" . ' <li data-bvseo="localSEOFileRoot">' . $local_seo_file_root . '</li>';
|
105 |
-
$footer .= "\n" . ' <li data-bvseo="cloudKey">' . $this->base->config['cloud_key'] . '</li>';
|
106 |
-
$footer .= "\n" . ' <li data-bvseo="bv.root.folder">' . $this->base->config['bv_root_folder'] . '</li>';
|
107 |
-
$footer .= "\n" . ' <li data-bvseo="seo.sdk.charset">' . $this->base->config['charset'] . '</li>';
|
108 |
-
$footer .= "\n" . ' <li data-bvseo="seo.sdk.ssl.enabled">' . $ssl_enabled . '</li>';
|
109 |
-
$footer .= "\n" . ' <li data-bvseo="crawlerAgentPattern">' . $this->base->config['crawler_agent_pattern'] . '</li>';
|
110 |
-
$footer .= "\n" . ' <li data-bvseo="subjectID">' . urlencode($subject_id) . '</li>';
|
111 |
-
|
112 |
-
|
113 |
-
$footer .= "\n" . ' <li data-bvseo="en">' . $sdk_enabled . '</li>';
|
114 |
-
$footer .= "\n" . ' <li data-bvseo="pn">bvseo-' . $this->base->config['page'] . '</li>';
|
115 |
-
$footer .= "\n" . ' <li data-bvseo="userAgent">' . $_SERVER['HTTP_USER_AGENT'] . '</li>';
|
116 |
-
$footer .= "\n" . ' <li data-bvseo="pageURI">' . $this->base->config['page_url'] . '</li>';
|
117 |
-
$footer .= "\n" . ' <li data-bvseo="baseURI">' . $this->base->config['base_url'] . '</li>';
|
118 |
-
$footer .= "\n" . ' <li data-bvseo="contentType">' . $content_type . '</li>';
|
119 |
-
$footer .= "\n" . ' <li data-bvseo="subjectType">' . $subject_type . '</li>';
|
120 |
-
if (!empty($this->base->seo_url)) {
|
121 |
-
$footer .= "\n" . ' <li data-bvseo="contentURL">' . $this->base->seo_url . '</li>';
|
122 |
-
}
|
123 |
-
|
124 |
-
$footer .= "\n" . '</ul>';
|
125 |
-
|
126 |
-
return $footer;
|
127 |
-
}
|
128 |
-
|
129 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* BV PHP SEO SDK Footer
|
5 |
+
*/
|
6 |
+
class BVFooter {
|
7 |
+
const VERSION = '3.2.0';
|
8 |
+
|
9 |
+
private $base;
|
10 |
+
private $url;
|
11 |
+
private $access_method;
|
12 |
+
private $msg;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* BVFooter Class Constructor
|
16 |
+
*
|
17 |
+
* @access public
|
18 |
+
* @param array ($base) - base class parameters
|
19 |
+
* @param string ($url) - SEO url
|
20 |
+
* @param string ($access_method) - access method
|
21 |
+
* @param string ($msg) - build message
|
22 |
+
* @return object
|
23 |
+
*/
|
24 |
+
public function __construct($base, $access_method, $msg) {
|
25 |
+
$this->base = $base;
|
26 |
+
$this->access_method = $access_method;
|
27 |
+
$this->msg = $msg;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* buildSDKFooter
|
32 |
+
*
|
33 |
+
* Returns hidden SDK footer.
|
34 |
+
*
|
35 |
+
* @access public
|
36 |
+
* @return string Html formatted footer.
|
37 |
+
*/
|
38 |
+
public function buildSDKFooter() {
|
39 |
+
$method_type = !empty($this->base->config['internal_file_path']) ? 'LOCAL' : 'CLOUD';
|
40 |
+
$access_method = $this->access_method;
|
41 |
+
$time_end = microtime(true);
|
42 |
+
|
43 |
+
if (!empty($this->base->start_time)) {
|
44 |
+
$exec_time = round(($time_end - $this->base->start_time) * 1000, 2);
|
45 |
+
} else {
|
46 |
+
$exec_time = 0;
|
47 |
+
}
|
48 |
+
$content_type = mb_strtoupper($this->base->config['content_type']);
|
49 |
+
$subject_type = mb_strtoupper($this->base->config['subject_type']);
|
50 |
+
|
51 |
+
$footer = "\n" . '<ul id="BVSEOSDK_meta" style="display:none !important;">';
|
52 |
+
$footer .= "\n" . ' <li data-bvseo="sdk">bvseo_sdk, p_sdk, ' . self::VERSION . '</li>';
|
53 |
+
$footer .= "\n" . ' <li data-bvseo="sp_mt">' . $method_type . ', ' . $access_method . ', ' . $exec_time . 'ms</li>';
|
54 |
+
$footer .= "\n" . ' <li data-bvseo="ct_st">' . $content_type . ', ' . $subject_type . '</li>';
|
55 |
+
if (!empty($this->msg)) {
|
56 |
+
$footer .= "\n" . ' <li data-bvseo="ms">bvseo-msg: ' . $this->msg . '</li>';
|
57 |
+
}
|
58 |
+
$footer .= "\n" . '</ul>';
|
59 |
+
|
60 |
+
return $footer;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* buildSDKDebugFooter
|
65 |
+
*
|
66 |
+
* Returns hidden SDK debug footer.
|
67 |
+
*
|
68 |
+
* @access public
|
69 |
+
* @return string Html formatted debug footer.
|
70 |
+
*/
|
71 |
+
public function buildSDKDebugFooter() {
|
72 |
+
$staging = !empty($this->base->config['staging']) ? 'TRUE' : 'FALSE';
|
73 |
+
$testing = !empty($this->base->config['testing']) ? 'TRUE' : 'FALSE';
|
74 |
+
$sdk_enabled = !empty($this->base->config['seo_sdk_enabled']) ? 'TRUE' : 'FALSE';
|
75 |
+
$ssl_enabled = !empty($this->base->config['ssl_enabled']) ? 'TRUE' : 'FALSE';
|
76 |
+
$proxy_host = !empty($this->base->config['proxy_host']) ? $this->base->config['proxy_host'] : 'none';
|
77 |
+
$proxy_port = !empty($this->base->config['proxy_port']) ? $this->base->config['proxy_port'] : '0';
|
78 |
+
$local_seo_file_root = (!empty($this->base->config['load_seo_files_locally'])) ? $this->base->config['local_seo_file_root'] : 'FALSE';
|
79 |
+
$content_type = mb_strtoupper($this->base->config['content_type']);
|
80 |
+
$subject_type = mb_strtoupper($this->base->config['subject_type']);
|
81 |
+
if (!empty($this->base->config['page_params']['subject_id'])
|
82 |
+
&& !empty($this->base->config['page_params']['content_type'])
|
83 |
+
&& $this->base->config['page_params']['content_type'] == $this->base->config['content_type']) {
|
84 |
+
$subject_id = $this->base->config['page_params']['subject_id'];
|
85 |
+
} else {
|
86 |
+
$subject_id = $this->base->config['subject_id'];
|
87 |
+
}
|
88 |
+
|
89 |
+
$footer = "\n" . '<ul id="BVSEOSDK_DEBUG" style="display:none;">';
|
90 |
+
|
91 |
+
$footer .= "\n" . ' <li data-bvseo="staging">' . $staging . '</li>';
|
92 |
+
$footer .= "\n" . ' <li data-bvseo="testing">' . $testing . '</li>';
|
93 |
+
$footer .= "\n" . ' <li data-bvseo="seo.sdk.enabled">' . $sdk_enabled . '</li>';
|
94 |
+
if (!isset($this->base->config['subject_type']) || $this->base->config['subject_type'] != 'seller') {
|
95 |
+
$footer .= "\n" . ' <li data-bvseo="stagingS3Hostname">' . $this->base->bv_config['seo-domain']['staging'] . '</li>';
|
96 |
+
$footer .= "\n" . ' <li data-bvseo="productionS3Hostname">' . $this->base->bv_config['seo-domain']['production'] . '</li>';
|
97 |
+
$footer .= "\n" . ' <li data-bvseo="testingStagingS3Hostname">' . $this->base->bv_config['seo-domain']['testing_staging'] . '</li>';
|
98 |
+
$footer .= "\n" . ' <li data-bvseo="testingProductionS3Hostname">' . $this->base->bv_config['seo-domain']['testing_production'] . '</li>';
|
99 |
+
}
|
100 |
+
$footer .= "\n" . ' <li data-bvseo="proxyHost">' . $proxy_host . '</li>';
|
101 |
+
$footer .= "\n" . ' <li data-bvseo="proxyPort">' . $proxy_port . '</li>';
|
102 |
+
$footer .= "\n" . ' <li data-bvseo="seo.sdk.execution.timeout.bot">' . $this->base->config['execution_timeout_bot'] . '</li>';
|
103 |
+
$footer .= "\n" . ' <li data-bvseo="seo.sdk.execution.timeout">' . $this->base->config['execution_timeout'] . '</li>';
|
104 |
+
$footer .= "\n" . ' <li data-bvseo="localSEOFileRoot">' . $local_seo_file_root . '</li>';
|
105 |
+
$footer .= "\n" . ' <li data-bvseo="cloudKey">' . $this->base->config['cloud_key'] . '</li>';
|
106 |
+
$footer .= "\n" . ' <li data-bvseo="bv.root.folder">' . $this->base->config['bv_root_folder'] . '</li>';
|
107 |
+
$footer .= "\n" . ' <li data-bvseo="seo.sdk.charset">' . $this->base->config['charset'] . '</li>';
|
108 |
+
$footer .= "\n" . ' <li data-bvseo="seo.sdk.ssl.enabled">' . $ssl_enabled . '</li>';
|
109 |
+
$footer .= "\n" . ' <li data-bvseo="crawlerAgentPattern">' . $this->base->config['crawler_agent_pattern'] . '</li>';
|
110 |
+
$footer .= "\n" . ' <li data-bvseo="subjectID">' . urlencode($subject_id) . '</li>';
|
111 |
+
|
112 |
+
|
113 |
+
$footer .= "\n" . ' <li data-bvseo="en">' . $sdk_enabled . '</li>';
|
114 |
+
$footer .= "\n" . ' <li data-bvseo="pn">bvseo-' . $this->base->config['page'] . '</li>';
|
115 |
+
$footer .= "\n" . ' <li data-bvseo="userAgent">' . $_SERVER['HTTP_USER_AGENT'] . '</li>';
|
116 |
+
$footer .= "\n" . ' <li data-bvseo="pageURI">' . $this->base->config['page_url'] . '</li>';
|
117 |
+
$footer .= "\n" . ' <li data-bvseo="baseURI">' . $this->base->config['base_url'] . '</li>';
|
118 |
+
$footer .= "\n" . ' <li data-bvseo="contentType">' . $content_type . '</li>';
|
119 |
+
$footer .= "\n" . ' <li data-bvseo="subjectType">' . $subject_type . '</li>';
|
120 |
+
if (!empty($this->base->seo_url)) {
|
121 |
+
$footer .= "\n" . ' <li data-bvseo="contentURL">' . $this->base->seo_url . '</li>';
|
122 |
+
}
|
123 |
+
|
124 |
+
$footer .= "\n" . '</ul>';
|
125 |
+
|
126 |
+
return $footer;
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
lib/Bazaarvoice/BVUtility.php
CHANGED
@@ -1,254 +1,254 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Tick function for execTimer.
|
5 |
-
*
|
6 |
-
* @param int ($start) - start time in ms
|
7 |
-
* @param int ($exec_time_ms) - execution time in ms
|
8 |
-
* @param bool ($is_bot) - shows the mode in which script was run
|
9 |
-
*/
|
10 |
-
function tick_timer($start, $exec_time, $is_bot) {
|
11 |
-
static $once = true;
|
12 |
-
if ((microtime(1) - $start) > $exec_time) {
|
13 |
-
if ($once) {
|
14 |
-
$once = false;
|
15 |
-
throw new Exception('Execution timed out' . ($is_bot ? ' for search bot' : '') . ', exceeded ' . $exec_time * 1000 . 'ms');
|
16 |
-
}
|
17 |
-
}
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* BV PHP SEO SDK Utilities.
|
22 |
-
*/
|
23 |
-
class BVUtility {
|
24 |
-
public static $supportedContentTypes = array(
|
25 |
-
'r' => 'REVIEWS',
|
26 |
-
'q' => 'QUESTIONS',
|
27 |
-
's' => 'STORIES',
|
28 |
-
'u' => 'UNIVERSAL',
|
29 |
-
'sp'=> 'SPOTLIGHTS'
|
30 |
-
);
|
31 |
-
private static $supportedSubjectTypes = array(
|
32 |
-
'p' => 'PRODUCT',
|
33 |
-
'c' => 'CATEGORY',
|
34 |
-
'e' => 'ENTRY',
|
35 |
-
'd' => 'DETAIL',
|
36 |
-
's' => 'SELLER'
|
37 |
-
);
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Method used to limit execution time of the script.
|
41 |
-
*
|
42 |
-
* @access public
|
43 |
-
* @param int ($exec_time_ms) - execution time in ms
|
44 |
-
* @param bool ($is_bot) - shows the mode in which script was run
|
45 |
-
*/
|
46 |
-
public static function execTimer($exec_time_ms, $is_bot = false, $start = 0) {
|
47 |
-
$exec_time = $exec_time_ms / 1000;
|
48 |
-
declare(ticks = 1); // or more if 1 takes too much time
|
49 |
-
if (empty($start)) {
|
50 |
-
$start = microtime(1);
|
51 |
-
}
|
52 |
-
register_tick_function('tick_timer', $start, $exec_time, $is_bot);
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Method used to stop execution time checker.
|
57 |
-
*
|
58 |
-
* @access public
|
59 |
-
*/
|
60 |
-
public static function stopTimer() {
|
61 |
-
unregister_tick_function('tick_timer');
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Parse the provided "bvstate" parameter value.
|
66 |
-
*
|
67 |
-
* @access public
|
68 |
-
* @param string $bvstate - Value of the bvstate parameter.
|
69 |
-
* @return array - parsed "bvstate" parameters.
|
70 |
-
*/
|
71 |
-
public static function getBVStateHash($bvstate) {
|
72 |
-
$bvStateHash = array();
|
73 |
-
$bvp = mb_split("/", $bvstate);
|
74 |
-
foreach ($bvp as $param) {
|
75 |
-
$key = static::mb_trim(mb_substr($param, 0, mb_strpos($param, ':')));
|
76 |
-
$bvStateHash[$key] = static::mb_trim(mb_substr($param, mb_strpos($param, ':') + 1));
|
77 |
-
}
|
78 |
-
return $bvStateHash;
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Checks content type or subject type is supported.
|
83 |
-
* If type is not supported throw exception.
|
84 |
-
*
|
85 |
-
* @access public
|
86 |
-
* @param string ($type) - content type or subject type which have to be checked.
|
87 |
-
* @param string ($typeType) - default 'ct', mark of type 'ct' - content type, 'st' - subject type
|
88 |
-
* @return boolean True if type is correct and no exception was thrown.
|
89 |
-
*/
|
90 |
-
public static function checkType($type, $typeType = 'ct') {
|
91 |
-
if ($typeType == 'st') {
|
92 |
-
$typeName = 'subject type';
|
93 |
-
$typeArray = static::$supportedSubjectTypes;
|
94 |
-
} else {
|
95 |
-
$typeName = 'content type';
|
96 |
-
$typeArray = static::$supportedContentTypes;
|
97 |
-
}
|
98 |
-
if (!array_key_exists(mb_strtolower($type), $typeArray)) {
|
99 |
-
foreach ($typeArray as $key => $value) {
|
100 |
-
$supportList[] = $key . '=' . $value;
|
101 |
-
}
|
102 |
-
throw new Exception('Obtained not supported ' . $typeName
|
103 |
-
. '. BV Class supports following ' . $typeName . ': '
|
104 |
-
. implode(', ', $supportList));
|
105 |
-
}
|
106 |
-
|
107 |
-
return true;
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Generates an array of parameters from the bvstate parameter value.
|
112 |
-
*
|
113 |
-
* @access public
|
114 |
-
* @param string $bvstate - "bvstate" parameter value.
|
115 |
-
* @return array - array of parameters that are ready to use in script.
|
116 |
-
*/
|
117 |
-
public static function getBVStateParams($bvstate) {
|
118 |
-
$bvStateHash = self::getBVStateHash($bvstate);
|
119 |
-
$params = array();
|
120 |
-
|
121 |
-
// If the content type 'ct' parameter is not present, then ignore bvstate.
|
122 |
-
if (empty($bvStateHash['ct'])) {
|
123 |
-
return $params;
|
124 |
-
}
|
125 |
-
|
126 |
-
if (!empty($bvStateHash)) {
|
127 |
-
if (!empty($bvStateHash['id'])) {
|
128 |
-
$params['subject_id'] = $bvStateHash['id'];
|
129 |
-
}
|
130 |
-
if (!empty($bvStateHash['pg'])) {
|
131 |
-
$params['page'] = $bvStateHash['pg'];
|
132 |
-
}
|
133 |
-
if (!empty($bvStateHash['ct'])) {
|
134 |
-
$cType = $bvStateHash['ct'];
|
135 |
-
self::checkType($cType, 'ct');
|
136 |
-
$params['content_type'] = mb_strtolower(self::$supportedContentTypes[$cType]);
|
137 |
-
}
|
138 |
-
if (!empty($bvStateHash['st'])) {
|
139 |
-
$sType = $bvStateHash['st'];
|
140 |
-
self::checkType($sType, 'st');
|
141 |
-
$params['subject_type'] = mb_strtolower(self::$supportedSubjectTypes[$sType]);
|
142 |
-
}
|
143 |
-
if (!empty($bvStateHash['reveal'])) {
|
144 |
-
$params['bvreveal'] = $bvStateHash['reveal'];
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
if (!empty($params)) {
|
149 |
-
// This acts as a flag to tell us that a useful bvstate value was in fact
|
150 |
-
// extracted from the URL.
|
151 |
-
$params['base_url_bvstate'] = TRUE;
|
152 |
-
}
|
153 |
-
if (empty($params['page'])) {
|
154 |
-
$params['page'] = '1';
|
155 |
-
}
|
156 |
-
|
157 |
-
return $params;
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Parse name=value parameters from the URL query string, fragment, and
|
162 |
-
* _escaped_fragment_.
|
163 |
-
*
|
164 |
-
* @access public
|
165 |
-
* @param string ($url) - The URL.
|
166 |
-
* @return array - An array of parameters values indexed by parameter names.
|
167 |
-
*/
|
168 |
-
public static function parseUrlParameters($url) {
|
169 |
-
// Why are we doing things in this devious way? The answer is to be as
|
170 |
-
// multibyte-supportive as possible. Most of the URL-parsing tools in the
|
171 |
-
// toolbox appear to be only varying degrees of multibyte-supportive; good
|
172 |
-
// for UTF-8 but not so great if you venture beyond that.
|
173 |
-
|
174 |
-
// Break down the URL into a mix of things, some of which are name=value
|
175 |
-
// pairs.
|
176 |
-
$params = array();
|
177 |
-
$chunks = mb_split('\?|&|&|#!|#|_escaped_fragment_=|%26', $url);
|
178 |
-
foreach ($chunks as $chunk) {
|
179 |
-
// If this is name=value, then there will be two items.
|
180 |
-
$values = mb_split('=', $chunk);
|
181 |
-
if (sizeof($values) == 2) {
|
182 |
-
// Since we're moving left to right in the URL, and we want query string
|
183 |
-
// to win over fragment if there are the same parameters in both, then
|
184 |
-
// only add if not already there.
|
185 |
-
if (!isset($params[$values[0]])) {
|
186 |
-
$params[$values[0]] = $values[1];
|
187 |
-
}
|
188 |
-
}
|
189 |
-
}
|
190 |
-
return $params;
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Remove a parameter from the provided URL.
|
195 |
-
*
|
196 |
-
* This will remove the named parameter wherever it occurs as name=value in
|
197 |
-
* the URL via a simple regex replacement. This is crude but the most
|
198 |
-
* straightforward way of going about this in PHP.
|
199 |
-
*
|
200 |
-
* If there is a query string delimeter following the name=value parameter
|
201 |
-
* then that will also be removed.
|
202 |
-
*
|
203 |
-
* E.g. we're expecting to remove the bvstate from URLs such as:
|
204 |
-
*
|
205 |
-
* http://example.com/product/123?bvstate=pg:4/ct:r
|
206 |
-
* http://example.com/product/123#!bvstate=pg:4/ct:r
|
207 |
-
*
|
208 |
-
* This will only be used for Bazaarvoice SEO parameters, so apologies in
|
209 |
-
* advance to the one person in the universe for whom bvstate=xyz is a vital
|
210 |
-
* part of the URL path.
|
211 |
-
*
|
212 |
-
* Note that the fragment isn't passed to the server, so we're not really
|
213 |
-
* going to see that in practice. Attention is given to that here for the
|
214 |
-
* sake of completeness.
|
215 |
-
*
|
216 |
-
* @access public
|
217 |
-
* @param string ($url) - The URL.
|
218 |
-
* @param string ($paramName) - Name of the parameter to be removed.
|
219 |
-
* @return string - The updated URL.
|
220 |
-
*/
|
221 |
-
public static function removeUrlParam($url, $paramName) {
|
222 |
-
// The ereg POSIX regex functions are all greedy all the time, which makes
|
223 |
-
// this harder than it has to be.
|
224 |
-
//
|
225 |
-
// Big assumption: our seo link values will never contain the % character.
|
226 |
-
//
|
227 |
-
// http://example.com/product/123?bvstate=pg:4/ct:r&a=b
|
228 |
-
$url = mb_ereg_replace($paramName . '=[^&#%]*&', '', $url);
|
229 |
-
// http://example.com/product/123?bvstate=pg:4/ct:r&a=b
|
230 |
-
// http://example.com/product/123?#!bvstate=pg:4/ct:r&a=b
|
231 |
-
// http://example.com/product/123?_escaped_fragment_=bvstate=pg:4/ct:r%26a=b
|
232 |
-
$url = mb_ereg_replace($paramName . '=[^&#%]*(&|%26)', '', $url);
|
233 |
-
// http://example.com/product/123?bvstate=pg:4/ct:r#!x/y/z
|
234 |
-
$url = mb_ereg_replace($paramName . '=[^&#]*#', '#', $url);
|
235 |
-
// This one last as it will break everything if we haven't already dealt
|
236 |
-
// with all of the cases, since .* is always greedy in POSIX regex.
|
237 |
-
// http://example.com/product/123?bvstate=pg:4/ct:r
|
238 |
-
$url = mb_ereg_replace($paramName . '=[^&#%]*$', '', $url);
|
239 |
-
return $url;
|
240 |
-
}
|
241 |
-
|
242 |
-
/**
|
243 |
-
* A multibyte-safe trim.
|
244 |
-
* (http://stackoverflow.com/questions/10066647/multibyte-trim-in-php/10067670#10067670)
|
245 |
-
*
|
246 |
-
* @access public
|
247 |
-
* @param string ($str) - The string that will be trimmed.
|
248 |
-
* @return string - The trimmed string.
|
249 |
-
*/
|
250 |
-
public static function mb_trim($str) {
|
251 |
-
return mb_ereg_replace('(^\s+)|(\s+$)', '', $str);
|
252 |
-
}
|
253 |
-
|
254 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Tick function for execTimer.
|
5 |
+
*
|
6 |
+
* @param int ($start) - start time in ms
|
7 |
+
* @param int ($exec_time_ms) - execution time in ms
|
8 |
+
* @param bool ($is_bot) - shows the mode in which script was run
|
9 |
+
*/
|
10 |
+
function tick_timer($start, $exec_time, $is_bot) {
|
11 |
+
static $once = true;
|
12 |
+
if ((microtime(1) - $start) > $exec_time) {
|
13 |
+
if ($once) {
|
14 |
+
$once = false;
|
15 |
+
throw new Exception('Execution timed out' . ($is_bot ? ' for search bot' : '') . ', exceeded ' . $exec_time * 1000 . 'ms');
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* BV PHP SEO SDK Utilities.
|
22 |
+
*/
|
23 |
+
class BVUtility {
|
24 |
+
public static $supportedContentTypes = array(
|
25 |
+
'r' => 'REVIEWS',
|
26 |
+
'q' => 'QUESTIONS',
|
27 |
+
's' => 'STORIES',
|
28 |
+
'u' => 'UNIVERSAL',
|
29 |
+
'sp'=> 'SPOTLIGHTS'
|
30 |
+
);
|
31 |
+
private static $supportedSubjectTypes = array(
|
32 |
+
'p' => 'PRODUCT',
|
33 |
+
'c' => 'CATEGORY',
|
34 |
+
'e' => 'ENTRY',
|
35 |
+
'd' => 'DETAIL',
|
36 |
+
's' => 'SELLER'
|
37 |
+
);
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Method used to limit execution time of the script.
|
41 |
+
*
|
42 |
+
* @access public
|
43 |
+
* @param int ($exec_time_ms) - execution time in ms
|
44 |
+
* @param bool ($is_bot) - shows the mode in which script was run
|
45 |
+
*/
|
46 |
+
public static function execTimer($exec_time_ms, $is_bot = false, $start = 0) {
|
47 |
+
$exec_time = $exec_time_ms / 1000;
|
48 |
+
declare(ticks = 1); // or more if 1 takes too much time
|
49 |
+
if (empty($start)) {
|
50 |
+
$start = microtime(1);
|
51 |
+
}
|
52 |
+
register_tick_function('tick_timer', $start, $exec_time, $is_bot);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Method used to stop execution time checker.
|
57 |
+
*
|
58 |
+
* @access public
|
59 |
+
*/
|
60 |
+
public static function stopTimer() {
|
61 |
+
unregister_tick_function('tick_timer');
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Parse the provided "bvstate" parameter value.
|
66 |
+
*
|
67 |
+
* @access public
|
68 |
+
* @param string $bvstate - Value of the bvstate parameter.
|
69 |
+
* @return array - parsed "bvstate" parameters.
|
70 |
+
*/
|
71 |
+
public static function getBVStateHash($bvstate) {
|
72 |
+
$bvStateHash = array();
|
73 |
+
$bvp = mb_split("/", $bvstate);
|
74 |
+
foreach ($bvp as $param) {
|
75 |
+
$key = static::mb_trim(mb_substr($param, 0, mb_strpos($param, ':')));
|
76 |
+
$bvStateHash[$key] = static::mb_trim(mb_substr($param, mb_strpos($param, ':') + 1));
|
77 |
+
}
|
78 |
+
return $bvStateHash;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Checks content type or subject type is supported.
|
83 |
+
* If type is not supported throw exception.
|
84 |
+
*
|
85 |
+
* @access public
|
86 |
+
* @param string ($type) - content type or subject type which have to be checked.
|
87 |
+
* @param string ($typeType) - default 'ct', mark of type 'ct' - content type, 'st' - subject type
|
88 |
+
* @return boolean True if type is correct and no exception was thrown.
|
89 |
+
*/
|
90 |
+
public static function checkType($type, $typeType = 'ct') {
|
91 |
+
if ($typeType == 'st') {
|
92 |
+
$typeName = 'subject type';
|
93 |
+
$typeArray = static::$supportedSubjectTypes;
|
94 |
+
} else {
|
95 |
+
$typeName = 'content type';
|
96 |
+
$typeArray = static::$supportedContentTypes;
|
97 |
+
}
|
98 |
+
if (!array_key_exists(mb_strtolower($type), $typeArray)) {
|
99 |
+
foreach ($typeArray as $key => $value) {
|
100 |
+
$supportList[] = $key . '=' . $value;
|
101 |
+
}
|
102 |
+
throw new Exception('Obtained not supported ' . $typeName
|
103 |
+
. '. BV Class supports following ' . $typeName . ': '
|
104 |
+
. implode(', ', $supportList));
|
105 |
+
}
|
106 |
+
|
107 |
+
return true;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Generates an array of parameters from the bvstate parameter value.
|
112 |
+
*
|
113 |
+
* @access public
|
114 |
+
* @param string $bvstate - "bvstate" parameter value.
|
115 |
+
* @return array - array of parameters that are ready to use in script.
|
116 |
+
*/
|
117 |
+
public static function getBVStateParams($bvstate) {
|
118 |
+
$bvStateHash = self::getBVStateHash($bvstate);
|
119 |
+
$params = array();
|
120 |
+
|
121 |
+
// If the content type 'ct' parameter is not present, then ignore bvstate.
|
122 |
+
if (empty($bvStateHash['ct'])) {
|
123 |
+
return $params;
|
124 |
+
}
|
125 |
+
|
126 |
+
if (!empty($bvStateHash)) {
|
127 |
+
if (!empty($bvStateHash['id'])) {
|
128 |
+
$params['subject_id'] = $bvStateHash['id'];
|
129 |
+
}
|
130 |
+
if (!empty($bvStateHash['pg'])) {
|
131 |
+
$params['page'] = $bvStateHash['pg'];
|
132 |
+
}
|
133 |
+
if (!empty($bvStateHash['ct'])) {
|
134 |
+
$cType = $bvStateHash['ct'];
|
135 |
+
self::checkType($cType, 'ct');
|
136 |
+
$params['content_type'] = mb_strtolower(self::$supportedContentTypes[$cType]);
|
137 |
+
}
|
138 |
+
if (!empty($bvStateHash['st'])) {
|
139 |
+
$sType = $bvStateHash['st'];
|
140 |
+
self::checkType($sType, 'st');
|
141 |
+
$params['subject_type'] = mb_strtolower(self::$supportedSubjectTypes[$sType]);
|
142 |
+
}
|
143 |
+
if (!empty($bvStateHash['reveal'])) {
|
144 |
+
$params['bvreveal'] = $bvStateHash['reveal'];
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
if (!empty($params)) {
|
149 |
+
// This acts as a flag to tell us that a useful bvstate value was in fact
|
150 |
+
// extracted from the URL.
|
151 |
+
$params['base_url_bvstate'] = TRUE;
|
152 |
+
}
|
153 |
+
if (empty($params['page'])) {
|
154 |
+
$params['page'] = '1';
|
155 |
+
}
|
156 |
+
|
157 |
+
return $params;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Parse name=value parameters from the URL query string, fragment, and
|
162 |
+
* _escaped_fragment_.
|
163 |
+
*
|
164 |
+
* @access public
|
165 |
+
* @param string ($url) - The URL.
|
166 |
+
* @return array - An array of parameters values indexed by parameter names.
|
167 |
+
*/
|
168 |
+
public static function parseUrlParameters($url) {
|
169 |
+
// Why are we doing things in this devious way? The answer is to be as
|
170 |
+
// multibyte-supportive as possible. Most of the URL-parsing tools in the
|
171 |
+
// toolbox appear to be only varying degrees of multibyte-supportive; good
|
172 |
+
// for UTF-8 but not so great if you venture beyond that.
|
173 |
+
|
174 |
+
// Break down the URL into a mix of things, some of which are name=value
|
175 |
+
// pairs.
|
176 |
+
$params = array();
|
177 |
+
$chunks = mb_split('\?|&|&|#!|#|_escaped_fragment_=|%26', $url);
|
178 |
+
foreach ($chunks as $chunk) {
|
179 |
+
// If this is name=value, then there will be two items.
|
180 |
+
$values = mb_split('=', $chunk);
|
181 |
+
if (sizeof($values) == 2) {
|
182 |
+
// Since we're moving left to right in the URL, and we want query string
|
183 |
+
// to win over fragment if there are the same parameters in both, then
|
184 |
+
// only add if not already there.
|
185 |
+
if (!isset($params[$values[0]])) {
|
186 |
+
$params[$values[0]] = $values[1];
|
187 |
+
}
|
188 |
+
}
|
189 |
+
}
|
190 |
+
return $params;
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Remove a parameter from the provided URL.
|
195 |
+
*
|
196 |
+
* This will remove the named parameter wherever it occurs as name=value in
|
197 |
+
* the URL via a simple regex replacement. This is crude but the most
|
198 |
+
* straightforward way of going about this in PHP.
|
199 |
+
*
|
200 |
+
* If there is a query string delimeter following the name=value parameter
|
201 |
+
* then that will also be removed.
|
202 |
+
*
|
203 |
+
* E.g. we're expecting to remove the bvstate from URLs such as:
|
204 |
+
*
|
205 |
+
* http://example.com/product/123?bvstate=pg:4/ct:r
|
206 |
+
* http://example.com/product/123#!bvstate=pg:4/ct:r
|
207 |
+
*
|
208 |
+
* This will only be used for Bazaarvoice SEO parameters, so apologies in
|
209 |
+
* advance to the one person in the universe for whom bvstate=xyz is a vital
|
210 |
+
* part of the URL path.
|
211 |
+
*
|
212 |
+
* Note that the fragment isn't passed to the server, so we're not really
|
213 |
+
* going to see that in practice. Attention is given to that here for the
|
214 |
+
* sake of completeness.
|
215 |
+
*
|
216 |
+
* @access public
|
217 |
+
* @param string ($url) - The URL.
|
218 |
+
* @param string ($paramName) - Name of the parameter to be removed.
|
219 |
+
* @return string - The updated URL.
|
220 |
+
*/
|
221 |
+
public static function removeUrlParam($url, $paramName) {
|
222 |
+
// The ereg POSIX regex functions are all greedy all the time, which makes
|
223 |
+
// this harder than it has to be.
|
224 |
+
//
|
225 |
+
// Big assumption: our seo link values will never contain the % character.
|
226 |
+
//
|
227 |
+
// http://example.com/product/123?bvstate=pg:4/ct:r&a=b
|
228 |
+
$url = mb_ereg_replace($paramName . '=[^&#%]*&', '', $url);
|
229 |
+
// http://example.com/product/123?bvstate=pg:4/ct:r&a=b
|
230 |
+
// http://example.com/product/123?#!bvstate=pg:4/ct:r&a=b
|
231 |
+
// http://example.com/product/123?_escaped_fragment_=bvstate=pg:4/ct:r%26a=b
|
232 |
+
$url = mb_ereg_replace($paramName . '=[^&#%]*(&|%26)', '', $url);
|
233 |
+
// http://example.com/product/123?bvstate=pg:4/ct:r#!x/y/z
|
234 |
+
$url = mb_ereg_replace($paramName . '=[^&#]*#', '#', $url);
|
235 |
+
// This one last as it will break everything if we haven't already dealt
|
236 |
+
// with all of the cases, since .* is always greedy in POSIX regex.
|
237 |
+
// http://example.com/product/123?bvstate=pg:4/ct:r
|
238 |
+
$url = mb_ereg_replace($paramName . '=[^&#%]*$', '', $url);
|
239 |
+
return $url;
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* A multibyte-safe trim.
|
244 |
+
* (http://stackoverflow.com/questions/10066647/multibyte-trim-in-php/10067670#10067670)
|
245 |
+
*
|
246 |
+
* @access public
|
247 |
+
* @param string ($str) - The string that will be trimmed.
|
248 |
+
* @return string - The trimmed string.
|
249 |
+
*/
|
250 |
+
public static function mb_trim($str) {
|
251 |
+
return mb_ereg_replace('(^\s+)|(\s+$)', '', $str);
|
252 |
+
}
|
253 |
+
|
254 |
+
}
|
lib/Bazaarvoice/bvseosdk.php
CHANGED
@@ -1,1041 +1,1048 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* BV PHP SEO SDK
|
5 |
-
*
|
6 |
-
* Base code to power either SEO or SEO and display. This SDK
|
7 |
-
* is provided as is and Bazaarvoice, Inc. is not responsible
|
8 |
-
* for future maintenance or support. You are free to modify
|
9 |
-
* this SDK as needed to suit your needs.
|
10 |
-
*
|
11 |
-
* This SDK was built with the following assumptions:
|
12 |
-
* - you are running PHP 5 or greater
|
13 |
-
* - you have the curl library installed
|
14 |
-
* - every request has the user agent header
|
15 |
-
* in it (if using a CDN like Akamai additional configuration
|
16 |
-
* maybe required).
|
17 |
-
*
|
18 |
-
*/
|
19 |
-
/**
|
20 |
-
* Example usage:
|
21 |
-
*
|
22 |
-
* require(bvsdk.php);
|
23 |
-
*
|
24 |
-
* $bv = new BV(array(
|
25 |
-
* 'bv_root_folder' => '1234-en_US',
|
26 |
-
* 'subject_id' => 'XXYYY',
|
27 |
-
* 'cloud_key' => 'company-cdfa682b84bef44672efed074093ccd3',
|
28 |
-
* 'staging' => FALSE
|
29 |
-
* ));
|
30 |
-
*
|
31 |
-
*/
|
32 |
-
require_once 'BVUtility.php';
|
33 |
-
require_once 'BVFooter.php';
|
34 |
-
|
35 |
-
// Should be declared in file where execTimer will be used.
|
36 |
-
// If declared in the another file it does not affect the current file.
|
37 |
-
declare(ticks = 1);
|
38 |
-
|
39 |
-
// Default charset will be used in case charset parameter is not properly configured by user.
|
40 |
-
define('DEFAULT_CHARSET', 'UTF-8');
|
41 |
-
|
42 |
-
// ------------------------------------------------------------------------
|
43 |
-
|
44 |
-
/**
|
45 |
-
* BV Class
|
46 |
-
*
|
47 |
-
* When you instantiate the BV class, pass it's constructor an array
|
48 |
-
* containing the following key value pairs.
|
49 |
-
*
|
50 |
-
* Required fields:
|
51 |
-
* bv_root_folder (string)
|
52 |
-
* subject_id (string)
|
53 |
-
* cloud_key (string)
|
54 |
-
*
|
55 |
-
* Optional fields
|
56 |
-
* base_url (string) (defaults to detecting the base_url automatically)
|
57 |
-
* page_url (string) (defaults to empty, to provide query parameters )
|
58 |
-
* staging (boolean) (defaults to false, need to put true for testing with staging data)
|
59 |
-
* testing (boolean) (defaults to false, need to put true for testing with testing data)
|
60 |
-
* content_type (string) (defaults to reviews, you can pass content type here if needed)
|
61 |
-
* subject_type (string) (defaults to product, you can pass subject type here if needed)
|
62 |
-
* content_sub_type (string) (defaults to stories, for stories you can pass either STORIES_LIST or STORIES_GRID content type)
|
63 |
-
* execution_timeout (int) (in milliseconds) (defaults to 500ms, to set period of time before the BVSEO injection times out for user agents that do not match the criteria set in CRAWLER_AGENT_PATTERN)
|
64 |
-
* execution_timeout_bot (int) (in milliseconds) (defaults to 2000ms, to set period of time before the BVSEO injection times out for user agents that match the criteria set in CRAWLER_AGENT_PATTERN)
|
65 |
-
* charset (string) (defaults to UTF-8, to set alternate character for SDK output)
|
66 |
-
* crawler_agent_pattern (string) (defaults to msnbot|googlebot|teoma|bingbot|yandexbot|yahoo)
|
67 |
-
*/
|
68 |
-
class BV {
|
69 |
-
|
70 |
-
/**
|
71 |
-
* BV Class Constructor
|
72 |
-
*
|
73 |
-
* The constructor takes in all the arguments via a single array.
|
74 |
-
*
|
75 |
-
* @access public
|
76 |
-
* @param array
|
77 |
-
* @return object
|
78 |
-
*/
|
79 |
-
public function __construct($params = array()) {
|
80 |
-
|
81 |
-
$this->validateParameters($params);
|
82 |
-
|
83 |
-
// config array, defaults are defined here.
|
84 |
-
$this->config = array(
|
85 |
-
'staging' => FALSE,
|
86 |
-
'testing' => FALSE,
|
87 |
-
'content_type' => isset($params['content_type']) ? $params['content_type'] : 'reviews',
|
88 |
-
'subject_type' => isset($params['subject_type']) ? $params['subject_type'] : 'product',
|
89 |
-
'page_url' => isset($params['page_url']) ? $params['page_url'] : '',
|
90 |
-
'base_url' => isset($params['base_url']) ? $params['base_url'] : '',
|
91 |
-
'include_display_integration_code' => FALSE,
|
92 |
-
'client_name' => $params['bv_root_folder'],
|
93 |
-
'local_seo_file_root' => '',
|
94 |
-
'load_seo_files_locally' => FALSE,
|
95 |
-
// used in regex to determine if request is a bot or not
|
96 |
-
'crawler_agent_pattern' => 'msnbot|google|teoma|bingbot|yandexbot|yahoo',
|
97 |
-
'ssl_enabled' => FALSE,
|
98 |
-
'proxy_host' => '',
|
99 |
-
'proxy_port' => '',
|
100 |
-
'charset' => 'UTF-8',
|
101 |
-
'seo_sdk_enabled' => TRUE,
|
102 |
-
'execution_timeout' => 500,
|
103 |
-
'execution_timeout_bot' => 2000,
|
104 |
-
'bvreveal' => isset($params['bvreveal']) ? $params['bvreveal'] : '',
|
105 |
-
'page' => 1,
|
106 |
-
'page_params' => array()
|
107 |
-
);
|
108 |
-
|
109 |
-
// Merge passed in params with defaults for config.
|
110 |
-
$this->config = array_merge($this->config, $params);
|
111 |
-
|
112 |
-
// Obtain all the name=value parameters from either the page URL passed in,
|
113 |
-
// or from the actual page URL as seen by PHP. Parameter values from the
|
114 |
-
// actual URL override those from the URL passed in, as that is usually a
|
115 |
-
// trucated URL where present at all.
|
116 |
-
//
|
117 |
-
// Note that we're taking parameters from query string, fragment, or
|
118 |
-
// _escaped_fragment_. (Though fragment is not passed to the server, so
|
119 |
-
// we won't actually see that in practice).
|
120 |
-
//
|
121 |
-
// We're after bvrrp, bvqap, bvsyp, and bvstate, but sweep up everything
|
122 |
-
// while we're here.
|
123 |
-
if (isset($params['page_url'])) {
|
124 |
-
$this->config['bv_page_data'] = BVUtility::parseUrlParameters($params['page_url']);
|
125 |
-
}
|
126 |
-
|
127 |
-
// Extract bvstate if present and parse that into a set of useful values.
|
128 |
-
if (isset($this->config['bv_page_data']['bvstate'])) {
|
129 |
-
$this->config['page_params'] = BVUtility::getBVStateParams($this->config['bv_page_data']['bvstate']);
|
130 |
-
}
|
131 |
-
|
132 |
-
// Remove any trailing URL delimeters from the base URL. E.g.:
|
133 |
-
// http://example.com?
|
134 |
-
// http://example.com?a=b&
|
135 |
-
// http://example.com?a=b&_escaped_fragment_=x/y/z?r=s%26
|
136 |
-
//
|
137 |
-
$this->config['base_url'] = mb_ereg_replace('(&|\?|%26)$', '', $this->config['base_url']);
|
138 |
-
|
139 |
-
// Get rid of all the other things we care about from the base URL, so that
|
140 |
-
// we don't double up the parameters.
|
141 |
-
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvstate');
|
142 |
-
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvrrp');
|
143 |
-
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvqap');
|
144 |
-
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvsyp');
|
145 |
-
|
146 |
-
// Create the processor objects.
|
147 |
-
$this->reviews = new Reviews($this->config);
|
148 |
-
$this->questions = new Questions($this->config);
|
149 |
-
$this->stories = new Stories($this->config);
|
150 |
-
$this->spotlights = new Spotlights($this->config);
|
151 |
-
$this->sellerratings = new SellerRatings($this->config);
|
152 |
-
|
153 |
-
// Assign one to $this->SEO based on the content type.
|
154 |
-
$ct = isset($this->config['page_params']['content_type']) ? $this->config['page_params']['content_type'] : $this->config['content_type'];
|
155 |
-
if (isset($ct)) {
|
156 |
-
switch ($ct) {
|
157 |
-
case 'reviews': {
|
158 |
-
$st = isset($this->config['page_params']['subject_type']) ? $this->config['page_params']['subject_type'] : $this->config['subject_type'];
|
159 |
-
if (isset($st) && $st == 'seller') {
|
160 |
-
$this->SEO = $this->sellerratings;
|
161 |
-
} else {
|
162 |
-
$this->SEO = $this->reviews;
|
163 |
-
}
|
164 |
-
break;
|
165 |
-
}
|
166 |
-
case 'questions': $this->SEO = $this->questions;
|
167 |
-
break;
|
168 |
-
case 'stories': $this->SEO = $this->stories;
|
169 |
-
break;
|
170 |
-
case 'spotlights': $this->SEO = $this->spotlights;
|
171 |
-
break;
|
172 |
-
default:
|
173 |
-
throw new Exception('Invalid content_type value provided: ' . $this->config['content_type']);
|
174 |
-
}
|
175 |
-
}
|
176 |
-
}
|
177 |
-
|
178 |
-
protected function validateParameters($params) {
|
179 |
-
if (!is_array($params)) {
|
180 |
-
throw new Exception(
|
181 |
-
'BV class constructor argument $params must be an array.'
|
182 |
-
);
|
183 |
-
}
|
184 |
-
|
185 |
-
// check to make sure we have the required parameters.
|
186 |
-
if (empty($params['bv_root_folder'])) {
|
187 |
-
throw new Exception(
|
188 |
-
'BV class constructor argument $params is missing required bv_root_folder key. An ' .
|
189 |
-
'array containing bv_root_folder (string) is expected.'
|
190 |
-
);
|
191 |
-
}
|
192 |
-
|
193 |
-
if (empty($params['subject_id'])) {
|
194 |
-
throw new Exception(
|
195 |
-
'BV class constructor argument $params is missing required subject_id key. An ' .
|
196 |
-
'array containing subject_id (string) is expected.'
|
197 |
-
);
|
198 |
-
}
|
199 |
-
}
|
200 |
-
}
|
201 |
-
// end of BV class
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Base Class containing most shared functionality. So when we add support for
|
205 |
-
* questions and answers it should be minimal changes. Just need to create an
|
206 |
-
* answers class which inherits from Base.
|
207 |
-
*
|
208 |
-
* Configuration array is required for creation class object.
|
209 |
-
*
|
210 |
-
*/
|
211 |
-
class Base {
|
212 |
-
private $msg = '';
|
213 |
-
|
214 |
-
public function __construct($params = array()) {
|
215 |
-
|
216 |
-
$this->validateParams($params);
|
217 |
-
|
218 |
-
$this->config = $params;
|
219 |
-
|
220 |
-
// setup bv (internal) defaults
|
221 |
-
$this->bv_config['seo-domain']['staging'] = 'seo-stg.bazaarvoice.com';
|
222 |
-
$this->bv_config['seo-domain']['production'] = 'seo.bazaarvoice.com';
|
223 |
-
$this->bv_config['seo-domain']['testing_staging'] = 'seo-qa-stg.bazaarvoice.com';
|
224 |
-
$this->bv_config['seo-domain']['testing_production'] = 'seo-qa.bazaarvoice.com';
|
225 |
-
|
226 |
-
// seller rating display is a special snowflake
|
227 |
-
$this->bv_config['srd-domain'] = 'srd.bazaarvoice.com';
|
228 |
-
$this->bv_config['srd-prefix-staging'] = 'stg';
|
229 |
-
$this->bv_config['srd-prefix-production'] = 'prod';
|
230 |
-
$this->bv_config['srd-prefix-testing_staging'] = 'qa-stg';
|
231 |
-
$this->bv_config['srd-prefix-testing_production'] = 'qa';
|
232 |
-
|
233 |
-
$this->config['latency_timeout'] = $this->_isBot()
|
234 |
-
? $this->config['execution_timeout_bot']
|
235 |
-
: $this->config['execution_timeout'];
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
*
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
$
|
316 |
-
|
317 |
-
//
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
//
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
$seo_content = $this->
|
328 |
-
|
329 |
-
|
330 |
-
$seo_content = $this->
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
$
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
$payload = $this->
|
374 |
-
|
375 |
-
// remove
|
376 |
-
$payload = $this->_replaceSection($payload, '<!--begin-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
$payload = $this->
|
389 |
-
|
390 |
-
//
|
391 |
-
$
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
*
|
402 |
-
*
|
403 |
-
*
|
404 |
-
*
|
405 |
-
*
|
406 |
-
*
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
$
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
$this->
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
*
|
445 |
-
*
|
446 |
-
*
|
447 |
-
*
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
*
|
464 |
-
*
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
*
|
497 |
-
*
|
498 |
-
*
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
//
|
513 |
-
//
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
//
|
522 |
-
//
|
523 |
-
//
|
524 |
-
//
|
525 |
-
//
|
526 |
-
//
|
527 |
-
//
|
528 |
-
//
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
*
|
551 |
-
*
|
552 |
-
*
|
553 |
-
*
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
$
|
580 |
-
//
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
$
|
592 |
-
$this->config['
|
593 |
-
$
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
if
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
*
|
636 |
-
*
|
637 |
-
*
|
638 |
-
*
|
639 |
-
*
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
$this->_setBuildMessage('
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
*
|
673 |
-
*
|
674 |
-
*
|
675 |
-
*
|
676 |
-
*
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
//
|
684 |
-
//
|
685 |
-
|
686 |
-
|
687 |
-
//
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
}
|
731 |
-
|
732 |
-
// if we
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
*
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
//
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
//
|
762 |
-
// the
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
return $
|
814 |
-
}
|
815 |
-
|
816 |
-
public function
|
817 |
-
$this->_setBuildMessage('Content Type "' . $this->config['content_type'] . '" is not supported by
|
818 |
-
$pay_load = $this->_buildComment('', '
|
819 |
-
|
820 |
-
return $pay_load;
|
821 |
-
}
|
822 |
-
|
823 |
-
public function
|
824 |
-
$this->_setBuildMessage('Content Type "' . $this->config['content_type'] . '" is not supported by
|
825 |
-
$pay_load = $this->_buildComment('', '
|
826 |
-
|
827 |
-
return $pay_load;
|
828 |
-
}
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
//
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
|
860 |
-
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
if ($this->config['
|
874 |
-
$
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
if ($this->config['
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
//
|
952 |
-
|
953 |
-
|
954 |
-
//
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
$
|
969 |
-
}
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
|
974 |
-
if ($this->config['
|
975 |
-
$
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
|
1002 |
-
|
1003 |
-
//
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
//
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* BV PHP SEO SDK
|
5 |
+
*
|
6 |
+
* Base code to power either SEO or SEO and display. This SDK
|
7 |
+
* is provided as is and Bazaarvoice, Inc. is not responsible
|
8 |
+
* for future maintenance or support. You are free to modify
|
9 |
+
* this SDK as needed to suit your needs.
|
10 |
+
*
|
11 |
+
* This SDK was built with the following assumptions:
|
12 |
+
* - you are running PHP 5 or greater
|
13 |
+
* - you have the curl library installed
|
14 |
+
* - every request has the user agent header
|
15 |
+
* in it (if using a CDN like Akamai additional configuration
|
16 |
+
* maybe required).
|
17 |
+
*
|
18 |
+
*/
|
19 |
+
/**
|
20 |
+
* Example usage:
|
21 |
+
*
|
22 |
+
* require(bvsdk.php);
|
23 |
+
*
|
24 |
+
* $bv = new BV(array(
|
25 |
+
* 'bv_root_folder' => '1234-en_US',
|
26 |
+
* 'subject_id' => 'XXYYY',
|
27 |
+
* 'cloud_key' => 'company-cdfa682b84bef44672efed074093ccd3',
|
28 |
+
* 'staging' => FALSE
|
29 |
+
* ));
|
30 |
+
*
|
31 |
+
*/
|
32 |
+
require_once 'BVUtility.php';
|
33 |
+
require_once 'BVFooter.php';
|
34 |
+
|
35 |
+
// Should be declared in file where execTimer will be used.
|
36 |
+
// If declared in the another file it does not affect the current file.
|
37 |
+
declare(ticks = 1);
|
38 |
+
|
39 |
+
// Default charset will be used in case charset parameter is not properly configured by user.
|
40 |
+
define('DEFAULT_CHARSET', 'UTF-8');
|
41 |
+
|
42 |
+
// ------------------------------------------------------------------------
|
43 |
+
|
44 |
+
/**
|
45 |
+
* BV Class
|
46 |
+
*
|
47 |
+
* When you instantiate the BV class, pass it's constructor an array
|
48 |
+
* containing the following key value pairs.
|
49 |
+
*
|
50 |
+
* Required fields:
|
51 |
+
* bv_root_folder (string)
|
52 |
+
* subject_id (string)
|
53 |
+
* cloud_key (string)
|
54 |
+
*
|
55 |
+
* Optional fields
|
56 |
+
* base_url (string) (defaults to detecting the base_url automatically)
|
57 |
+
* page_url (string) (defaults to empty, to provide query parameters )
|
58 |
+
* staging (boolean) (defaults to false, need to put true for testing with staging data)
|
59 |
+
* testing (boolean) (defaults to false, need to put true for testing with testing data)
|
60 |
+
* content_type (string) (defaults to reviews, you can pass content type here if needed)
|
61 |
+
* subject_type (string) (defaults to product, you can pass subject type here if needed)
|
62 |
+
* content_sub_type (string) (defaults to stories, for stories you can pass either STORIES_LIST or STORIES_GRID content type)
|
63 |
+
* execution_timeout (int) (in milliseconds) (defaults to 500ms, to set period of time before the BVSEO injection times out for user agents that do not match the criteria set in CRAWLER_AGENT_PATTERN)
|
64 |
+
* execution_timeout_bot (int) (in milliseconds) (defaults to 2000ms, to set period of time before the BVSEO injection times out for user agents that match the criteria set in CRAWLER_AGENT_PATTERN)
|
65 |
+
* charset (string) (defaults to UTF-8, to set alternate character for SDK output)
|
66 |
+
* crawler_agent_pattern (string) (defaults to msnbot|googlebot|teoma|bingbot|yandexbot|yahoo)
|
67 |
+
*/
|
68 |
+
class BV {
|
69 |
+
|
70 |
+
/**
|
71 |
+
* BV Class Constructor
|
72 |
+
*
|
73 |
+
* The constructor takes in all the arguments via a single array.
|
74 |
+
*
|
75 |
+
* @access public
|
76 |
+
* @param array
|
77 |
+
* @return object
|
78 |
+
*/
|
79 |
+
public function __construct($params = array()) {
|
80 |
+
|
81 |
+
$this->validateParameters($params);
|
82 |
+
|
83 |
+
// config array, defaults are defined here.
|
84 |
+
$this->config = array(
|
85 |
+
'staging' => FALSE,
|
86 |
+
'testing' => FALSE,
|
87 |
+
'content_type' => isset($params['content_type']) ? $params['content_type'] : 'reviews',
|
88 |
+
'subject_type' => isset($params['subject_type']) ? $params['subject_type'] : 'product',
|
89 |
+
'page_url' => isset($params['page_url']) ? $params['page_url'] : '',
|
90 |
+
'base_url' => isset($params['base_url']) ? $params['base_url'] : '',
|
91 |
+
'include_display_integration_code' => FALSE,
|
92 |
+
'client_name' => $params['bv_root_folder'],
|
93 |
+
'local_seo_file_root' => '',
|
94 |
+
'load_seo_files_locally' => FALSE,
|
95 |
+
// used in regex to determine if request is a bot or not
|
96 |
+
'crawler_agent_pattern' => 'msnbot|google|teoma|bingbot|yandexbot|yahoo',
|
97 |
+
'ssl_enabled' => FALSE,
|
98 |
+
'proxy_host' => '',
|
99 |
+
'proxy_port' => '',
|
100 |
+
'charset' => 'UTF-8',
|
101 |
+
'seo_sdk_enabled' => TRUE,
|
102 |
+
'execution_timeout' => 500,
|
103 |
+
'execution_timeout_bot' => 2000,
|
104 |
+
'bvreveal' => isset($params['bvreveal']) ? $params['bvreveal'] : '',
|
105 |
+
'page' => 1,
|
106 |
+
'page_params' => array()
|
107 |
+
);
|
108 |
+
|
109 |
+
// Merge passed in params with defaults for config.
|
110 |
+
$this->config = array_merge($this->config, $params);
|
111 |
+
|
112 |
+
// Obtain all the name=value parameters from either the page URL passed in,
|
113 |
+
// or from the actual page URL as seen by PHP. Parameter values from the
|
114 |
+
// actual URL override those from the URL passed in, as that is usually a
|
115 |
+
// trucated URL where present at all.
|
116 |
+
//
|
117 |
+
// Note that we're taking parameters from query string, fragment, or
|
118 |
+
// _escaped_fragment_. (Though fragment is not passed to the server, so
|
119 |
+
// we won't actually see that in practice).
|
120 |
+
//
|
121 |
+
// We're after bvrrp, bvqap, bvsyp, and bvstate, but sweep up everything
|
122 |
+
// while we're here.
|
123 |
+
if (isset($params['page_url'])) {
|
124 |
+
$this->config['bv_page_data'] = BVUtility::parseUrlParameters($params['page_url']);
|
125 |
+
}
|
126 |
+
|
127 |
+
// Extract bvstate if present and parse that into a set of useful values.
|
128 |
+
if (isset($this->config['bv_page_data']['bvstate'])) {
|
129 |
+
$this->config['page_params'] = BVUtility::getBVStateParams($this->config['bv_page_data']['bvstate']);
|
130 |
+
}
|
131 |
+
|
132 |
+
// Remove any trailing URL delimeters from the base URL. E.g.:
|
133 |
+
// http://example.com?
|
134 |
+
// http://example.com?a=b&
|
135 |
+
// http://example.com?a=b&_escaped_fragment_=x/y/z?r=s%26
|
136 |
+
//
|
137 |
+
$this->config['base_url'] = mb_ereg_replace('(&|\?|%26)$', '', $this->config['base_url']);
|
138 |
+
|
139 |
+
// Get rid of all the other things we care about from the base URL, so that
|
140 |
+
// we don't double up the parameters.
|
141 |
+
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvstate');
|
142 |
+
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvrrp');
|
143 |
+
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvqap');
|
144 |
+
$this->config['base_url'] = BVUtility::removeUrlParam($this->config['base_url'], 'bvsyp');
|
145 |
+
|
146 |
+
// Create the processor objects.
|
147 |
+
$this->reviews = new Reviews($this->config);
|
148 |
+
$this->questions = new Questions($this->config);
|
149 |
+
$this->stories = new Stories($this->config);
|
150 |
+
$this->spotlights = new Spotlights($this->config);
|
151 |
+
$this->sellerratings = new SellerRatings($this->config);
|
152 |
+
|
153 |
+
// Assign one to $this->SEO based on the content type.
|
154 |
+
$ct = isset($this->config['page_params']['content_type']) ? $this->config['page_params']['content_type'] : $this->config['content_type'];
|
155 |
+
if (isset($ct)) {
|
156 |
+
switch ($ct) {
|
157 |
+
case 'reviews': {
|
158 |
+
$st = isset($this->config['page_params']['subject_type']) ? $this->config['page_params']['subject_type'] : $this->config['subject_type'];
|
159 |
+
if (isset($st) && $st == 'seller') {
|
160 |
+
$this->SEO = $this->sellerratings;
|
161 |
+
} else {
|
162 |
+
$this->SEO = $this->reviews;
|
163 |
+
}
|
164 |
+
break;
|
165 |
+
}
|
166 |
+
case 'questions': $this->SEO = $this->questions;
|
167 |
+
break;
|
168 |
+
case 'stories': $this->SEO = $this->stories;
|
169 |
+
break;
|
170 |
+
case 'spotlights': $this->SEO = $this->spotlights;
|
171 |
+
break;
|
172 |
+
default:
|
173 |
+
throw new Exception('Invalid content_type value provided: ' . $this->config['content_type']);
|
174 |
+
}
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
protected function validateParameters($params) {
|
179 |
+
if (!is_array($params)) {
|
180 |
+
throw new Exception(
|
181 |
+
'BV class constructor argument $params must be an array.'
|
182 |
+
);
|
183 |
+
}
|
184 |
+
|
185 |
+
// check to make sure we have the required parameters.
|
186 |
+
if (empty($params['bv_root_folder'])) {
|
187 |
+
throw new Exception(
|
188 |
+
'BV class constructor argument $params is missing required bv_root_folder key. An ' .
|
189 |
+
'array containing bv_root_folder (string) is expected.'
|
190 |
+
);
|
191 |
+
}
|
192 |
+
|
193 |
+
if (empty($params['subject_id'])) {
|
194 |
+
throw new Exception(
|
195 |
+
'BV class constructor argument $params is missing required subject_id key. An ' .
|
196 |
+
'array containing subject_id (string) is expected.'
|
197 |
+
);
|
198 |
+
}
|
199 |
+
}
|
200 |
+
}
|
201 |
+
// end of BV class
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Base Class containing most shared functionality. So when we add support for
|
205 |
+
* questions and answers it should be minimal changes. Just need to create an
|
206 |
+
* answers class which inherits from Base.
|
207 |
+
*
|
208 |
+
* Configuration array is required for creation class object.
|
209 |
+
*
|
210 |
+
*/
|
211 |
+
class Base {
|
212 |
+
private $msg = '';
|
213 |
+
|
214 |
+
public function __construct($params = array()) {
|
215 |
+
|
216 |
+
$this->validateParams($params);
|
217 |
+
|
218 |
+
$this->config = $params;
|
219 |
+
|
220 |
+
// setup bv (internal) defaults
|
221 |
+
$this->bv_config['seo-domain']['staging'] = 'seo-stg.bazaarvoice.com';
|
222 |
+
$this->bv_config['seo-domain']['production'] = 'seo.bazaarvoice.com';
|
223 |
+
$this->bv_config['seo-domain']['testing_staging'] = 'seo-qa-stg.bazaarvoice.com';
|
224 |
+
$this->bv_config['seo-domain']['testing_production'] = 'seo-qa.bazaarvoice.com';
|
225 |
+
|
226 |
+
// seller rating display is a special snowflake
|
227 |
+
$this->bv_config['srd-domain'] = 'srd.bazaarvoice.com';
|
228 |
+
$this->bv_config['srd-prefix-staging'] = 'stg';
|
229 |
+
$this->bv_config['srd-prefix-production'] = 'prod';
|
230 |
+
$this->bv_config['srd-prefix-testing_staging'] = 'qa-stg';
|
231 |
+
$this->bv_config['srd-prefix-testing_production'] = 'qa';
|
232 |
+
|
233 |
+
$this->config['latency_timeout'] = $this->_isBot()
|
234 |
+
? $this->config['execution_timeout_bot']
|
235 |
+
: $this->config['execution_timeout'];
|
236 |
+
|
237 |
+
// set up combined user agent to be passed to cloud storage (if needed)
|
238 |
+
$this->config['user_agent'] = "bv_php_sdk/3.2.0;" . $_SERVER['HTTP_USER_AGENT'];
|
239 |
+
}
|
240 |
+
|
241 |
+
protected function validateParams($params) {
|
242 |
+
if (!is_array($params)) {
|
243 |
+
throw new Exception('BV Base Class missing config array.');
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* A check on the bvstate parameter content type value.
|
249 |
+
*/
|
250 |
+
protected function _checkBVStateContentType() {
|
251 |
+
if (empty($this->config['page_params']['content_type'])) {
|
252 |
+
return TRUE;
|
253 |
+
}
|
254 |
+
|
255 |
+
if (
|
256 |
+
!empty($this->config['page_params']['content_type']) &&
|
257 |
+
$this->config['page_params']['content_type'] == $this->config['content_type']
|
258 |
+
) {
|
259 |
+
return TRUE;
|
260 |
+
}
|
261 |
+
|
262 |
+
return FALSE;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Function for collecting messages.
|
267 |
+
*/
|
268 |
+
protected function _setBuildMessage($msg) {
|
269 |
+
$msg = rtrim($msg, ";");
|
270 |
+
$this->msg .= ' ' . $msg . ';';
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Is this SDK enabled?
|
275 |
+
*
|
276 |
+
* Return true if either seo_sdk_enabled is set truthy or bvreveal flags are
|
277 |
+
* set.
|
278 |
+
*/
|
279 |
+
private function _isSdkEnabled() {
|
280 |
+
return $this->config['seo_sdk_enabled'] || $this->_getBVReveal();
|
281 |
+
}
|
282 |
+
|
283 |
+
/**
|
284 |
+
* Check if charset is correct, if not set to default
|
285 |
+
*/
|
286 |
+
private function _checkCharset($seo_content) {
|
287 |
+
if (isset($this->config['charset'])) {
|
288 |
+
$supportedCharsets = mb_list_encodings();
|
289 |
+
if (!in_array($this->config['charset'], $supportedCharsets)) {
|
290 |
+
$this->config['charset'] = DEFAULT_CHARSET;
|
291 |
+
$this->_setBuildMessage("Charset is not configured properly. "
|
292 |
+
. "BV-SEO-SDK will load default charset and continue.");
|
293 |
+
}
|
294 |
+
} else {
|
295 |
+
$this->config['charset'] = DEFAULT_CHARSET;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Return encoded content with set charset
|
301 |
+
*/
|
302 |
+
private function _charsetEncode($seo_content) {
|
303 |
+
if (isset($this->config['charset'])) {
|
304 |
+
$enc = mb_detect_encoding($seo_content);
|
305 |
+
$seo_content = mb_convert_encoding($seo_content, $this->config['charset'], $enc);
|
306 |
+
}
|
307 |
+
|
308 |
+
return $seo_content;
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Return full SEO content.
|
313 |
+
*/
|
314 |
+
private function _getFullSeoContents() {
|
315 |
+
$seo_content = '';
|
316 |
+
|
317 |
+
// get the page number of SEO content to load
|
318 |
+
$page_number = $this->_getPageNumber();
|
319 |
+
|
320 |
+
// build the URL to access the SEO content for
|
321 |
+
// this product / page combination
|
322 |
+
$this->seo_url = $this->_buildSeoUrl($page_number);
|
323 |
+
|
324 |
+
// make call to get SEO payload from cloud unless seo_sdk_enabled is false
|
325 |
+
// make call if bvreveal param in query string is set to 'debug'
|
326 |
+
if ($this->_isSdkEnabled()) {
|
327 |
+
$seo_content = $this->_fetchSeoContent($this->seo_url);
|
328 |
+
|
329 |
+
$this->_checkCharset($seo_content);
|
330 |
+
$seo_content = $this->_charsetEncode($seo_content);
|
331 |
+
|
332 |
+
// replace tokens for pagination URLs with page_url
|
333 |
+
$seo_content = $this->_replaceTokens($seo_content);
|
334 |
+
}
|
335 |
+
// show footer even if seo_sdk_enabled flag is false
|
336 |
+
else {
|
337 |
+
$this->_setBuildMessage(
|
338 |
+
'SEO SDK is disabled. Enable by setting seo.sdk.enabled to true.'
|
339 |
+
);
|
340 |
+
}
|
341 |
+
|
342 |
+
$payload = $seo_content;
|
343 |
+
|
344 |
+
return $payload;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Remove predefined section from a string.
|
349 |
+
*/
|
350 |
+
private function _replaceSection($str, $search_str_begin, $search_str_end) {
|
351 |
+
$result = $str;
|
352 |
+
$start_index = mb_strrpos($str, $search_str_begin);
|
353 |
+
|
354 |
+
if ($start_index !== false) {
|
355 |
+
$end_index = mb_strrpos($str, $search_str_end);
|
356 |
+
|
357 |
+
if ($end_index !== false) {
|
358 |
+
$end_index += mb_strlen($search_str_end);
|
359 |
+
$str_begin = mb_substr($str, 0, $start_index);
|
360 |
+
$str_end = mb_substr($str, $end_index);
|
361 |
+
|
362 |
+
$result = $str_begin . $str_end;
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
return $result;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Get only aggregate rating from SEO content.
|
371 |
+
*/
|
372 |
+
protected function _renderAggregateRating() {
|
373 |
+
$payload = $this->_renderSEO('getAggregateRating');
|
374 |
+
|
375 |
+
// remove reviews section from full_contents
|
376 |
+
$payload = $this->_replaceSection($payload, '<!--begin-reviews-->', '<!--end-reviews-->');
|
377 |
+
|
378 |
+
// remove pagination section from full contents
|
379 |
+
$payload = $this->_replaceSection($payload, '<!--begin-pagination-->', '<!--end-pagination-->');
|
380 |
+
|
381 |
+
return $payload;
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* Get only reviews from SEO content.
|
386 |
+
*/
|
387 |
+
protected function _renderReviews() {
|
388 |
+
$payload = $this->_renderSEO('getReviews');
|
389 |
+
|
390 |
+
// remove aggregate rating section from full_contents
|
391 |
+
$payload = $this->_replaceSection($payload, '<!--begin-aggregate-rating-->', '<!--end-aggregate-rating-->');
|
392 |
+
|
393 |
+
// Remove schema.org product text from reviews if it exists
|
394 |
+
$schema_org_text = "itemscope itemtype=\"http://schema.org/Product\"";
|
395 |
+
$payload = mb_ereg_replace($schema_org_text, '', $payload);
|
396 |
+
|
397 |
+
return $payload;
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
* Render SEO
|
402 |
+
*
|
403 |
+
* Method used to do all the work to fetch, parse, and then return
|
404 |
+
* the SEO payload. This is set as protected so classes inheriting
|
405 |
+
* from the base class can invoke it or replace it if needed.
|
406 |
+
*
|
407 |
+
* @access protected
|
408 |
+
* @param $access_method
|
409 |
+
* @return string
|
410 |
+
*/
|
411 |
+
protected function _renderSEO($access_method) {
|
412 |
+
$payload = '';
|
413 |
+
$this->start_time = microtime(1);
|
414 |
+
|
415 |
+
$isBot = $this->_isBot();
|
416 |
+
|
417 |
+
if (!$isBot && $this->config['latency_timeout'] == 0) {
|
418 |
+
$this->_setBuildMessage("EXECUTION_TIMEOUT is set to 0 ms; JavaScript-only Display.");
|
419 |
+
} else {
|
420 |
+
|
421 |
+
if ($isBot && $this->config['latency_timeout'] < 100) {
|
422 |
+
$this->config['latency_timeout'] = 100;
|
423 |
+
$this->_setBuildMessage("EXECUTION_TIMEOUT_BOT is less than the minimum value allowed. Minimum value of 100ms used.");
|
424 |
+
}
|
425 |
+
|
426 |
+
try {
|
427 |
+
BVUtility::execTimer($this->config['latency_timeout'], $isBot, $this->start_time);
|
428 |
+
$payload = $this->_getFullSeoContents($access_method);
|
429 |
+
} catch (Exception $e) {
|
430 |
+
$this->_setBuildMessage($e->getMessage());
|
431 |
+
}
|
432 |
+
BVUtility::stopTimer();
|
433 |
+
}
|
434 |
+
|
435 |
+
$payload .= $this->_buildComment($access_method);
|
436 |
+
return $payload;
|
437 |
+
}
|
438 |
+
|
439 |
+
// -------------------------------------------------------------------
|
440 |
+
// Private methods. Internal workings of SDK.
|
441 |
+
//--------------------------------------------------------------------
|
442 |
+
|
443 |
+
/**
|
444 |
+
* isBot
|
445 |
+
*
|
446 |
+
* Helper method to determine if current request is a bot or not. Will
|
447 |
+
* use the configured regex string which can be overridden with params.
|
448 |
+
*
|
449 |
+
* @access private
|
450 |
+
* @return bool
|
451 |
+
*/
|
452 |
+
private function _isBot() {
|
453 |
+
$bvreveal = $this->_getBVReveal();
|
454 |
+
if ($bvreveal) {
|
455 |
+
return TRUE;
|
456 |
+
}
|
457 |
+
|
458 |
+
// search the user agent string for an indication if this is a search bot or not
|
459 |
+
return mb_eregi('(' . $this->config['crawler_agent_pattern'] . ')', $_SERVER['HTTP_USER_AGENT']);
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* getBVReveal
|
464 |
+
*
|
465 |
+
* Return true if bvreveal flags are set, either via reveal:debug in the
|
466 |
+
* bvstate query parameter or in the old bvreveal query parameter, or is
|
467 |
+
* passed in via the configuration of the main class.
|
468 |
+
*/
|
469 |
+
private function _getBVReveal() {
|
470 |
+
// Passed in as configuration override?
|
471 |
+
if (
|
472 |
+
!empty($this->config['bvreveal']) &&
|
473 |
+
$this->config['bvreveal'] == 'debug'
|
474 |
+
) {
|
475 |
+
return TRUE;
|
476 |
+
}
|
477 |
+
// Set via bvstate query parameter?
|
478 |
+
else if (
|
479 |
+
!empty($this->config['page_params']['bvreveal']) &&
|
480 |
+
$this->config['page_params']['bvreveal'] == 'debug'
|
481 |
+
) {
|
482 |
+
return TRUE;
|
483 |
+
}
|
484 |
+
// Set via bvreveal query parameter?
|
485 |
+
else if (
|
486 |
+
!empty($this->config['bv_page_data']['bvreveal']) &&
|
487 |
+
$this->config['bv_page_data']['bvreveal'] == 'debug'
|
488 |
+
) {
|
489 |
+
return TRUE;
|
490 |
+
} else {
|
491 |
+
return FALSE;
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* getPageNumber
|
497 |
+
*
|
498 |
+
* Helper method to pull from the URL the page of SEO we need to view.
|
499 |
+
*
|
500 |
+
* @access private
|
501 |
+
* @return int
|
502 |
+
*/
|
503 |
+
private function _getPageNumber() {
|
504 |
+
$page_number = 1;
|
505 |
+
|
506 |
+
// Override from config.
|
507 |
+
if (isset($this->config['page']) && $this->config['page'] != $page_number) {
|
508 |
+
$page_number = (int) $this->config['page'];
|
509 |
+
}
|
510 |
+
// Check the bvstate parameter if one was found and successfully parsed.
|
511 |
+
else if (isset($this->config['page_params']['base_url_bvstate'])) {
|
512 |
+
// We only apply the bvstate page number parameter if the content type
|
513 |
+
// specified matches the content type being generated here. E.g. if
|
514 |
+
// someone calls up a page with bvstate=ct:r/pg:2 and loads stories rather
|
515 |
+
// than reviews, show page 1 for stories. Only show page 2 if they are in
|
516 |
+
// fact displaying review content.
|
517 |
+
if ($this->config['content_type'] == $this->config['page_params']['content_type']) {
|
518 |
+
$page_number = $this->config['page_params']['page'];
|
519 |
+
}
|
520 |
+
}
|
521 |
+
// other implementations use the bvrrp, bvqap, or bvsyp parameter
|
522 |
+
// ?bvrrp=1234-en_us/reviews/product/2/ASF234.htm
|
523 |
+
//
|
524 |
+
// Note that unlike bvstate, we don't actually check for the content type
|
525 |
+
// to match the parameter type for the legacy page parameters bvrrp, bvqap,
|
526 |
+
// and bvsyp. This is consistent with the behavior of the other SDKs, even
|
527 |
+
// if it doesn't really make much sense.
|
528 |
+
//
|
529 |
+
// Note that there is a bug in the SEO-CPS content generation where it uses
|
530 |
+
// the bvrrp parameter in place of bvqap, so this may all be sort of
|
531 |
+
// deliberate, if not sensible.
|
532 |
+
else if (isset($this->config['bv_page_data']['bvrrp'])) {
|
533 |
+
$bvparam = $this->config['bv_page_data']['bvrrp'];
|
534 |
+
} else if (isset($this->config['bv_page_data']['bvqap'])) {
|
535 |
+
$bvparam = $this->config['bv_page_data']['bvqap'];
|
536 |
+
} else if (isset($this->config['bv_page_data']['bvsyp'])) {
|
537 |
+
$bvparam = $this->config['bv_page_data']['bvsyp'];
|
538 |
+
}
|
539 |
+
|
540 |
+
if (!empty($bvparam)) {
|
541 |
+
$match = array();
|
542 |
+
mb_ereg('\/(\d+)\/', $bvparam, $match);
|
543 |
+
$page_number = max(1, (int) $match[1]);
|
544 |
+
}
|
545 |
+
|
546 |
+
return $page_number;
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* buildSeoUrl
|
551 |
+
*
|
552 |
+
* Helper method to that builds the URL to the SEO payload
|
553 |
+
*
|
554 |
+
* @access private
|
555 |
+
* @param int (page number)
|
556 |
+
* @return string
|
557 |
+
*/
|
558 |
+
private function _buildSeoUrl($page_number) {
|
559 |
+
$primary_selector = 'seo-domain';
|
560 |
+
|
561 |
+
// calculate, which environment should we be using
|
562 |
+
if ($this->config['testing']) {
|
563 |
+
if ($this->config['staging']) {
|
564 |
+
$env_selector = 'testing_staging';
|
565 |
+
} else {
|
566 |
+
$env_selector = 'testing_production';
|
567 |
+
}
|
568 |
+
} else {
|
569 |
+
if ($this->config['staging']) {
|
570 |
+
$env_selector = 'staging';
|
571 |
+
} else {
|
572 |
+
$env_selector = 'production';
|
573 |
+
}
|
574 |
+
}
|
575 |
+
|
576 |
+
$url_scheme = $this->config['ssl_enabled'] ? 'https://' : 'http://';
|
577 |
+
|
578 |
+
if ($this->config['content_type'] == 'reviews' &&
|
579 |
+
$this->config['subject_type'] == 'seller') {
|
580 |
+
// when content type is reviews and subject type is seller,
|
581 |
+
// we're dealing with seller rating, so use different primary selector
|
582 |
+
$primary_selector = 'srd-domain';
|
583 |
+
// for seller rating we use different selector for prefix
|
584 |
+
$hostname = $this->bv_config[$primary_selector] . '/' . $this->bv_config['srd-prefix-' . $env_selector];
|
585 |
+
} else {
|
586 |
+
$hostname = $this->bv_config[$primary_selector][$env_selector];
|
587 |
+
};
|
588 |
+
|
589 |
+
// dictates order of URL
|
590 |
+
$url_parts = array(
|
591 |
+
$url_scheme . $hostname,
|
592 |
+
$this->config['cloud_key'],
|
593 |
+
$this->config['bv_root_folder'],
|
594 |
+
$this->config['content_type'],
|
595 |
+
$this->config['subject_type'],
|
596 |
+
$page_number
|
597 |
+
);
|
598 |
+
|
599 |
+
if (isset($this->config['content_sub_type']) && !empty($this->config['content_sub_type'])) {
|
600 |
+
$url_parts[] = $this->config['content_sub_type'];
|
601 |
+
}
|
602 |
+
|
603 |
+
if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) {
|
604 |
+
$url_parts[] = urlencode($this->config['page_params']['subject_id']) . '.htm';
|
605 |
+
} else {
|
606 |
+
$url_parts[] = urlencode($this->config['subject_id']) . '.htm';
|
607 |
+
}
|
608 |
+
|
609 |
+
// if our SEO content source is a file path
|
610 |
+
// we need to remove the first two sections
|
611 |
+
// and prepend the passed in file path
|
612 |
+
if (!empty($this->config['load_seo_files_locally']) && !empty($this->config['local_seo_file_root'])) {
|
613 |
+
unset($url_parts[0]);
|
614 |
+
unset($url_parts[1]);
|
615 |
+
|
616 |
+
return $this->config['local_seo_file_root'] . implode("/", $url_parts);
|
617 |
+
}
|
618 |
+
|
619 |
+
// implode will convert array to a string with / in between each value in array
|
620 |
+
return implode("/", $url_parts);
|
621 |
+
}
|
622 |
+
|
623 |
+
/**
|
624 |
+
* Return a SEO content from local or distant sourse.
|
625 |
+
*/
|
626 |
+
private function _fetchSeoContent($resource) {
|
627 |
+
if ($this->config['load_seo_files_locally']) {
|
628 |
+
return $this->_fetchFileContent($resource);
|
629 |
+
} else {
|
630 |
+
return $this->_fetchCloudContent($resource);
|
631 |
+
}
|
632 |
+
}
|
633 |
+
|
634 |
+
/**
|
635 |
+
* fetchFileContent
|
636 |
+
*
|
637 |
+
* Helper method that will take in a file path and return it's payload while
|
638 |
+
* handling the possible errors or exceptions that can happen.
|
639 |
+
*
|
640 |
+
* @access private
|
641 |
+
* @param string (valid file path)
|
642 |
+
* @return string (content of file)
|
643 |
+
*/
|
644 |
+
private function _fetchFileContent($path) {
|
645 |
+
$file = @file_get_contents($path);
|
646 |
+
if ($file === FALSE) {
|
647 |
+
$this->_setBuildMessage('Trying to get content from "' . $path
|
648 |
+
. '". The resource file is currently unavailable');
|
649 |
+
} else {
|
650 |
+
$this->_setBuildMessage('Local file content was uploaded');
|
651 |
+
}
|
652 |
+
return $file;
|
653 |
+
}
|
654 |
+
|
655 |
+
public function curlExecute($ch) {
|
656 |
+
return curl_exec($ch);
|
657 |
+
}
|
658 |
+
|
659 |
+
public function curlInfo($ch) {
|
660 |
+
return curl_getinfo($ch);
|
661 |
+
}
|
662 |
+
|
663 |
+
public function curlErrorNo($ch) {
|
664 |
+
return curl_errno($ch);
|
665 |
+
}
|
666 |
+
|
667 |
+
public function curlError($ch) {
|
668 |
+
return curl_error($ch);
|
669 |
+
}
|
670 |
+
|
671 |
+
/**
|
672 |
+
* fetchCloudContent
|
673 |
+
*
|
674 |
+
* Helper method that will take in a URL and return it's payload while
|
675 |
+
* handling the possible errors or exceptions that can happen.
|
676 |
+
*
|
677 |
+
* @access private
|
678 |
+
* @param string (valid url)
|
679 |
+
* @return string
|
680 |
+
*/
|
681 |
+
private function _fetchCloudContent($url) {
|
682 |
+
|
683 |
+
// is cURL installed yet?
|
684 |
+
// if ( ! function_exists('curl_init')){
|
685 |
+
// return '<!-- curl library is not installed -->';
|
686 |
+
// }
|
687 |
+
// create a new cURL resource handle
|
688 |
+
$ch = curl_init();
|
689 |
+
|
690 |
+
// Set URL to download
|
691 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
692 |
+
// Set a referer as coming from the current page url
|
693 |
+
curl_setopt($ch, CURLOPT_REFERER, $this->config['page_url']);
|
694 |
+
// Include header in result? (0 = yes, 1 = no)
|
695 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
696 |
+
// Should cURL return or print out the data? (true = return, false = print)
|
697 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
698 |
+
// Timeout in seconds
|
699 |
+
curl_setopt($ch, CURLOPT_TIMEOUT, ($this->config['latency_timeout'] / 1000));
|
700 |
+
// Enable decoding of the response
|
701 |
+
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
|
702 |
+
// Enable following of redirects
|
703 |
+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
704 |
+
// set user agent if needed
|
705 |
+
if ($this->config['user_agent'] != '') {
|
706 |
+
curl_setopt($ch, CURLOPT_USERAGENT, $this->config['user_agent']);
|
707 |
+
}
|
708 |
+
|
709 |
+
if ($this->config['proxy_host'] != '') {
|
710 |
+
curl_setopt($ch, CURLOPT_PROXY, $this->config['proxy_host']);
|
711 |
+
curl_setopt($ch, CURLOPT_PROXYPORT, $this->config['proxy_port']);
|
712 |
+
}
|
713 |
+
|
714 |
+
// make the request to the given URL and then store the response,
|
715 |
+
// request info, and error number
|
716 |
+
// so we can use them later
|
717 |
+
$request = array(
|
718 |
+
'response' => $this->curlExecute($ch),
|
719 |
+
'info' => $this->curlInfo($ch),
|
720 |
+
'error_number' => $this->curlErrorNo($ch),
|
721 |
+
'error_message' => $this->curlError($ch)
|
722 |
+
);
|
723 |
+
|
724 |
+
// Close the cURL resource, and free system resources
|
725 |
+
curl_close($ch);
|
726 |
+
|
727 |
+
// see if we got any errors with the connection
|
728 |
+
if ($request['error_number'] != 0) {
|
729 |
+
$this->_setBuildMessage('Error - ' . $request['error_message']);
|
730 |
+
}
|
731 |
+
|
732 |
+
// see if we got a status code of something other than 200
|
733 |
+
if ($request['info']['http_code'] != 200) {
|
734 |
+
$this->_setBuildMessage('HTTP status code of '
|
735 |
+
. $request['info']['http_code'] . ' was returned');
|
736 |
+
return '';
|
737 |
+
}
|
738 |
+
|
739 |
+
// if we are here we got a response so let's return it
|
740 |
+
$this->response_time = round($request['info']['total_time'] * 1000);
|
741 |
+
return $request['response'];
|
742 |
+
}
|
743 |
+
|
744 |
+
/**
|
745 |
+
* replaceTokens
|
746 |
+
*
|
747 |
+
* After we have an SEO payload we need to replace the {INSERT_PAGE_URI}
|
748 |
+
* tokens with the current page url so pagination works.
|
749 |
+
*
|
750 |
+
* @access private
|
751 |
+
* @param string (valid url)
|
752 |
+
* @return string
|
753 |
+
*/
|
754 |
+
private function _replaceTokens($content) {
|
755 |
+
$page_url_query_prefix = '';
|
756 |
+
|
757 |
+
// Attach a suitable ending to the base URL if it doesn't already end with
|
758 |
+
// either ? or &. This is complicated by the _escaped_fragment_ case.
|
759 |
+
//
|
760 |
+
// We're assuming that the base URL can't have a fragment or be a hashbang
|
761 |
+
// URL - that just won't work in conjunction with the assumption that we
|
762 |
+
// always postfix the SEO query parameters to the end of the URL.
|
763 |
+
//
|
764 |
+
// If the base url ends with an empty _escaped_fragment_ property.
|
765 |
+
if (mb_ereg('_escaped_fragment_=$', $this->config['base_url'])) {
|
766 |
+
// Append nothing for this annoying edge case.
|
767 |
+
}
|
768 |
+
// Otherwise if there is something in the _escaped_fragment_ then append
|
769 |
+
// the escaped ampersand.
|
770 |
+
else if (mb_ereg('_escaped_fragment_=.+$', $this->config['base_url'])) {
|
771 |
+
$page_url_query_prefix = '%26';
|
772 |
+
}
|
773 |
+
// Otherwise we're back to thinking about query strings.
|
774 |
+
else if (!mb_ereg('[\?&]$', $this->config['base_url'])) {
|
775 |
+
if(mb_ereg('\?', $this->config['base_url'])) {
|
776 |
+
$page_url_query_prefix = '&';
|
777 |
+
} else {
|
778 |
+
$page_url_query_prefix = '?';
|
779 |
+
}
|
780 |
+
}
|
781 |
+
|
782 |
+
$content = mb_ereg_replace(
|
783 |
+
'{INSERT_PAGE_URI}',
|
784 |
+
// Make sure someone doesn't sneak in "><script>...<script> in the URL
|
785 |
+
// contents.
|
786 |
+
htmlspecialchars(
|
787 |
+
$this->config['base_url'] . $page_url_query_prefix,
|
788 |
+
ENT_QUOTES | ENT_HTML5,
|
789 |
+
$this->config['charset'],
|
790 |
+
// Don't double-encode.
|
791 |
+
false
|
792 |
+
),
|
793 |
+
$content
|
794 |
+
);
|
795 |
+
|
796 |
+
return $content;
|
797 |
+
}
|
798 |
+
|
799 |
+
/**
|
800 |
+
* Return hidden metadata for adding to SEO content.
|
801 |
+
*/
|
802 |
+
private function _buildComment($access_method) {
|
803 |
+
$bvf = new BVFooter($this, $access_method, $this->msg);
|
804 |
+
$footer = $bvf->buildSDKFooter();
|
805 |
+
$reveal = $this->_getBVReveal();
|
806 |
+
if ($reveal) {
|
807 |
+
$footer .= $bvf->buildSDKDebugFooter();
|
808 |
+
}
|
809 |
+
return $footer;
|
810 |
+
}
|
811 |
+
|
812 |
+
public function getBVMessages() {
|
813 |
+
return $this->msg;
|
814 |
+
}
|
815 |
+
|
816 |
+
public function getContent() {
|
817 |
+
$this->_setBuildMessage('Content Type "' . $this->config['content_type'] . '" is not supported by getContent().');
|
818 |
+
$pay_load = $this->_buildComment('', 'getContent');
|
819 |
+
|
820 |
+
return $pay_load;
|
821 |
+
}
|
822 |
+
|
823 |
+
public function getAggregateRating() {
|
824 |
+
$this->_setBuildMessage('Content Type "' . $this->config['content_type'] . '" is not supported by getAggregateRating().');
|
825 |
+
$pay_load = $this->_buildComment('', 'getAggregateRating');
|
826 |
+
|
827 |
+
return $pay_load;
|
828 |
+
}
|
829 |
+
|
830 |
+
public function getReviews() {
|
831 |
+
$this->_setBuildMessage('Content Type "' . $this->config['content_type'] . '" is not supported by getReviews().');
|
832 |
+
$pay_load = $this->_buildComment('', 'getReviews');
|
833 |
+
|
834 |
+
return $pay_load;
|
835 |
+
}
|
836 |
+
|
837 |
+
}
|
838 |
+
// end of Base class
|
839 |
+
|
840 |
+
/**
|
841 |
+
* Reviews Class
|
842 |
+
*
|
843 |
+
* Base class extention for work with "reviews" content type.
|
844 |
+
*/
|
845 |
+
class Reviews extends Base {
|
846 |
+
|
847 |
+
function __construct($params = array()) {
|
848 |
+
// call Base Class constructor
|
849 |
+
parent::__construct($params);
|
850 |
+
|
851 |
+
// since we are in the reviews class
|
852 |
+
// we need to set the content_type config
|
853 |
+
// to reviews so we get reviews in our
|
854 |
+
// SEO request
|
855 |
+
$this->config['content_type'] = 'reviews';
|
856 |
+
|
857 |
+
// for reviews subject type will always
|
858 |
+
// need to be product
|
859 |
+
$this->config['subject_type'] = 'product';
|
860 |
+
}
|
861 |
+
|
862 |
+
public function getAggregateRating() {
|
863 |
+
return $this->_renderAggregateRating();
|
864 |
+
}
|
865 |
+
|
866 |
+
public function getReviews() {
|
867 |
+
return $this->_renderReviews();
|
868 |
+
}
|
869 |
+
|
870 |
+
public function getContent() {
|
871 |
+
$payload = $this->_renderSEO('getContent');
|
872 |
+
|
873 |
+
if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) {
|
874 |
+
$subject_id = $this->config['page_params']['subject_id'];
|
875 |
+
} else {
|
876 |
+
$subject_id = $this->config['subject_id'];
|
877 |
+
}
|
878 |
+
// if they want to power display integration as well
|
879 |
+
// then we need to include the JS integration code
|
880 |
+
if ($this->config['include_display_integration_code']) {
|
881 |
+
$payload .= '
|
882 |
+
<script>
|
883 |
+
$BV.ui("rr", "show_reviews", {
|
884 |
+
productId: "' . $subject_id . '"
|
885 |
+
});
|
886 |
+
</script>
|
887 |
+
';
|
888 |
+
}
|
889 |
+
|
890 |
+
return $payload;
|
891 |
+
}
|
892 |
+
|
893 |
+
}
|
894 |
+
// end of Reviews class
|
895 |
+
|
896 |
+
/**
|
897 |
+
* Questions Class
|
898 |
+
*
|
899 |
+
* Base class extention for work with "questions" content type.
|
900 |
+
*/
|
901 |
+
class Questions extends Base {
|
902 |
+
|
903 |
+
function __construct($params = array()) {
|
904 |
+
// call Base Class constructor
|
905 |
+
parent::__construct($params);
|
906 |
+
|
907 |
+
// since we are in the questions class
|
908 |
+
// we need to set the content_type config
|
909 |
+
// to questions so we get questions in our
|
910 |
+
// SEO request
|
911 |
+
$this->config['content_type'] = 'questions';
|
912 |
+
}
|
913 |
+
|
914 |
+
public function getContent() {
|
915 |
+
$payload = $this->_renderSEO('getContent');
|
916 |
+
if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) {
|
917 |
+
$subject_id = $this->config['page_params']['subject_id'];
|
918 |
+
} else {
|
919 |
+
$subject_id = $this->config['subject_id'];
|
920 |
+
}
|
921 |
+
// if they want to power display integration as well
|
922 |
+
// then we need to include the JS integration code
|
923 |
+
if ($this->config['include_display_integration_code']) {
|
924 |
+
|
925 |
+
$payload .= '
|
926 |
+
<script>
|
927 |
+
$BV.ui("qa", "show_questions", {
|
928 |
+
productId: "' . $subject_id . '"
|
929 |
+
});
|
930 |
+
</script>
|
931 |
+
';
|
932 |
+
}
|
933 |
+
|
934 |
+
return $payload;
|
935 |
+
}
|
936 |
+
|
937 |
+
}
|
938 |
+
// end of Questions class
|
939 |
+
|
940 |
+
/**
|
941 |
+
* Stories Class
|
942 |
+
*
|
943 |
+
* Base class extention for work with "stories" content type.
|
944 |
+
*/
|
945 |
+
class Stories extends Base {
|
946 |
+
|
947 |
+
function __construct($params = array()) {
|
948 |
+
// call Base Class constructor
|
949 |
+
parent::__construct($params);
|
950 |
+
|
951 |
+
// since we are in the stories class
|
952 |
+
// we need to set the content_type config
|
953 |
+
// to stories so we get stories in our
|
954 |
+
// SEO request
|
955 |
+
$this->config['content_type'] = 'stories';
|
956 |
+
|
957 |
+
// for stories subject type will always
|
958 |
+
// need to be product
|
959 |
+
$this->config['subject_type'] = 'product';
|
960 |
+
|
961 |
+
// for stories we have to set content sub type
|
962 |
+
// the sub type is configured as either STORIES_LIST or STORIES_GRID
|
963 |
+
// the folder names are "stories" and "storiesgrid" respectively.
|
964 |
+
if (isset($this->config['content_sub_type'])
|
965 |
+
&& $this->config['content_sub_type'] == "stories_grid") {
|
966 |
+
$this->config['content_sub_type'] = "storiesgrid";
|
967 |
+
} else {
|
968 |
+
$this->config['content_sub_type'] = "stories";
|
969 |
+
}
|
970 |
+
}
|
971 |
+
|
972 |
+
public function getContent() {
|
973 |
+
$payload = $this->_renderSeo('getContent');
|
974 |
+
if (!empty($this->config['page_params']['subject_id']) && $this->_checkBVStateContentType()) {
|
975 |
+
$subject_id = $this->config['page_params']['subject_id'];
|
976 |
+
} else {
|
977 |
+
$subject_id = $this->config['subject_id'];
|
978 |
+
}
|
979 |
+
// if they want to power display integration as well
|
980 |
+
// then we need to include the JS integration code
|
981 |
+
if ($this->config['include_display_integration_code']) {
|
982 |
+
$payload .= '
|
983 |
+
<script>
|
984 |
+
$BV.ui("su", "show_stories", {
|
985 |
+
productId: "' . $subject_id . '"
|
986 |
+
});
|
987 |
+
</script>
|
988 |
+
';
|
989 |
+
}
|
990 |
+
|
991 |
+
return $payload;
|
992 |
+
}
|
993 |
+
|
994 |
+
}
|
995 |
+
// end of Stories class
|
996 |
+
|
997 |
+
class Spotlights extends Base {
|
998 |
+
|
999 |
+
function __construct($params = array()) {
|
1000 |
+
// call Base Class constructor
|
1001 |
+
parent::__construct($params);
|
1002 |
+
|
1003 |
+
// since we are in the spotlights class
|
1004 |
+
// we need to set the content_type config
|
1005 |
+
// to spotlights so we get reviews in our
|
1006 |
+
// SEO request
|
1007 |
+
$this->config['content_type'] = 'spotlights';
|
1008 |
+
|
1009 |
+
// for spotlights subject type will always
|
1010 |
+
// need to be category
|
1011 |
+
$this->config['subject_type'] = 'category';
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
public function getContent() {
|
1015 |
+
return $this->_renderSEO('getContent');
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
}
|
1019 |
+
// end of Spotlights class
|
1020 |
+
|
1021 |
+
class SellerRatings extends Base {
|
1022 |
+
|
1023 |
+
function __construct($params = array()) {
|
1024 |
+
|
1025 |
+
// call Base Class constructor
|
1026 |
+
parent::__construct($params);
|
1027 |
+
|
1028 |
+
// since we are in the Seller Rating class
|
1029 |
+
// we need to set the content_type config
|
1030 |
+
// to reviews so we get reviews in our
|
1031 |
+
// SEO request
|
1032 |
+
$this->config['content_type'] = 'reviews';
|
1033 |
+
|
1034 |
+
// for seller rating subject type will always
|
1035 |
+
// need to be seller
|
1036 |
+
$this->config['subject_type'] = 'seller';
|
1037 |
+
|
1038 |
+
}
|
1039 |
+
|
1040 |
+
public function getContent() {
|
1041 |
+
return $this->_renderSEO('getContent');
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
}
|
1045 |
+
// end of Spotlights class
|
1046 |
+
|
1047 |
+
|
1048 |
+
// end of bvseosdk.php
|
package.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Bazaarvoice_Connector</name>
|
4 |
-
<version>6.3.
|
5 |
<stability>stable</stability>
|
6 |
<license>Bazaarvoice, Inc.</license>
|
7 |
<channel>community</channel>
|
@@ -10,9 +10,9 @@
|
|
10 |
<description>See www.bazaarvoice.com for further details on our offerings</description>
|
11 |
<notes>Plugin corresponds to version 6.0.2 of the Bazaarvoice platform</notes>
|
12 |
<authors><author><name>BV DTS</name><user>bvdts</user><email>dts@bazaarvoice.com</email></author></authors>
|
13 |
-
<date>2016-
|
14 |
-
<time>
|
15 |
-
<contents><target name="magelocal"><dir name="Bazaarvoice"><dir name="Connector"><dir name="Block"><file name="Bazaarvoice.php" hash="473e92e58fd86c823fb55765ed473414"/><file name="Questions.php" hash="
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
18 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Bazaarvoice_Connector</name>
|
4 |
+
<version>6.3.3</version>
|
5 |
<stability>stable</stability>
|
6 |
<license>Bazaarvoice, Inc.</license>
|
7 |
<channel>community</channel>
|
10 |
<description>See www.bazaarvoice.com for further details on our offerings</description>
|
11 |
<notes>Plugin corresponds to version 6.0.2 of the Bazaarvoice platform</notes>
|
12 |
<authors><author><name>BV DTS</name><user>bvdts</user><email>dts@bazaarvoice.com</email></author></authors>
|
13 |
+
<date>2016-03-08</date>
|
14 |
+
<time>19:54:53</time>
|
15 |
+
<contents><target name="magelocal"><dir name="Bazaarvoice"><dir name="Connector"><dir name="Block"><file name="Bazaarvoice.php" hash="473e92e58fd86c823fb55765ed473414"/><file name="Questions.php" hash="d6716bdff6f2bf71c014b21c041a1d8d"/><file name="Ratings.php" hash="6822db584f2ee777beb8d39c662e8465"/><file name="Reviews.php" hash="06445b51aa4d80b5e78db88281b8aec2"/><dir name="Roi"><file name="Beacon.php" hash="2cdb524458a30eec2e0c9fe037858788"/></dir><file name="Submissioncontainer.php" hash="23d04ee9ece011d107bb8b914653a24d"/></dir><dir name="Helper"><file name="Data.php" hash="c5b526413097b81e0e9d1410cc5318fa"/><file name="Sftp.php" hash="1c2867bdaaaaa94e14848a07a2b6b688"/><file name="SftpConnection.php" hash="a50078565951d100aa2b7e98553f79e5"/></dir><dir name="Model"><file name="ExportProductFeed.php" hash="4ade5e0406a3e76f052d7f75de8e395a"/><file name="ExportPurchaseFeed.php" hash="01b13a019b1b94bf988d3a67fcbd17b9"/><dir name="Mysql4"><file name="Setup.php" hash="884c886c1e9fa395f05e7872ba6478a2"/></dir><dir name="ProductFeed"><file name="Brand.php" hash="b2ab72e79d7e3afe23b38bc3b64ba115"/><file name="Category.php" hash="abf1ea4943f855e56e99cdc26810c235"/><file name="Product.php" hash="fbd6ed422ba4f7be0084a50acde843bf"/></dir><file name="RetrieveInlineRatingsFeed.php" hash="c64ad33753408111e04322ef4b39ef34"/><file name="RetrieveSmartSEOPackage.php" hash="ececf2f31e0b3ca9c2dda4ed6967c8c1"/><dir name="Source"><file name="AuthenticationMethod.php" hash="582d6c76372bac64728e6e4d68f959e4"/><file name="Environment.php" hash="1e575c9adb480df80e4a8a917960bd55"/><file name="FeedGenerationScope.php" hash="b2450e4c0c69b0da328f1d0d7d67012a"/><file name="TriggeringEvent.php" hash="fa47f3a2fcec92d9603f21541c853035"/></dir></dir><dir name="controllers"><file name="FeedController.php" hash="933a1555d97ac2cec8ea52306cf63102"/><file name="IndexController.php" hash="16b9a353153d40ebc32e759112ca6d6f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="39cf8642bfc219709849618519a1c767"/><file name="config.xml" hash="5bb1743f7cbdc4aba581468f60772cb3"/><file name="system.xml" hash="807fc6e8d720e178099e24aece08e678"/></dir><dir name="sql"><dir name="bazaarvoice_setup"><file name="mysql4-install-0.1.0.php" hash="2cf37e5f08ae8bb7f8c43d23d9493e58"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Bazaarvoice_Connector.xml" hash="c517b52d29fec93a83a8010451368ee1"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="enterprise"><dir name="default"><dir name="template"><dir name="bazaarvoice"><dir name="display"><file name="headerincludes.phtml" hash="0faf96303bfe38e1c4130dfdbaff9c87"/><file name="headerproduct.phtml" hash="b2f48fcb558b33faeb4c6fa0cff7a064"/><dir name="qa"><file name="questions.phtml" hash="b5c186576e9c20cd764860ad08702349"/><file name="questionsummary.phtml" hash="c6044994c1d355730d7e5cfd3a6e3125"/></dir><dir name="rr"><file name="ratings.phtml" hash="56047515b347d0250d44e4e2eb0a923c"/><file name="reviews.phtml" hash="7d2ad8b18910010d22240c9521131290"/><file name="reviewsummary.phtml" hash="75e823088dd75387fc94e6028d8236a5"/></dir></dir><dir name="submit"><file name="roi_beacon.phtml" hash="494b9a44ceb14b1f376611d30ac18645"/><file name="submissioncontainer.phtml" hash="3f3f22b922c1aa5b87f7bbf4fbeea51c"/></dir></dir></dir><dir name="layout"><file name="bazaarvoice.xml" hash="e8d6c4a2ca62a21ddac1cd22e1ee8ad0"/></dir></dir></dir></dir></target><target name="magelocale"><dir name="en_US"><dir name="template"><dir name="email"><file name="bazaarvoice_notification.html" hash="9a0e90ac62d926dad4db13719f3c8b73"/></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="images"><dir name="bazaarvoice"><file name="rating-0_0.gif" hash="f50bd3f45f69a753614b2e76f53bdafc"/><file name="rating-1_0.gif" hash="c691e11e3250a18939aec523734d9b67"/><file name="rating-1_1.gif" hash="26377f1337bb6fb9e340292243a6f780"/><file name="rating-1_2.gif" hash="5c51583dc52d901c61d9470d5faeb2a4"/><file name="rating-1_3.gif" hash="3948c716d18ea0389ce9e57c347e7b6d"/><file name="rating-1_4.gif" hash="2211d8586bda467cb8fcc617670b94df"/><file name="rating-1_5.gif" hash="3fa9480c8b86f85749147fa0e8144b05"/><file name="rating-1_6.gif" hash="a577c79e7ea0c6c59ac15251c39de515"/><file name="rating-1_7.gif" hash="b5b52fa267632eda6ba5b3be56319397"/><file name="rating-1_8.gif" hash="205170e1ffbfcc81569286a9e1a88eb5"/><file name="rating-1_9.gif" hash="63709f7b2a2e2f14ae442dbef6513f25"/><file name="rating-2_0.gif" hash="4eec2468b5e41dc03d198ed6fe084a53"/><file name="rating-2_1.gif" hash="155cab7b16f4cfef3e94b99ca297cedc"/><file name="rating-2_2.gif" hash="2e2dc606fd83853bdf90a3beb901cf3e"/><file name="rating-2_3.gif" hash="638632f37a750558722c0bf1a79f2546"/><file name="rating-2_4.gif" hash="6b0a85c21066c6402b9f8914284b999f"/><file name="rating-2_5.gif" hash="c4792dac3b9d5a914a72a4200f931c6e"/><file name="rating-2_6.gif" hash="1c7ac3f4e3721d4779721973cfaaa8db"/><file name="rating-2_7.gif" hash="21b680dce6ffef505532afea7fea1452"/><file name="rating-2_8.gif" hash="136ac6b284d1a2b9452a06eea993c1fa"/><file name="rating-2_9.gif" hash="d13af6920569aa85da6dfb0a139d560a"/><file name="rating-3_0.gif" hash="6b30e597cc23aec52dbd2be978d52351"/><file name="rating-3_1.gif" hash="cb544d168a949100fb5ee117adbd765b"/><file name="rating-3_2.gif" hash="75124c4b4dfc5cbcf5ae3ccfa7bdf906"/><file name="rating-3_3.gif" hash="0693b6a471361957da1dc8ee2e9af5ec"/><file name="rating-3_4.gif" hash="1a6e3cff41a61e1bbed9296badb94392"/><file name="rating-3_5.gif" hash="7f63ecf505414386267fad2e92617a9f"/><file name="rating-3_6.gif" hash="8b9b9ccebc3537cffd2bed75c60eaa9e"/><file name="rating-3_7.gif" hash="7f83f3996a738d1fd6763204cd964376"/><file name="rating-3_8.gif" hash="219a1f2dbd45bcb58a58f460c9491bbf"/><file name="rating-3_9.gif" hash="e4114607ca469db2fd5f87ac21c4f00a"/><file name="rating-4_0.gif" hash="a15541525186bf6911202e0f64daa4a6"/><file name="rating-4_1.gif" hash="818971c067beb397247095f5eedbac29"/><file name="rating-4_2.gif" hash="5b9599176771adfbf8c52c7dfa04e565"/><file name="rating-4_3.gif" hash="18dc68db736819e17ab5cf0d5725d99c"/><file name="rating-4_4.gif" hash="56b124f1a2e599918b462ce29cd1cd96"/><file name="rating-4_5.gif" hash="2044f11b1f7005f66f14219c5fce1020"/><file name="rating-4_6.gif" hash="3166f044e7f73f9b3e75bda4507eaa35"/><file name="rating-4_7.gif" hash="20546d3ebee7a364927e9da9274996a7"/><file name="rating-4_8.gif" hash="9dab0f19785d1592a96c5c295842f308"/><file name="rating-4_9.gif" hash="19a47143b04aceae85def246059fba33"/><file name="rating-5_0.gif" hash="e43b403663785255d2f023ca35566ac3"/></dir></dir></dir></dir></dir></target><target name="magelib"><dir name="Bazaarvoice"><file name="BVFooter.php" hash="072c3a6899b189fd2631abc89e99c55e"/><file name="BVUtility.php" hash="a4f768441ee099d93e8c5899e62b19ac"/><file name="bvseosdk.php" hash="2feabbb99f2a002671f62a2f971a80e8"/></dir></target><target name="mageweb"><dir name="shell"><file name="bv_export_order_feed.php" hash="309995ede2f85d95a0b91d8845c06ae5"/><file name="bv_export_product_feed.php" hash="1696c363c97bf9943560045b297c98fb"/></dir><dir name="docs"><file name="Integrations_Magento_for_Bazaarvoice_v6.3.3.pdf" hash="73970f62877c75602e5c0eff38993cd8"/></dir></target></contents>
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
|
18 |
</package>
|