pixlee-for-magento - Version 2.0.0.23

Version Notes

- Add category widgets

Download this release

Release Info

Developer Yunfan Luo
Extension pixlee-for-magento
Version 2.0.0.23
Comparing to
See all releases


Code changes from version 2.0.0.24 to 2.0.0.23

Files changed (34) hide show
  1. app/code/community/Pixlee/Base/Helper/Data.php +0 -0
  2. app/code/community/Pixlee/Base/Model/Observer.php +0 -0
  3. app/code/community/Pixlee/Base/etc/config.xml +1 -1
  4. app/code/community/Pixlee/Base/etc/config.xml.bak +1 -1
  5. app/code/community/Pixlee/Base/version.txt +1 -1
  6. app/design/adminhtml/default/default/layout/pixlee/base.xml +0 -8
  7. app/design/adminhtml/default/default/template/pixlee/system/config/demo_button.phtml +0 -44
  8. app/design/adminhtml/default/default/template/pixlee/system/config/export_button.phtml +0 -28
  9. app/design/frontend/base/default/layout/pixlee/gallery.xml +0 -36
  10. app/design/frontend/base/default/template/pixlee/category_gallery.phtml +0 -29
  11. app/design/frontend/base/default/template/pixlee/gallery.phtml +0 -30
  12. app/design/frontend/base/default/template/pixlee/pixlee_tracking_pixel.phtml +0 -6
  13. app/etc/modules/Pixlee_Base.xml +0 -10
  14. lib/Pixlee/Pixlee.php +0 -182
  15. lib/Raven/Autoloader.php +0 -43
  16. lib/Raven/Breadcrumbs.php +0 -60
  17. lib/Raven/Breadcrumbs/ErrorHandler.php +0 -47
  18. lib/Raven/Breadcrumbs/MonologHandler.php +0 -94
  19. lib/Raven/Client.php +0 -1155
  20. lib/Raven/Compat.php +0 -135
  21. lib/Raven/Context.php +0 -23
  22. lib/Raven/CurlHandler.php +0 -117
  23. lib/Raven/ErrorHandler.php +0 -183
  24. lib/Raven/Exception.php +0 -4
  25. lib/Raven/Processor.php +0 -20
  26. lib/Raven/ReprSerializer.php +0 -41
  27. lib/Raven/SanitizeDataProcessor.php +0 -120
  28. lib/Raven/Serializer.php +0 -133
  29. lib/Raven/Stacktrace.php +0 -284
  30. lib/Raven/Util.php +0 -33
  31. lib/Raven/data/cacert.pem +0 -5134
  32. package.xml +29 -1
  33. skin/adminhtml/default/default/pixlee/base.css +0 -7
  34. skin/adminhtml/default/default/pixlee/pixlee_logo_133x24.png +0 -0
app/code/community/Pixlee/Base/Helper/Data.php CHANGED
File without changes
app/code/community/Pixlee/Base/Model/Observer.php CHANGED
File without changes
app/code/community/Pixlee/Base/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
<config>
3
<modules>
4
<Pixlee_Base>
5
- <version>2.0.0.24</version>
6
</Pixlee_Base>
7
</modules>
8
<default>
2
<config>
3
<modules>
4
<Pixlee_Base>
5
+ <version>2.0.0.23</version>
6
</Pixlee_Base>
7
</modules>
8
<default>
app/code/community/Pixlee/Base/etc/config.xml.bak CHANGED
@@ -2,7 +2,7 @@
2
<config>
3
<modules>
4
<Pixlee_Base>
5
- <version>2.0.0.24</version>
6
</Pixlee_Base>
7
</modules>
8
<default>
2
<config>
3
<modules>
4
<Pixlee_Base>
5
+ <version>2.0.0.23</version>
6
</Pixlee_Base>
7
</modules>
8
<default>
app/code/community/Pixlee/Base/version.txt CHANGED
@@ -1 +1 @@
1
- 3f657125cdaf7e0a0a4fe37da260176eec674dd1
1
+ 1ce7253de7c9800a7bfa769eeab6abd77dbdd400
app/design/adminhtml/default/default/layout/pixlee/base.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0"?>
2
- <layout>
3
- <adminhtml_system_config_edit>
4
- <reference name="head">
5
- <action method="addCss"><stylesheet>pixlee/base.css</stylesheet></action>
6
- </reference>
7
- </adminhtml_system_config_edit>
8
- </layout>
app/design/adminhtml/default/default/template/pixlee/system/config/demo_button.phtml DELETED
@@ -1,44 +0,0 @@
1
- <script type="text/javascript">
2
- //<![CDATA[
3
- function requestDemo() {
4
- var name = document.getElementById('pixlee_demo_name').value
5
- var email = document.getElementById('pixlee_demo_email').value
6
- var website = document.getElementById('pixlee_demo_website').value
7
-
8
-
9
- if (name === '') {
10
- alert('Name cannot be empty. Please try again.');
11
- return;
12
- }
13
- if (email === '') {
14
- alert('Email cannot be empty. Please try again.');
15
- return;
16
-
17
- }
18
-
19
- var params = "?source=magento_1&name=" + name + "&email=" + email + "&website" + website;
20
-
21
- var request = new XMLHttpRequest();
22
- request.onreadystatechange = function() {
23
- if (this.readyState == 4) {
24
- if (this.status >= 200 && this.status < 400) {
25
- var response = JSON.parse(this.responseText);
26
- if (response && response.result === "Successful") {
27
- $('request_demo_button').addClassName('disabled');
28
- alert('Thanks for requesting a demo. We will get in touch with you shortly.');
29
- } else {
30
- alert('Opps! Something went wrong. While we are working on resolving the issue, feel free to reach us at hi@pixleeteam.com');
31
- }
32
- } else {
33
- alert('Opps! Something went wrong. While we are working on resolving the issue, feel free to reach us at hi@pixleeteam.com');
34
- }
35
- }
36
- }
37
-
38
- request.open('POST', "https://app.pixlee.com/leads/add" + params, true);
39
- request.send();
40
- }
41
- //]]>
42
- </script>
43
-
44
- <?php echo $this->getButtonHtml() ?>
app/design/adminhtml/default/default/template/pixlee/system/config/export_button.phtml DELETED
@@ -1,28 +0,0 @@
1
- <script type="text/javascript">
2
- //<![CDATA[
3
- function exportToPixlee(url) {
4
- if($('pixlee_export_button').hasClassName('disabled')) {
5
- return;
6
- }
7
- $('pixlee_export_button').addClassName('disabled');
8
- new Ajax.Request(url, {
9
- method: 'get',
10
- onSuccess: function(transport){
11
- if (transport.responseText){
12
- var json = transport.responseText.evalJSON(true);
13
- if(json.pixlee_remaining_text) {
14
- $('pixlee_remaining').update(json.pixlee_remaining_text);
15
- }
16
- if(json.action == 'continue' && json.url) {
17
- $('pixlee_export_button').removeClassName('disabled');
18
- exportToPixlee(json.url);
19
- }
20
- }
21
- }
22
- });
23
- }
24
- //]]>
25
- </script>
26
-
27
- <?php echo $this->getButtonHtml() ?>
28
- <p class="note"><span id="pixlee_remaining"><?php echo Mage::helper('pixlee')->getPixleeRemainingText(); ?></span></p>
app/design/frontend/base/default/layout/pixlee/gallery.xml DELETED
@@ -1,36 +0,0 @@
1
- <?xml version="1.0"?>
2
- <layout version="0.1.0">
3
- <!--
4
- You should be able to make the following call on any page:
5
-
6
- <?php echo $this->getLayout()->createBlock('pixlee/gallery')->toHtml(); ?>
7
-
8
- The above will embed the Pixlee gallery in place and handle any
9
- responsive design you can throw at it.
10
-
11
- The Pixlee extension will attempt to discern the current product's
12
- SKU automatically in order to display the correct gallery, but if
13
- it is unable to do so you can explicitly set the product SKU with
14
- the "setProductSku" function like so:
15
-
16
- <?php echo $this->getLayout()->createBlock('pixlee/gallery')->setProductSku($SKU)->toHtml(); ?>
17
- -->
18
-
19
- <!-- How to insert your JavaScript on all Magento pages? http://magento.stackexchange.com/questions/59897/load-js-in-footer-in-magento -->
20
-
21
- <default>
22
- <reference name="head">
23
- <block type="core/text" name="pixlee_events">
24
- <action method="setText">
25
- <text>
26
- <![CDATA[
27
- <script type="text/javascript" src="https://assets.pixlee.com/assets/pixlee_events.js"></script>
28
- ]]>
29
- </text>
30
- </action>
31
- </block>
32
- <block type="page/html" name="pixlee_events_invocation" template="pixlee/pixlee_tracking_pixel.phtml"/>
33
- </reference>
34
- </default>
35
-
36
- </layout>
app/design/frontend/base/default/template/pixlee/category_gallery.phtml DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
- $helper = Mage::helper('pixlee');
3
- $nativeCategoryId = $this->category_id;
4
- if($helper->isActive() && !empty($nativeCategoryId)):
5
- $pixleeCategoryWidgetId = $this->getCategoryWidgetId();
6
- $pixleeAccountApiKey = $this->getAccountApiKey();
7
- ?>
8
- <div id="pixlee_container"></div>
9
- <div id="pixlee_widget_master_container"></div>
10
- <script id="pixlee_script">
11
-
12
- window.PixleeAsyncInit = function() {
13
- Pixlee.init({
14
- apiKey: '<?php echo $pixleeAccountApiKey; ?>'
15
- });
16
- Pixlee.addCategoryWidget({
17
- widgetId: <?php echo $pixleeCategoryWidgetId; ?>,
18
- nativeCategoryId: <?php echo $nativeCategoryId; ?>,
19
- ecomm_platform: 'magento'
20
- });
21
- };
22
- </script>
23
- <script src="https://assets.pixlee.com/assets/pixlee_widget_1_0_0.js"></script>
24
-
25
- <?php elseif(empty($nativeCategoryId)): ?>
26
- <!-- Could not display the Pixlee gallery. No product SKU found. Try explicitly setting one with the "setProductSku" function after creating the block. -->
27
- <?php else: ?>
28
- <!-- Could not display the Pixlee gallery. Make sure all the required credentials are saved in the Magento admin panel! -->
29
- <?php endif; ?>
app/design/frontend/base/default/template/pixlee/gallery.phtml DELETED
@@ -1,30 +0,0 @@
1
- <?php
2
- $helper = Mage::helper('pixlee');
3
- $productSku = $this->getProductSku();
4
- if($helper->isActive() && !empty($productSku)):
5
- $pixleeAccountId = $this->getAccountId();
6
- $pixleeWidgetId = $this->getWidgetId();
7
- $pixleeAccountApiKey = $this->getAccountApiKey();
8
- ?>
9
- <div id="pixlee_container"></div>
10
- <div id="pixlee_widget_master_container"></div>
11
- <script id="pixlee_script">
12
-
13
- window.PixleeAsyncInit = function() {
14
- Pixlee.init({
15
- apiKey: '<?php echo $pixleeAccountApiKey; ?>'
16
- });
17
- Pixlee.addProductWidget({
18
- widgetId: <?php echo $pixleeWidgetId; ?>,
19
- skuId: '<?php echo $productSku; ?>',
20
- accountId:<?php echo $pixleeAccountId; ?>
21
- });
22
- };
23
- </script>
24
- <script src="https://assets.pixlee.com/assets/pixlee_widget_1_0_0.js"></script>
25
-
26
- <?php elseif(empty($productSku)): ?>
27
- <!-- Could not display the Pixlee gallery. No product SKU found. Try explicitly setting one with the "setProductSku" function after creating the block. -->
28
- <?php else: ?>
29
- <!-- Could not display the Pixlee gallery. Make sure all the required credentials are saved in the Magento admin panel! -->
30
- <?php endif; ?>
app/design/frontend/base/default/template/pixlee/pixlee_tracking_pixel.phtml DELETED
@@ -1,6 +0,0 @@
1
- <?php
2
- $pixleeAccountApiKey = Mage::getStoreConfig('pixlee/pixlee/account_api_key', Mage::app()->getStore());
3
- ?>
4
- <script id="initialize_pixlee_tracking">
5
- pixlee_analytics = new Pixlee_Analytics('<?php echo $pixleeAccountApiKey; ?>');
6
- </script>
app/etc/modules/Pixlee_Base.xml DELETED
@@ -1,10 +0,0 @@
1
- <?xml version="1.0"?>
2
- <config>
3
- <modules>
4
- <Pixlee_Base>
5
- <active>true</active>
6
- <codePool>community</codePool>
7
- <depends></depends>
8
- </Pixlee_Base>
9
- </modules>
10
- </config>
lib/Pixlee/Pixlee.php DELETED
@@ -1,182 +0,0 @@
1
- <?php
2
- class Pixlee_Pixlee {
3
- private $apiKey;
4
- private $baseURL;
5
- private $secretKey;
6
-
7
- public function __construct($accountApiKey, $accountSecretKey){
8
- if( is_null( $accountApiKey )){
9
- throw new Exception("An API Key is required");
10
- }
11
- $this->apiKey = $accountApiKey;
12
- $this->secretKey = $accountSecretKey;
13
- $this->baseURL = "https://distillery.pixlee.com/api/v2";
14
- }
15
-
16
- public function getAlbums(){
17
- return $this->getFromAPI("/albums");
18
- }
19
-
20
- // The following functions don't seem to be used anywhere
21
- // The only functions I seem to NEED are:
22
- // 1) getAlbums, to make sure that the config is right, and we can hit the API
23
- // 2) createProduct, which doubles as "updateProduct," via POST
24
- // Not going to spend time figuring out the distillery versions of the following
25
- // v1 API calls, but leaving the original declarations here, in case I'm wrong
26
- /*
27
- public function getPhotos($albumID, $options = NULL ){
28
- return $this->getFromAPI( "/albums/$albumID/photos", $options);
29
- }
30
- public function getPhoto($albumID, $photoID, $options = NULL ){
31
- return $this->getFromAPI( "/albums/$albumID/photos/$photoID", $options);
32
- }
33
- // ex of $media = array('photo_url' => $newPhotoURL, 'email_address' => $email_address, 'type' => $type);
34
- public function createPhoto($albumID, $media){
35
- // assign media to the data key
36
- $data = array('media' => $media);
37
- $payload = $this->signedData($data);
38
- return $this->postToAPI( "/albums/$albumID/photos", $payload );
39
- }
40
- */
41
-
42
- public function createProduct($product_name, $sku, $product_url , $product_image, $product_id = NULL, $product_price, $aggregateStock = NULL, $variantsDict = NULL, $extraFields = NULL, $currencyCode, $update_stock_only = False){
43
- Mage::log("* In createProduct");
44
- /*
45
- Converted from Rails API format to distillery API format
46
- Also, now sending _account_ 'api_key' instead of _user_ 'api_key'
47
- Instead of:
48
- {
49
- 'album': {
50
- 'album_name': <VAL>
51
- }
52
- 'product: {
53
- 'name': <VAL>,
54
- 'sku': <VAL>,
55
- 'buy_now_link_url': <VAL>,
56
- 'product_photo': <VAL>
57
- }
58
- }
59
- Is now:
60
- {
61
- 'title': <VAL>,
62
- 'album_type': <VAL>,
63
- 'num_photo': <VAL>,
64
- 'num_inbox_photo': <VAL>,
65
- 'product':
66
- 'name': <VAL>,
67
- 'sku': <VAL>,
68
- 'buy_now_link_url': <VAL>,
69
- 'product_photo': <VAL>
70
- }
71
- }
72
- */
73
-
74
- // I feel like this is the result of a long chain of engineers being uncertain, that
75
- // a product's ID, which is inaccesible to the user, and almost certainly a number,
76
- // comes back as a string from $product->getId(). I'm just going to decide to break the cycle.
77
- // Let's hope I'm right.
78
- $product_id = (int) $product_id;
79
-
80
- // If 'update_stock_only' is True (which it is not by default), do not send the URL along
81
- if ($update_stock_only == True) {
82
- $product = array('name' => $product_name, 'sku' => $sku, 'stock' => $aggregateStock);
83
- } else {
84
- $product = array('name' => $product_name, 'sku' => $sku, 'buy_now_link_url' => $product_url,
85
- 'product_photo' => $product_image, 'price' => $product_price, 'stock' => $aggregateStock,
86
- 'native_product_id' => $product_id, 'variants_json' => $variantsDict,
87
- 'extra_fields' => $extraFields, 'currency' => $currencyCode);
88
- }
89
- $data = array('title' => $product_name, 'album_type' => 'product', 'live_update' => false, 'num_photo' => 0,
90
- 'num_inbox_photo' => 0, 'product' => $product);
91
-
92
- //Fix for php versions that don't support JSON_UNESCAPED_SLASHES (< php 5.4)
93
- if(defined("JSON_UNESCAPED_SLASHES")){
94
- $payload = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
95
- } else {
96
- $payload = str_replace('\\/', '/', json_encode($data));
97
- }
98
- return $this->postToAPI( "/albums?api_key=" . $this->apiKey, $payload );
99
- }
100
-
101
- // Private functions
102
- private function getFromAPI( $uri, $options = NULL ){
103
- $apiString = "?api_key=".$this->apiKey;
104
- $urlToHit = $this->baseURL;
105
- $urlToHit = $urlToHit . $uri . $apiString;
106
-
107
- if( !is_null($options)){
108
- $queryString = http_build_query($options);
109
- $urlToHit = $urlToHit . "&" . $queryString;
110
- }
111
-
112
- $ch = curl_init( $urlToHit );
113
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
114
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
115
- curl_setopt($ch, CURLOPT_HTTPHEADER, array(
116
- 'Content-Type: application/json'
117
- )
118
- );
119
- $response = curl_exec($ch);
120
-
121
- return $this->handleResponse($response, $ch);
122
- }
123
-
124
- private function postToAPI($uri, $payload){
125
- Mage::log("*** In postToAPI");
126
- Mage::log("With this URI: {$uri}");
127
- $urlToHit = $this->baseURL . $uri;
128
-
129
- $ch = curl_init( $urlToHit );
130
- Mage::log("Hitting URL: {$urlToHit}");
131
- Mage::log("With payload: {$payload}");
132
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
133
- curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
134
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
135
- curl_setopt($ch, CURLOPT_HTTPHEADER, array(
136
- 'Content-Type: application/json',
137
- 'X-Alt-Referer: magento.pixlee.com',
138
- 'Content-Length: ' . strlen($payload),
139
- 'Signature: ' . $this->generateSignature($payload)
140
- )
141
- );
142
- $response = curl_exec($ch);
143
-
144
- Mage::log("Got response: {$response}");
145
- return $this->handleResponse($response, $ch);
146
- }
147
-
148
- private function generateSignature($data) {
149
- return base64_encode(hash_hmac('sha1', $data, $this->secretKey, true));
150
- }
151
-
152
- private function handleResponse($response, $ch){
153
- $responseInfo = curl_getinfo($ch);
154
- $responseCode = $responseInfo['http_code'];
155
- $theResult = json_decode($response);
156
-
157
- curl_close($ch);
158
-
159
- // Unlike the rails API, distillery doesn't return such pretty statuses
160
- // On successful creation, we get a JSON with the created product's fields:
161
- // {"id":217127,"title":"Tori Tank","user_id":1055,"account_id":216,"public_contribution":false,"thumbnail_id":0,"inbox_thumbnail_id":0,"public_viewing":false,"description":null,"deleted_at":null,"public_token":null,"moderation":false,"email_slug":"A27EfF","campaign":false,"instructions":null,"action_link":null,"password":null,"has_password":false,"collect_email":false,"collect_custom_1":false,"collect_custom_1_field":null,"location_updated_at":null,"captions_updated_at":null,"redis_count":null,"num_inbox_photos":null,"unread_messages":null,"num_photos":null,"updated_dead_at":null,"live_update":false,"album_type":"product","display_options":{},"photos":[],"created_at":"2016-03-11 04:28:45.592","updated_at":"2016-03-11 04:28:45.592"}
162
- // On product update, we just get a string that says:
163
- // Product updated.
164
- // Suppose we'll check the HTTP return code, but not expect a JSON 'status' field
165
- if( !$this->isBetween( $responseCode, 200, 299 ) ){
166
- throw new Exception("HTTP $responseCode response from API");
167
- }else{
168
- return $theResult;
169
- }
170
- }
171
-
172
- private function isBetween($theNum, $low, $high){
173
- if($theNum >= $low && $theNum <= $high){
174
- return true;
175
- }
176
- else{
177
- return false;
178
- }
179
- }
180
- }
181
-
182
- ?>
lib/Raven/Autoloader.php DELETED
@@ -1,43 +0,0 @@
1
- <?php
2
-
3
- /*
4
- * This file is part of Raven.
5
- *
6
- * (c) Sentry Team
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
-
12
- /**
13
- * Autoloads Raven classes.
14
- *
15
- * @package raven
16
- */
17
- class Raven_Autoloader
18
- {
19
- /**
20
- * Registers Raven_Autoloader as an SPL autoloader.
21
- */
22
- public static function register()
23
- {
24
- ini_set('unserialize_callback_func', 'spl_autoload_call');
25
- spl_autoload_register(array('Raven_Autoloader', 'autoload'));
26
- }
27
-
28
- /**
29
- * Handles autoloading of classes.
30
- *
31
- * @param string $class A class name.
32
- */
33
- public static function autoload($class)
34
- {
35
- if (0 !== strpos($class, 'Raven')) {
36
- return;
37
- }
38
-
39
- if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
40
- require $file;
41
- }
42
- }
43
- }
lib/Raven/Breadcrumbs.php DELETED
@@ -1,60 +0,0 @@
1
- <?php
2
- /*
3
- * This file is part of Raven.
4
- *
5
- * (c) Sentry Team
6
- *
7
- * For the full copyright and license information, please view the LICENSE
8
- * file that was distributed with this source code.
9
- */
10
-
11
- /**
12
- * Raven Breadcrumbs
13
- *
14
- * @package raven
15
- */
16
-
17
- class Raven_Breadcrumbs
18
- {
19
- public function __construct($size = 100)
20
- {
21
- $this->count = 0;
22
- $this->pos = 0;
23
- $this->size = $size;
24
- $this->buffer = array();
25
- }
26
-
27
- public function record($crumb)
28
- {
29
- if (empty($crumb['timestamp'])) {
30
- $crumb['timestamp'] = microtime(true);
31
- }
32
- $this->buffer[$this->pos] = $crumb;
33
- $this->pos = ($this->pos + 1) % $this->size;
34
- $this->count++;
35
- }
36
-
37
- public function fetch()
38
- {
39
- $results = array();
40
- for ($i = 0; $i <= ($this->size - 1); $i++) {
41
- $idx = ($this->pos + $i) % $this->size;
42
- if (isset($this->buffer[$idx])) {
43
- $results[] = $this->buffer[$idx];
44
- }
45
- }
46
- return $results;
47
- }
48
-
49
- public function is_empty()
50
- {
51
- return $this->count === 0;
52
- }
53
-
54
- public function to_json()
55
- {
56
- return array(
57
- 'values' => $this->fetch(),
58
- );
59
- }
60
- }
lib/Raven/Breadcrumbs/ErrorHandler.php DELETED
@@ -1,47 +0,0 @@
1
- <?php
2
-
3
- class Raven_Breadcrumbs_ErrorHandler
4
- {
5
- private $existingHandler;
6
-
7
- /**
8
- * @var Raven_Client the client object that sends the message to the server
9
- */
10
- protected $ravenClient;
11
-
12
- /**
13
- * @param Raven_Client $ravenClient
14
- * @param int $level The minimum logging level at which this handler will be triggered
15
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
16
- */
17
- public function __construct(Raven_Client $ravenClient)
18
- {
19
- $this->ravenClient = $ravenClient;
20
- }
21
-
22
- public function handleError($code, $message, $file = '', $line = 0, $context=array())
23
- {
24
- $this->ravenClient->breadcrumbs->record(array(
25
- 'category' => 'error_reporting',
26
- 'message' => $message,
27
- 'level' => $this->ravenClient->translateSeverity($code),
28
- 'data' => array(
29
- 'code' => $code,
30
- 'line' => $line,
31
- 'file' => $file,
32
- ),
33
- ));
34
-
35
- if ($this->existingHandler !== null) {
36
- return call_user_func($this->existingHandler, $code, $message, $file, $line, $context);
37
- } else {
38
- return false;
39
- }
40
- }
41
-
42
- public function install()
43
- {
44
- $this->existingHandler = set_error_handler(array($this, 'handleError'), E_ALL);
45
- return $this;
46
- }
47
- }
lib/Raven/Breadcrumbs/MonologHandler.php DELETED
@@ -1,94 +0,0 @@
1
- <?php
2
-
3
- use Monolog\Logger;
4
- use Monolog\Handler\AbstractProcessingHandler;
5
-
6
- class Raven_Breadcrumbs_MonologHandler extends AbstractProcessingHandler
7
- {
8
- /**
9
- * Translates Monolog log levels to Raven log levels.
10
- */
11
- private $logLevels = array(
12
- Logger::DEBUG => Raven_Client::DEBUG,
13
- Logger::INFO => Raven_Client::INFO,
14
- Logger::NOTICE => Raven_Client::INFO,
15
- Logger::WARNING => Raven_Client::WARNING,
16
- Logger::ERROR => Raven_Client::ERROR,
17
- Logger::CRITICAL => Raven_Client::FATAL,
18
- Logger::ALERT => Raven_Client::FATAL,
19
- Logger::EMERGENCY => Raven_Client::FATAL,
20
- );
21
-
22
- private $excMatch = '/^exception \'([^\']+)\' with message \'(.+)\' in .+#x2F;s';
23
-
24
- /**
25
- * @var Raven_Client the client object that sends the message to the server
26
- */
27
- protected $ravenClient;
28
-
29
- /**
30
- * @param Raven_Client $ravenClient
31
- * @param int $level The minimum logging level at which this handler will be triggered
32
- * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
33
- */
34
- public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
35
- {
36
- parent::__construct($level, $bubble);
37
-
38
- $this->ravenClient = $ravenClient;
39
- }
40
-
41
- protected function parseException($message)
42
- {
43
- if (!preg_match($this->excMatch, $message, $matches)) {
44
- return;
45
- }
46
-
47
- return array($matches[1], $matches[2]);
48
- }
49
-
50
- /**
51
- * {@inheritdoc}
52
- */
53
- protected function write(array $record)
54
- {
55
- // sentry uses the 'nobreadcrumb' attribute to skip reporting
56
- if (!empty($record['context']['nobreadcrumb'])) {
57
- return;
58
- }
59
-
60
- if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
61
- $exc = $record['context']['exception'];
62
- $crumb = array(
63
- 'type' => 'error',
64
- 'level' => $this->logLevels[$record['level']],
65
- 'category' => $record['channel'],
66
- 'data' => array(
67
- 'type' => get_class($exc),
68
- 'value' => $exc->getMessage(),
69
- ),
70
- );
71
- } else {
72
- // TODO(dcramer): parse exceptions out of messages and format as above
73
- if ($error = $this->parseException($record['message'])) {
74
- $crumb = array(
75
- 'type' => 'error',
76
- 'level' => $this->logLevels[$record['level']],
77
- 'category' => $record['channel'],
78
- 'data' => array(
79
- 'type' => $error[0],
80
- 'value' => $error[1],
81
- ),
82
- );
83
- } else {
84
- $crumb = array(
85
- 'level' => $this->logLevels[$record['level']],
86
- 'category' => $record['channel'],
87
- 'message' => $record['message'],
88
- );
89
- }
90
- }
91
-
92
- $this->ravenClient->breadcrumbs->record($crumb);
93
- }
94
- }
lib/Raven/Client.php DELETED
@@ -1,1155 +0,0 @@
1
- <?php
2
- /*
3
- * This file is part of Raven.
4
- *
5
- * (c) Sentry Team
6
- *
7
- * For the full copyright and license information, please view the LICENSE
8
- * file that was distributed with this source code.
9
- */
10
-
11
- /**
12
- * Raven PHP Client
13
- *
14
- * @package raven
15
- */
16
-
17
- class Raven_Client
18
- {
19
- const VERSION = '1.2.0';
20
-
21
- const PROTOCOL = '6';
22
-
23
- const DEBUG = 'debug';
24
- const INFO = 'info';
25
- const WARN = 'warning';
26
- const WARNING = 'warning';
27
- const ERROR = 'error';
28
- const FATAL = 'fatal';
29
-
30
- const MESSAGE_LIMIT = 1024;
31
-
32
- public $breadcrumbs;
33
- public $context;
34
- public $extra_data;
35
- public $severity_map;
36
- public $store_errors_for_bulk_send = false;
37
-
38
- private $error_handler;
39
-
40
- private $serializer;
41
- private $reprSerializer;
42
-
43
- public function __construct($options_or_dsn=null, $options=array())
44
- {
45
- if (is_array($options_or_dsn)) {
46
- $options = array_merge($options_or_dsn, $options);
47
- }
48
-
49
- if (!is_array($options_or_dsn) && !empty($options_or_dsn)) {
50
- $dsn = $options_or_dsn;
51
- } elseif (!empty($_SERVER['SENTRY_DSN'])) {
52
- $dsn = @$_SERVER['SENTRY_DSN'];
53
- } elseif (!empty($options['dsn'])) {
54
- $dsn = $options['dsn'];
55
- } else {
56
- $dsn = null;
57
- }
58
-
59
- if (!empty($dsn)) {
60
- $options = array_merge($options, self::parseDSN($dsn));
61
- }
62
-
63
- $this->logger = Raven_Util::get($options, 'logger', 'php');
64
- $this->server = Raven_Util::get($options, 'server');
65
- $this->secret_key = Raven_Util::get($options, 'secret_key');
66
- $this->public_key = Raven_Util::get($options, 'public_key');
67
- $this->project = Raven_Util::get($options, 'project', 1);
68
- $this->auto_log_stacks = (bool) Raven_Util::get($options, 'auto_log_stacks', false);
69
- $this->name = Raven_Util::get($options, 'name', Raven_Compat::gethostname());
70
- $this->site = Raven_Util::get($options, 'site', $this->_server_variable('SERVER_NAME'));
71
- $this->tags = Raven_Util::get($options, 'tags', array());
72
- $this->release = Raven_Util::get($options, 'release', null);
73
- $this->environment = Raven_Util::get($options, 'environment', null);
74
- $this->trace = (bool) Raven_Util::get($options, 'trace', true);
75
- $this->timeout = Raven_Util::get($options, 'timeout', 2);
76
- $this->message_limit = Raven_Util::get($options, 'message_limit', self::MESSAGE_LIMIT);
77
- $this->exclude = Raven_Util::get($options, 'exclude', array());
78
- $this->severity_map = null;
79
- $this->shift_vars = (bool) Raven_Util::get($options, 'shift_vars', true);
80
- $this->http_proxy = Raven_Util::get($options, 'http_proxy');
81
- $this->extra_data = Raven_Util::get($options, 'extra', array());
82
- $this->send_callback = Raven_Util::get($options, 'send_callback', null);
83
- $this->curl_method = Raven_Util::get($options, 'curl_method', 'sync');
84
- $this->curl_path = Raven_Util::get($options, 'curl_path', 'curl');
85
- $this->curl_ipv4 = Raven_Util::get($options, 'curl_ipv4', true);
86
- $this->ca_cert = Raven_Util::get($options, 'ca_cert', $this->get_default_ca_cert());
87
- $this->verify_ssl = Raven_Util::get($options, 'verify_ssl', true);
88
- $this->curl_ssl_version = Raven_Util::get($options, 'curl_ssl_version');
89
- $this->trust_x_forwarded_proto = Raven_Util::get($options, 'trust_x_forwarded_proto');
90
- $this->transport = Raven_Util::get($options, 'transport', null);
91
- $this->mb_detect_order = Raven_Util::get($options, 'mb_detect_order', null);
92
-
93
- // app path is used to determine if code is part of your application
94
- $this->setAppPath(Raven_Util::get($options, 'app_path', null));
95
- // a list of prefixes used to coerce absolute paths into relative
96
- $this->setPrefixes(Raven_Util::get($options, 'prefixes', null));
97
- $this->processors = $this->setProcessorsFromOptions($options);
98
-
99
- $this->_lasterror = null;
100
- $this->_last_event_id = null;
101
- $this->_user = null;
102
- $this->_pending_events = array();
103
- $this->context = new Raven_Context();
104
- $this->breadcrumbs = new Raven_Breadcrumbs();
105
- $this->sdk = Raven_Util::get($options, 'sdk', array(
106
- 'name' => 'sentry-php',
107
- 'version' => self::VERSION,
108
- ));
109
- $this->serializer = new Raven_Serializer($this->mb_detect_order);
110
- $this->reprSerializer = new Raven_ReprSerializer($this->mb_detect_order);
111
-
112
- if ($this->curl_method == 'async') {
113
- $this->_curl_handler = new Raven_CurlHandler($this->get_curl_options());
114
- }
115
-
116
- if (Raven_Util::get($options, 'install_default_breadcrumb_handlers', true)) {
117
- $this->registerDefaultBreadcrumbHandlers();
118
- }
119
-
120
- register_shutdown_function(array($this, 'onShutdown'));
121
- }
122
-
123
- /**
124
- * Installs any available automated hooks (such as error_reporting).
125
- */
126
- public function install()
127
- {
128
- if ($this->error_handler) {
129
- throw new Raven_Exception(sprintf('%s->install() must only be called once', get_class($this)));
130
- }
131
- $this->error_handler = new Raven_ErrorHandler($this);
132
- $this->error_handler->registerExceptionHandler();
133
- $this->error_handler->registerErrorHandler();
134
- $this->error_handler->registerShutdownFunction();
135
- return $this;
136
- }
137
-
138
- public function getRelease()
139
- {
140
- return $this->release;
141
- }
142
-
143
- public function setRelease($value)
144
- {
145
- $this->release = $value;
146
- return $this;
147
- }
148
-
149
- public function getEnvironment()
150
- {
151
- return $this->environment;
152
- }
153
-
154
- public function setEnvironment($value)
155
- {
156
- $this->environment = $value;
157
- return $this;
158
- }
159
-
160
- public function getAppPath()
161
- {
162
- return $this->app_path;
163
- }
164
-
165
- public function setAppPath($value)
166
- {
167
- $this->app_path = $value ? realpath($value) : null;
168
- return $this;
169
- }
170
-
171
- public function getPrefixes()
172
- {
173
- return $this->prefixes;
174
- }
175
-
176
- public function setPrefixes($value)
177
- {
178
- $this->prefixes = $value ? array_map('realpath', $value) : $value;
179
- return $this;
180
- }
181
-
182
- public function getSendCallback()
183
- {
184
- return $this->send_callback;
185
- }
186
-
187
- public function setSendCallback($value)
188
- {
189
- $this->send_callback = $value;
190
- return $this;
191
- }
192
-
193
- public function getTransport()
194
- {
195
- return $this->transport;
196
- }
197
-
198
- public function getServerEndpoint($value)
199
- {
200
- return $this->server;
201
- }
202
-
203
- public function getUserAgent()
204
- {
205
- return 'sentry-php/' . self::VERSION;
206
- }
207
-
208
- /**
209
- * Set a custom transport to override how Sentry events are sent upstream.
210
- *
211
- * The bound function will be called with ``$client`` and ``$data`` arguments
212
- * and is responsible for encoding the data, authenticating, and sending
213
- * the data to the upstream Sentry server.
214
- *
215
- * @param function $value Function to be called
216
- */
217
- public function setTransport($value)
218
- {
219
- $this->transport = $value;
220
- return $this;
221
- }
222
-
223
- public static function getDefaultProcessors()
224
- {
225
- return array(
226
- 'Raven_SanitizeDataProcessor',
227
- );
228
- }
229
-
230
- /**
231
- * Sets the Raven_Processor sub-classes to be used when data is processed before being
232
- * sent to Sentry.
233
- *
234
- * @param $options
235
- * @return array
236
- */
237
- public function setProcessorsFromOptions($options)
238
- {
239
- $processors = array();
240
- foreach (Raven_util::get($options, 'processors', self::getDefaultProcessors()) as $processor) {
241
- $new_processor = new $processor($this);
242
-
243
- if (isset($options['processorOptions']) && is_array($options['processorOptions'])) {
244
- if (isset($options['processorOptions'][$processor]) && method_exists($processor, 'setProcessorOptions')) {
245
- $new_processor->setProcessorOptions($options['processorOptions'][$processor]);
246
- }
247
- }
248
- $processors[] = $new_processor;
249
- }
250
- return $processors;
251
- }
252
-
253
- /**
254
- * Parses a Raven-compatible DSN and returns an array of its values.
255
- *
256
- * @param string $dsn Raven compatible DSN: http://raven.readthedocs.org/en/latest/config/#the-sentry-dsn
257
- * @return array parsed DSN
258
- */
259
- public static function parseDSN($dsn)
260
- {
261
- $url = parse_url($dsn);
262
- $scheme = (isset($url['scheme']) ? $url['scheme'] : '');
263
- if (!in_array($scheme, array('http', 'https'))) {
264
- throw new InvalidArgumentException('Unsupported Sentry DSN scheme: ' . (!empty($scheme) ? $scheme : '<not set>'));
265
- }
266
- $netloc = (isset($url['host']) ? $url['host'] : null);
267
- $netloc.= (isset($url['port']) ? ':'.$url['port'] : null);
268
- $rawpath = (isset($url['path']) ? $url['path'] : null);
269
- if ($rawpath) {
270
- $pos = strrpos($rawpath, '/', 1);
271
- if ($pos !== false) {
272
- $path = substr($rawpath, 0, $pos);
273
- $project = substr($rawpath, $pos + 1);
274
- } else {
275
- $path = '';
276
- $project = substr($rawpath, 1);
277
- }
278
- } else {
279
- $project = null;
280
- $path = '';
281
- }
282
- $username = (isset($url['user']) ? $url['user'] : null);
283
- $password = (isset($url['pass']) ? $url['pass'] : null);
284
- if (empty($netloc) || empty($project) || empty($username) || empty($password)) {
285
- throw new InvalidArgumentException('Invalid Sentry DSN: ' . $dsn);
286
- }
287
-
288
- return array(
289
- 'server' => sprintf('%s://%s%s/api/%s/store/', $scheme, $netloc, $path, $project),
290
- 'project' => $project,
291
- 'public_key' => $username,
292
- 'secret_key' => $password,
293
- );
294
- }
295
-
296
- public function getLastError()
297
- {
298
- return $this->_lasterror;
299
- }
300
-
301
- /**
302
- * Given an identifier, returns a Sentry searchable string.
303
- */
304
- public function getIdent($ident)
305
- {
306
- // XXX: We don't calculate checksums yet, so we only have the ident.
307
- return $ident;
308
- }
309
-
310
- /**
311
- * Deprecated
312
- */
313
- public function message($message, $params=array(), $level=self::INFO,
314
- $stack=false, $vars = null)
315
- {
316
- return $this->captureMessage($message, $params, $level, $stack, $vars);
317
- }
318
-
319
- /**
320
- * Deprecated
321
- */
322
- public function exception($exception)
323
- {
324
- return $this->captureException($exception);
325
- }
326
-
327
- /**
328
- * Log a message to sentry
329
- *
330
- * @param string $message The message (primary description) for the event.
331
- * @param array $params params to use when formatting the message.
332
- * @param array $data Additional attributes to pass with this event (see Sentry docs).
333
- */
334
- public function captureMessage($message, $params=array(), $data=array(),
335
- $stack=false, $vars = null)
336
- {
337
- // Gracefully handle messages which contain formatting characters, but were not
338
- // intended to be used with formatting.
339
- if (!empty($params)) {
340
- $formatted_message = vsprintf($message, $params);
341
- } else {
342
- $formatted_message = $message;
343
- }
344
-
345
- if ($data === null) {
346
- $data = array();
347
- // support legacy method of passing in a level name as the third arg
348
- } elseif (!is_array($data)) {
349
- $data = array(
350
- 'level' => $data,
351
- );
352
- }
353
-
354
- $data['message'] = $formatted_message;
355
- $data['sentry.interfaces.Message'] = array(
356
- 'message' => $message,
357
- 'params' => $params,
358
- 'formatted' => $formatted_message,
359
- );
360
-
361
- return $this->capture($data, $stack, $vars);
362
- }
363
-
364
- /**
365
- * Log an exception to sentry
366
- *
367
- * @param Exception $exception The Exception object.
368
- * @param array $data Additional attributes to pass with this event (see Sentry docs).
369
- */
370
- public function captureException($exception, $data=null, $logger=null, $vars=null)
371
- {
372
- $has_chained_exceptions = version_compare(PHP_VERSION, '5.3.0', '>=');
373
-
374
- if (in_array(get_class($exception), $this->exclude)) {
375
- return null;
376
- }
377
-
378
- if ($data === null) {
379
- $data = array();
380
- } elseif (!is_array($data)) {
381
- $data = array(
382
- 'culprit' => (string)$data,
383
- );
384
- }
385
-
386
- $exc = $exception;
387
- do {
388
- $exc_data = array(
389
- 'value' => $this->serializer->serialize($exc->getMessage()),
390
- 'type' => get_class($exc),
391
- 'module' => $exc->getFile() .':'. $exc->getLine(),
392
- );
393
-
394
- /**'exception'
395
- * Exception::getTrace doesn't store the point at where the exception
396
- * was thrown, so we have to stuff it in ourselves. Ugh.
397
- */
398
- $trace = $exc->getTrace();
399
- $frame_where_exception_thrown = array(
400
- 'file' => $exc->getFile(),
401
- 'line' => $exc->getLine(),
402
- );
403
-
404
- array_unshift($trace, $frame_where_exception_thrown);
405
-
406
- // manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
407
- if (!class_exists('Raven_Stacktrace')) {
408
- spl_autoload_call('Raven_Stacktrace');
409
- }
410
-
411
- $exc_data['stacktrace'] = array(
412
- 'frames' => Raven_Stacktrace::get_stack_info(
413
- $trace, $this->trace, $this->shift_vars, $vars, $this->message_limit, $this->prefixes,
414
- $this->app_path, $this->serializer, $this->reprSerializer
415
- ),
416
- );
417
-
418
- $exceptions[] = $exc_data;
419
- } while ($has_chained_exceptions && $exc = $exc->getPrevious());
420
-
421
- $data['exception'] = array(
422
- 'values' => array_reverse($exceptions),
423
- );
424
- if ($logger !== null) {
425
- $data['logger'] = $logger;
426
- }
427
-
428
- if (empty($data['level'])) {
429
- if (method_exists($exception, 'getSeverity')) {
430
- $data['level'] = $this->translateSeverity($exception->getSeverity());
431
- } else {
432
- $data['level'] = self::ERROR;
433
- }
434
- }
435
-
436
- return $this->capture($data, $trace, $vars);
437
- }
438
-
439
-
440
- /**
441
- * Capture the most recent error (obtained with ``error_get_last``).
442
- */
443
- public function captureLastError()
444
- {
445
- if (null === $error = error_get_last()) {
446
- return;
447
- }
448
-
449
- $e = new ErrorException(
450
- @$error['message'], 0, @$error['type'],
451
- @$error['file'], @$error['line']
452
- );
453
-
454
- return $this->captureException($e);
455
- }
456
-
457
- /**
458
- * Log an query to sentry
459
- */
460
- public function captureQuery($query, $level=self::INFO, $engine = '')
461
- {
462
- $data = array(
463
- 'message' => $query,
464
- 'level' => $level,
465
- 'sentry.interfaces.Query' => array(
466
- 'query' => $query
467
- )
468
- );
469
-
470
- if ($engine !== '') {
471
- $data['sentry.interfaces.Query']['engine'] = $engine;
472
- }
473
- return $this->capture($data, false);
474
- }
475
-
476
- /**
477
- * Return the last captured event's ID or null if none available.
478
- */
479
- public function getLastEventID()
480
- {
481
- return $this->_last_event_id;
482
- }
483
-
484
- protected function registerDefaultBreadcrumbHandlers()
485
- {
486
- $handler = new Raven_Breadcrumbs_ErrorHandler($this);
487
- $handler->install();
488
- }
489
-
490
- protected function is_http_request()
491
- {
492
- return isset($_SERVER['REQUEST_METHOD']) && PHP_SAPI !== 'cli';
493
- }
494
-
495
- protected function get_http_data()
496
- {
497
- $headers = array();
498
-
499
- foreach ($_SERVER as $key => $value) {
500
- if (0 === strpos($key, 'HTTP_')) {
501
- $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))))] = $value;
502
- } elseif (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH')) && $value !== '') {
503
- $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))))] = $value;
504
- }
505
- }
506
-
507
- $result = array(
508
- 'method' => $this->_server_variable('REQUEST_METHOD'),
509
- 'url' => $this->get_current_url(),
510
- 'query_string' => $this->_server_variable('QUERY_STRING'),
511
- );
512
-
513
- // dont set this as an empty array as PHP will treat it as a numeric array
514
- // instead of a mapping which goes against the defined Sentry spec
515
- if (!empty($_POST)) {
516
- $result['data'] = $_POST;
517
- }
518
- if (!empty($_COOKIE)) {
519
- $result['cookies'] = $_COOKIE;
520
- }
521
- if (!empty($headers)) {
522
- $result['headers'] = $headers;
523
- }
524
-
525
- return array(
526
- 'request' => $result,
527
- );
528
- }
529
-
530
- protected function get_user_data()
531
- {
532
- $user = $this->context->user;
533
- if ($user === null) {
534
- if (!session_id()) {
535
- return array();
536
- }
537
- $user = array(
538
- 'id' => session_id(),
539
- );
540
- if (!empty($_SESSION)) {
541
- $user['data'] = $_SESSION;
542
- }
543
- }
544
- return array(
545
- 'user' => $user,
546
- );
547
- }
548
-
549
- protected function get_extra_data()
550
- {
551
- return $this->extra_data;
552
- }
553
-
554
- public function get_default_data()
555
- {
556
- return array(
557
- 'server_name' => $this->name,
558
- 'project' => $this->project,
559
- 'site' => $this->site,
560
- 'logger' => $this->logger,
561
- 'tags' => $this->tags,
562
- 'platform' => 'php',
563
- 'sdk' => $this->sdk,
564
- );
565
- }
566
-
567
- public function capture($data, $stack = null, $vars = null)
568
- {
569
- if (!isset($data['timestamp'])) {
570
- $data['timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
571
- }
572
- if (!isset($data['level'])) {
573
- $data['level'] = self::ERROR;
574
- }
575
- if (!isset($data['tags'])) {
576
- $data['tags'] = array();
577
- }
578
- if (!isset($data['extra'])) {
579
- $data['extra'] = array();
580
- }
581
- if (!isset($data['event_id'])) {
582
- $data['event_id'] = $this->uuid4();
583
- }
584
-
585
- if (isset($data['message'])) {
586
- $data['message'] = substr($data['message'], 0, $this->message_limit);
587
- }
588
-
589
- $data = array_merge($this->get_default_data(), $data);
590
-
591
- if ($this->is_http_request()) {
592
- $data = array_merge($this->get_http_data(), $data);
593
- }
594
-
595
- $data = array_merge($this->get_user_data(), $data);
596
-
597
- if ($this->release) {
598
- $data['release'] = $this->release;
599
- }
600
- if ($this->environment) {
601
- $data['environment'] = $this->environment;
602
- }
603
-
604
- $data['tags'] = array_merge(
605
- $this->tags,
606
- $this->context->tags,
607
- $data['tags']);
608
-
609
- $data['extra'] = array_merge(
610
- $this->get_extra_data(),
611
- $this->context->extra,
612
- $data['extra']);
613
-
614
- if (empty($data['extra'])) {
615
- unset($data['extra']);
616
- }
617
- if (empty($data['tags'])) {
618
- unset($data['tags']);
619
- }
620
- if (empty($data['user'])) {
621
- unset($data['user']);
622
- }
623
- if (empty($data['request'])) {
624
- unset($data['request']);
625
- }
626
-
627
- if (!$this->breadcrumbs->is_empty()) {
628
- $data['breadcrumbs'] = $this->breadcrumbs->fetch();
629
- }
630
-
631
- if ((!$stack && $this->auto_log_stacks) || $stack === true) {
632
- $stack = debug_backtrace();
633
-
634
- // Drop last stack
635
- array_shift($stack);
636
- }
637
-
638
- if (!empty($stack)) {
639
- // manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
640
- if (!class_exists('Raven_Stacktrace')) {
641
- spl_autoload_call('Raven_Stacktrace');
642
- }
643
-
644
- if (!isset($data['stacktrace']) && !isset($data['exception'])) {
645
- $data['stacktrace'] = array(
646
- 'frames' => Raven_Stacktrace::get_stack_info(
647
- $stack, $this->trace, $this->shift_vars, $vars, $this->message_limit, $this->prefixes,
648
- $this->app_path, $this->serializer, $this->reprSerializer
649
- ),
650
- );
651
- }
652
- }
653
-
654
- $this->sanitize($data);
655
- $this->process($data);
656
-
657
- if (!$this->store_errors_for_bulk_send) {
658
- $this->send($data);
659
- } else {
660
- $this->_pending_events[] = $data;
661
- }
662
-
663
- $this->_last_event_id = $data['event_id'];
664
-
665
- return $data['event_id'];
666
- }
667
-
668
- public function sanitize(&$data)
669
- {
670
- // attempt to sanitize any user provided data
671
- if (!empty($data['request'])) {
672
- $data['request'] = $this->serializer->serialize($data['request']);
673
- }
674
- if (!empty($data['user'])) {
675
- $data['user'] = $this->serializer->serialize($data['user']);
676
- }
677
- if (!empty($data['extra'])) {
678
- $data['extra'] = $this->serializer->serialize($data['extra']);
679
- }
680
- if (!empty($data['tags'])) {
681
- $data['tags'] = $this->serializer->serialize($data['tags']);
682
- }
683
- if (!empty($data['stacktrace']) && !empty($data['stacktrace']['frames'])) {
684
- $data['stacktrace']['frames'] = $this->serializer->serialize($data['stacktrace']['frames']);
685
- }
686
- }
687
-
688
- /**
689
- * Process data through all defined Raven_Processor sub-classes
690
- *
691
- * @param array $data Associative array of data to log
692
- */
693
- public function process(&$data)
694
- {
695
- foreach ($this->processors as $processor) {
696
- $processor->process($data);
697
- }
698
- }
699
-
700
- public function sendUnsentErrors()
701
- {
702
- foreach ($this->_pending_events as $data) {
703
- $this->send($data);
704
- }
705
- $this->_pending_events = array();
706
- if ($this->store_errors_for_bulk_send) {
707
- //in case an error occurs after this is called, on shutdown, send any new errors.
708
- $this->store_errors_for_bulk_send = !defined('RAVEN_CLIENT_END_REACHED');
709
- }
710
- }
711
-
712
- public function encode(&$data)
713
- {
714
- $message = Raven_Compat::json_encode($data);
715
- if ($message === false) {
716
- if (function_exists('json_last_error_msg')) {
717
- $this->_lasterror = json_last_error_msg();
718
- } else {
719
- $this->_lasterror = json_last_error();
720
- }
721
- return false;
722
- }
723
-
724
- if (function_exists("gzcompress")) {
725
- $message = gzcompress($message);
726
- }
727
-
728
- // PHP's builtin curl_* function are happy without this, but the exec method requires it
729
- $message = base64_encode($message);
730
-
731
- return $message;
732
- }
733
-
734
- /**
735
- * Wrapper to handle encoding and sending data to the Sentry API server.
736
- *
737
- * @param array $data Associative array of data to log
738
- */
739
- public function send(&$data)
740
- {
741
- if (is_callable($this->send_callback) && call_user_func_array($this->send_callback, array(&$data)) === false) {
742
- // if send_callback returns false, end native send
743
- return;
744
- }
745
-
746
- if (!$this->server) {
747
- return;
748
- }
749
-
750
- if ($this->transport) {
751
- return call_user_func($this->transport, $this, $data);
752
- }
753
-
754
- $message = $this->encode($data);
755
-
756
- $headers = array(
757
- 'User-Agent' => $this->getUserAgent(),
758
- 'X-Sentry-Auth' => $this->getAuthHeader(),
759
- 'Content-Type' => 'application/octet-stream'
760
- );
761
-
762
- $this->send_remote($this->server, $message, $headers);
763
- }
764
-
765
- /**
766
- * Send data to Sentry
767
- *
768
- * @param string $url Full URL to Sentry
769
- * @param array $data Associative array of data to log
770
- * @param array $headers Associative array of headers
771
- */
772
- private function send_remote($url, $data, $headers=array())
773
- {
774
- $parts = parse_url($url);
775
- $parts['netloc'] = $parts['host'].(isset($parts['port']) ? ':'.$parts['port'] : null);
776
- $this->send_http($url, $data, $headers);
777
- }
778
-
779
- protected function get_default_ca_cert()
780
- {
781
- return dirname(__FILE__) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cacert.pem';
782
- }
783
-
784
- protected function get_curl_options()
785
- {
786
- $options = array(
787
- CURLOPT_VERBOSE => false,
788
- CURLOPT_SSL_VERIFYHOST => 2,
789
- CURLOPT_SSL_VERIFYPEER => $this->verify_ssl,
790
- CURLOPT_CAINFO => $this->ca_cert,
791
- CURLOPT_USERAGENT => 'sentry-php/' . self::VERSION,
792
- );
793
- if ($this->http_proxy) {
794
- $options[CURLOPT_PROXY] = $this->http_proxy;
795
- }
796
- if ($this->curl_ssl_version) {
797
- $options[CURLOPT_SSLVERSION] = $this->curl_ssl_version;
798
- }
799
- if ($this->curl_ipv4) {
800
- $options[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
801
- }
802
- if (defined('CURLOPT_TIMEOUT_MS')) {
803
- // MS is available in curl >= 7.16.2
804
- $timeout = max(1, ceil(1000 * $this->timeout));
805
-
806
- // some versions of PHP 5.3 don't have this defined correctly
807
- if (!defined('CURLOPT_CONNECTTIMEOUT_MS')) {
808
- //see http://stackoverflow.com/questions/9062798/php-curl-timeout-is-not-working/9063006#9063006
809
- define('CURLOPT_CONNECTTIMEOUT_MS', 156);
810
- }
811
-
812
- $options[CURLOPT_CONNECTTIMEOUT_MS] = $timeout;
813
- $options[CURLOPT_TIMEOUT_MS] = $timeout;
814
- } else {
815
- // fall back to the lower-precision timeout.
816
- $timeout = max(1, ceil($this->timeout));
817
- $options[CURLOPT_CONNECTTIMEOUT] = $timeout;
818
- $options[CURLOPT_TIMEOUT] = $timeout;
819
- }
820
- return $options;
821
- }
822
-
823
- /**
824
- * Send the message over http to the sentry url given
825
- *
826
- * @param string $url URL of the Sentry instance to log to
827
- * @param array $data Associative array of data to log
828
- * @param array $headers Associative array of headers
829
- */
830
- private function send_http($url, $data, $headers=array())
831
- {
832
- if ($this->curl_method == 'async') {
833
- $this->_curl_handler->enqueue($url, $data, $headers);
834
- } elseif ($this->curl_method == 'exec') {
835
- $this->send_http_asynchronous_curl_exec($url, $data, $headers);
836
- } else {
837
- $this->send_http_synchronous($url, $data, $headers);
838
- }
839
- }
840
-
841
- /**
842
- * Send the cURL to Sentry asynchronously. No errors will be returned from cURL
843
- *
844
- * @param string $url URL of the Sentry instance to log to
845
- * @param array $data Associative array of data to log
846
- * @param array $headers Associative array of headers
847
- * @return bool
848
- */
849
- private function send_http_asynchronous_curl_exec($url, $data, $headers)
850
- {
851
- // TODO(dcramer): support ca_cert
852
- $cmd = $this->curl_path.' -X POST ';
853
- foreach ($headers as $key => $value) {
854
- $cmd .= '-H \''. $key. ': '. $value. '\' ';
855
- }
856
- $cmd .= '-d \''. $data .'\' ';
857
- $cmd .= '\''. $url .'\' ';
858
- $cmd .= '-m 5 '; // 5 second timeout for the whole process (connect + send)
859
- if (!$this->verify_ssl) {
860
- $cmd .= '-k ';
861
- }
862
- $cmd .= '> /dev/null 2>&1 &'; // ensure exec returns immediately while curl runs in the background
863
-
864
- exec($cmd);
865
-
866
- return true; // The exec method is just fire and forget, so just assume it always works
867
- }
868
-
869
- /**
870
- * Send a blocking cURL to Sentry and check for errors from cURL
871
- *
872
- * @param string $url URL of the Sentry instance to log to
873
- * @param array $data Associative array of data to log
874
- * @param array $headers Associative array of headers
875
- * @return bool
876
- */
877
- private function send_http_synchronous($url, $data, $headers)
878
- {
879
- $new_headers = array();
880
- foreach ($headers as $key => $value) {
881
- array_push($new_headers, $key .': '. $value);
882
- }
883
- // XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
884
- $new_headers[] = 'Expect:';
885
-
886
- $curl = curl_init($url);
887
- curl_setopt($curl, CURLOPT_POST, 1);
888
- curl_setopt($curl, CURLOPT_HTTPHEADER, $new_headers);
889
- curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
890
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
891
-
892
- $options = $this->get_curl_options();
893
- $ca_cert = $options[CURLOPT_CAINFO];
894
- unset($options[CURLOPT_CAINFO]);
895
- curl_setopt_array($curl, $options);
896
-
897
- curl_exec($curl);
898
-
899
- $errno = curl_errno($curl);
900
- // CURLE_SSL_CACERT || CURLE_SSL_CACERT_BADFILE
901
- if ($errno == 60 || $errno == 77) {
902
- curl_setopt($curl, CURLOPT_CAINFO, $ca_cert);
903
- curl_exec($curl);
904
- }
905
-
906
- $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
907
- $success = ($code == 200);
908
- if (!$success) {
909
- // It'd be nice just to raise an exception here, but it's not very PHP-like
910
- $this->_lasterror = curl_error($curl);
911
- } else {
912
- $this->_lasterror = null;
913
- }
914
- curl_close($curl);
915
-
916
- return $success;
917
- }
918
-
919
- /**
920
- * Generate a Sentry authorization header string
921
- *
922
- * @param string $timestamp Timestamp when the event occurred
923
- * @param string $client HTTP client name (not Raven_Client object)
924
- * @param string $api_key Sentry API key
925
- * @param string $secret_key Sentry API key
926
- * @return string
927
- */
928
- protected function get_auth_header($timestamp, $client, $api_key, $secret_key)
929
- {
930
- $header = array(
931
- sprintf('sentry_timestamp=%F', $timestamp),
932
- "sentry_client={$client}",
933
- sprintf('sentry_version=%s', self::PROTOCOL),
934
- );
935
-
936
- if ($api_key) {
937
- $header[] = "sentry_key={$api_key}";
938
- }
939
-
940
- if ($secret_key) {
941
- $header[] = "sentry_secret={$secret_key}";
942
- }
943
-
944
-
945
- return sprintf('Sentry %s', implode(', ', $header));
946
- }
947
-
948
- public function getAuthHeader()
949
- {
950
- $timestamp = microtime(true);
951
- return $this->get_auth_header($timestamp, $this->getUserAgent(), $this->public_key, $this->secret_key);
952
- }
953
-
954
- /**
955
- * Generate an uuid4 value
956
- *
957
- * @return string
958
- */
959
- private function uuid4()
960
- {
961
- $uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
962
- // 32 bits for "time_low"
963
- mt_rand(0, 0xffff), mt_rand(0, 0xffff),
964
-
965
- // 16 bits for "time_mid"
966
- mt_rand(0, 0xffff),
967
-
968
- // 16 bits for "time_hi_and_version",
969
- // four most significant bits holds version number 4
970
- mt_rand(0, 0x0fff) | 0x4000,
971
-
972
- // 16 bits, 8 bits for "clk_seq_hi_res",
973
- // 8 bits for "clk_seq_low",
974
- // two most significant bits holds zero and one for variant DCE1.1
975
- mt_rand(0, 0x3fff) | 0x8000,
976
-
977
- // 48 bits for "node"
978
- mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
979
- );
980
-
981
- return str_replace('-', '', $uuid);
982
- }
983
-
984
- /**
985
- * Return the URL for the current request
986
- *
987
- * @return string|null
988
- */
989
- protected function get_current_url()
990
- {
991
- // When running from commandline the REQUEST_URI is missing.
992
- if (!isset($_SERVER['REQUEST_URI'])) {
993
- return null;
994
- }
995
-
996
- // HTTP_HOST is a client-supplied header that is optional in HTTP 1.0
997
- $host = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
998
- : (!empty($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR']
999
- : (!empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '')));
1000
-
1001
- $httpS = $this->isHttps() ? 's' : '';
1002
- return "http{$httpS}://{$host}{$_SERVER['REQUEST_URI']}";
1003
- }
1004
-
1005
- /**
1006
- * Was the current request made over https?
1007
- *
1008
- * @return bool
1009
- */
1010
- protected function isHttps()
1011
- {
1012
- if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
1013
- return true;
1014
- }
1015
-
1016
- if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
1017
- return true;
1018
- }
1019
-
1020
- if (!empty($this->trust_x_forwarded_proto) &&
1021
- !empty($_SERVER['X-FORWARDED-PROTO']) &&
1022
- $_SERVER['X-FORWARDED-PROTO'] === 'https') {
1023
- return true;
1024
- }
1025
-
1026
- return false;
1027
- }
1028
-
1029
- /**
1030
- * Get the value of a key from $_SERVER
1031
- *
1032
- * @param string $key Key whose value you wish to obtain
1033
- * @return string Key's value
1034
- */
1035
- private function _server_variable($key)
1036
- {
1037
- if (isset($_SERVER[$key])) {
1038
- return $_SERVER[$key];
1039
- }
1040
-
1041
- return '';
1042
- }
1043
-
1044
- /**
1045
- * Translate a PHP Error constant into a Sentry log level group
1046
- *
1047
- * @param string $severity PHP E_$x error constant
1048
- * @return string Sentry log level group
1049
- */
1050
- public function translateSeverity($severity)
1051
- {
1052
- if (is_array($this->severity_map) && isset($this->severity_map[$severity])) {
1053
- return $this->severity_map[$severity];
1054
- }
1055
- switch ($severity) {
1056
- case E_ERROR: return Raven_Client::ERROR;
1057
- case E_WARNING: return Raven_Client::WARN;
1058
- case E_PARSE: return Raven_Client::ERROR;
1059
- case E_NOTICE: return Raven_Client::INFO;
1060
- case E_CORE_ERROR: return Raven_Client::ERROR;
1061
- case E_CORE_WARNING: return Raven_Client::WARN;
1062
- case E_COMPILE_ERROR: return Raven_Client::ERROR;
1063
- case E_COMPILE_WARNING: return Raven_Client::WARN;
1064
- case E_USER_ERROR: return Raven_Client::ERROR;
1065
- case E_USER_WARNING: return Raven_Client::WARN;
1066
- case E_USER_NOTICE: return Raven_Client::INFO;
1067
- case E_STRICT: return Raven_Client::INFO;
1068
- case E_RECOVERABLE_ERROR: return Raven_Client::ERROR;
1069
- }
1070
- if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
1071
- switch ($severity) {
1072
- case E_DEPRECATED: return Raven_Client::WARN;
1073
- case E_USER_DEPRECATED: return Raven_Client::WARN;
1074
- }
1075
- }
1076
- return Raven_Client::ERROR;
1077
- }
1078
-
1079
- /**
1080
- * Provide a map of PHP Error constants to Sentry logging groups to use instead
1081
- * of the defaults in translateSeverity()
1082
- *
1083
- * @param array $map
1084
- */
1085
- public function registerSeverityMap($map)
1086
- {
1087
- $this->severity_map = $map;
1088
- }
1089
-
1090
- /**
1091
- * Convenience function for setting a user's ID and Email
1092
- *
1093
- * @deprecated
1094
- * @param string $id User's ID
1095
- * @param string|null $email User's email
1096
- * @param array $data Additional user data
1097
- */
1098
- public function set_user_data($id, $email=null, $data=array())
1099
- {
1100
- $user = array('id' => $id);
1101
- if (isset($email)) {
1102
- $user['email'] = $email;
1103
- }
1104
- $this->user_context(array_merge($user, $data));
1105
- }
1106
-
1107
- public function onShutdown()
1108
- {
1109
- if (!defined('RAVEN_CLIENT_END_REACHED')) {
1110
- define('RAVEN_CLIENT_END_REACHED', true);
1111
- }
1112
- $this->sendUnsentErrors();
1113
- if ($this->curl_method == 'async') {
1114
- $this->_curl_handler->join();
1115
- }
1116
- }
1117
-
1118
- /**
1119
- * Sets user context.
1120
- *
1121
- * @param array $data Associative array of user data
1122
- */
1123
- public function user_context($data)
1124
- {
1125
- $this->context->user = $data;
1126
- }
1127
-
1128
- /**
1129
- * Appends tags context.
1130
- *
1131
- * @param array $data Associative array of tags
1132
- */
1133
- public function tags_context($data)
1134
- {
1135
- $this->context->tags = array_merge($this->context->tags, $data);
1136
- }
1137
-
1138
- /**
1139
- * Appends additional context.
1140
- *
1141
- * @param array $data Associative array of extra data
1142
- */
1143
- public function extra_context($data)
1144
- {
1145
- $this->context->extra = array_merge($this->context->extra, $data);
1146
- }
1147
-
1148
- /**
1149
- * @param array $processors
1150
- */
1151
- public function setProcessors(array $processors)
1152
- {
1153
- $this->processors = $processors;
1154
- }
1155
- }
lib/Raven/Compat.php DELETED
@@ -1,135 +0,0 @@
1
- <?php
2
-
3
- /*
4
- * This file is part of Raven.
5
- *
6
- * (c) Sentry Team
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
-
12
- class Raven_Compat
13
- {
14
- public static function gethostname()
15
- {
16
- if (function_exists('gethostname')) {
17
- return gethostname();
18
- }
19
-
20
- return self::_gethostname();
21
- }
22
-
23
- public static function _gethostname()
24
- {
25
- return php_uname('n');
26
- }
27
-
28
- public static function hash_hmac($algo, $data, $key, $raw_output=false)
29
- {
30
- if (function_exists('hash_hmac')) {
31
- return hash_hmac($algo, $data, $key, $raw_output);
32
- }
33
-
34
- return self::_hash_hmac($algo, $data, $key, $raw_output);
35
- }
36
-
37
- /**
38
- * Implementation from 'KC Cloyd'.
39
- * See http://nl2.php.net/manual/en/function.hash-hmac.php
40
- */
41
- public static function _hash_hmac($algo, $data, $key, $raw_output=false)
42
- {
43
- $algo = strtolower($algo);
44
- $pack = 'H'.strlen($algo('test'));
45
- $size = 64;
46
- $opad = str_repeat(chr(0x5C), $size);
47
- $ipad = str_repeat(chr(0x36), $size);
48
-
49
- if (strlen($key) > $size) {
50
- $key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
51
- } else {
52
- $key = str_pad($key, $size, chr(0x00));
53
- }
54
-
55
- $keyLastPos = strlen($key) - 1;
56
- for ($i = 0; $i < $keyLastPos; $i++) {
57
- $opad[$i] = $opad[$i] ^ $key[$i];
58
- $ipad[$i] = $ipad[$i] ^ $key[$i];
59
- }
60
-
61
- $output = $algo($opad.pack($pack, $algo($ipad.$data)));
62
-
63
- return ($raw_output) ? pack($pack, $output) : $output;
64
- }
65
-
66
- /**
67
- * Note that we discard the options given to be compatible
68
- * with PHP < 5.3
69
- */
70
- public static function json_encode($value, $options=0)
71
- {
72
- if (function_exists('json_encode')) {
73
- return json_encode($value);
74
- }
75
-
76
- return self::_json_encode($value);
77
- }
78
-
79
- /**
80
- * Implementation taken from
81
- * http://www.mike-griffiths.co.uk/php-json_encode-alternative/
82
- */
83
- public static function _json_encode($value)
84
- {
85
- static $jsonReplaces = array(
86
- array('\\', '/', "\n", "\t", "\r", "\b", "\f", '"'),
87
- array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
88
-
89
- if (is_null($value)) {
90
- return 'null';
91
- }
92
- if ($value === false) {
93
- return 'false';
94
- }
95
- if ($value === true) {
96
- return 'true';
97
- }
98
-
99
- if (is_scalar($value)) {
100
-
101
- // Always use '.' for floats.
102
- if (is_float($value)) {
103
- return floatval(str_replace(',', '.', strval($value)));
104
- }
105
- if (is_string($value)) {
106
- return sprintf('"%s"',
107
- str_replace($jsonReplaces[0], $jsonReplaces[1], $value));
108
- } else {
109
- return $value;
110
- }
111
- }
112
-
113
- $isList = true;
114
- for ($i = 0, reset($value); $i<count($value); $i++, next($value)) {
115
- if (key($value) !== $i) {
116
- $isList = false;
117
- break;
118
- }
119
- }
120
- $result = array();
121
- if ($isList) {
122
- foreach ($value as $v) {
123
- $result[] = self::_json_encode($v);
124
- }
125
-
126
- return '[' . join(',', $result) . ']';
127
- } else {
128
- foreach ($value as $k => $v) {
129
- $result[] = self::_json_encode($k) . ':' . self::_json_encode($v);
130
- }
131
-
132
- return '{' . join(',', $result) . '}';
133
- }
134
- }
135
- }
lib/Raven/Context.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
- /**
3