├── History.md ├── Install.md ├── Readme.md ├── app ├── code │ └── community │ │ └── Segment │ │ └── Analytics │ │ ├── Block │ │ ├── Json.php │ │ └── Template.php │ │ ├── Helper │ │ └── Data.php │ │ ├── Model │ │ ├── Controller │ │ │ ├── Addedtowishlist.php │ │ │ ├── Addtocart.php │ │ │ ├── Alias.php │ │ │ ├── Amlistfav.php │ │ │ ├── Base.php │ │ │ ├── Customerloggedin.php │ │ │ ├── Customerloggedout.php │ │ │ ├── Customerregistered.php │ │ │ ├── Filteredproducts.php │ │ │ ├── Identity.php │ │ │ ├── Init.php │ │ │ ├── Layerednavfilter.php │ │ │ ├── Orderplaced.php │ │ │ ├── Page.php │ │ │ ├── Removefromcart.php │ │ │ ├── Reviewedproduct.php │ │ │ ├── Searchedproducts.php │ │ │ ├── Subscribenewsletter.php │ │ │ ├── Viewedproduct.php │ │ │ └── Viewedreviews.php │ │ ├── Front │ │ │ └── Controller.php │ │ ├── Observer.php │ │ ├── Observer │ │ │ ├── Admin.php │ │ │ ├── Layered.php │ │ │ └── Review.php │ │ ├── Query │ │ │ ├── .DS_Store │ │ │ ├── Totalpurchased.php │ │ │ └── Totalspent.php │ │ ├── Resource │ │ │ └── Setup.php │ │ └── Session.php │ │ ├── controllers │ │ └── IndexController.php │ │ ├── etc │ │ ├── adminhtml.xml │ │ ├── config.xml │ │ └── system.xml │ │ └── sql │ │ └── segment_analytics_setup │ │ ├── install-0.0.2.php │ │ └── upgrade-0.0.2-0.0.3.php ├── design │ ├── adminhtml │ │ └── default │ │ │ └── default │ │ │ └── template │ │ │ └── segment_analytics │ │ │ ├── welcome-container.phtml │ │ │ └── welcome.phtml │ └── frontend │ │ └── base │ │ └── default │ │ └── template │ │ └── segment_analytics │ │ ├── addedtowishlist.phtml │ │ ├── addtocart.phtml │ │ ├── alias.phtml │ │ ├── amlistfav.phtml │ │ ├── customerloggedin.phtml │ │ ├── customerloggedout.phtml │ │ ├── customerregistered.phtml │ │ ├── filteredproducts.phtml │ │ ├── identity.phtml │ │ ├── image-frontend.phtml │ │ ├── init.phtml │ │ ├── layerednavfilter.phtml │ │ ├── orderplaced.phtml │ │ ├── page.phtml │ │ ├── removefromcart.phtml │ │ ├── review-frontend.phtml │ │ ├── reviewedproduct.phtml │ │ ├── searchedproducts.phtml │ │ ├── share-frontend.phtml │ │ ├── subscribenewsletter.phtml │ │ ├── viewedproduct.phtml │ │ └── viewedreviews.phtml └── etc │ └── modules │ └── Segment_Analytics.xml ├── bin └── build ├── dist ├── analytics-2.0.1.tgz ├── analytics-latest.tgz └── var │ └── connect │ └── analytics.xml └── support ├── MagentoTarToConnect ├── README.md ├── _cli_stub.php ├── build.xml ├── example-config.php ├── magento-tar-to-connect.php └── vendor │ └── magento │ └── downloader │ └── lib │ └── Mage │ ├── Archive │ ├── Abstract.php │ ├── Helper │ │ └── File.php │ ├── Interface.php │ └── Tar.php │ └── Exception.php └── config.php /History.md: -------------------------------------------------------------------------------- 1 | 2.0.1 / 2015-09-17 2 | ================== 3 | * Identified and fixed bug affecting added/removed product behavior 4 | 5 | 2.0.0 / 2015-09-01 6 | ================== 7 | 8 | * The identify logic was filtering the userId from its usable data before it could render it into the `userId` field of its call. This meant that we weren't reliably rendering the userId in the one identify call we were firing on registration. That's been **fixed.** 9 | * `Added Product` and `Removed Product` only used to pass SKU; now they pass the full product info dictionary 10 | * Call identify on every page when the user is logged in, not just on registration 11 | * Allow store owner to optionally flush a.js `user()` object with [`analytics.reset()`](https://segment.com/docs/libraries/analytics.js/#reset-logout) after customers log out (defaults to false) 12 | * Allow store owner to optionally pass product properties which they'd like to **omit** from their product info dictionary (the same one used to populate `Completed Order`, `Viewed Product`, `Added Product`, and `Removed Product` properties). This allows them to deny fields from being rendered in analytics calls. 13 | * Strips all `null` K/V pairs from product properties by default. 14 | * Customer log out used to trigger two `Logged Out` events due to a redundant logout mechanism that would attempt to grab the customers id to use post-logout. That mechanism has been removed. If a user opts not to flush (# 4 above), then analytics.js will handle caching and use of the resilient `userId`. If they do flush, then they will deliberately not have that id after logout. 15 | 16 | 1.1.0 / 2015-08-20 17 | ================== 18 | 19 | * fix duplicate category bug 20 | * remove debug logging 21 | * add intro text 22 | * adding functionality to record discounts and revenue 23 | * removing code that accidentally overwrites casting of Magento product info into Segment API friendly product info 24 | 25 | 1.0.0 - August 23, 2014 26 | ----------------------- 27 | * first stable release 28 | 29 | 0.0.1 - July 14, 2014 30 | --------------------- 31 | * initial release 32 | -------------------------------------------------------------------------------- /Install.md: -------------------------------------------------------------------------------- 1 | Installing Extension 2 | -------------------------------------------------- 3 | 4 | Analytics for Magento is distributed as a Magento Connect `tgz` file. This means there's three ways to install it. 5 | 6 | - Directly via a Magento Connect extension key **NOTE**: Link to Connect page when it's setup. 7 | 8 | - By uploading the `tgz` extension via the Magento Connect Manager 9 | 10 | - By copying the extension source manually to your Magento system. 11 | 12 | ## Magento Connect Key Instructions 13 | 14 | - Log into to your Magento Connect Account 15 | 16 | - Browse to the Analytics for Magento page on Magento Connect (**NOTE**: Link to page when ready) 17 | 18 | - Click the Install Now button 19 | 20 | - Copy the Extension Key 21 | 22 | - Log into your Magento Admin console 23 | 24 | - Browse to `System -> Magento Connect -> Magento Connect Manager` 25 | 26 | - Re-enter your credentials 27 | 28 | - Paste the extension key from above into the field labeled *Paste Extension Key to Install* 29 | 30 | - Click the install button 31 | 32 | - Magento Connect will install the package into your system 33 | 34 | ## Uploading the Extension 35 | 36 | - Download the extension from the [releases page](https://github.com/segmentio/analytics-magento/releases) 37 | 38 | - Log into your Magento Admin console 39 | 40 | - Browse to `System -> Magento Connect -> Magento Connect Manager` 41 | 42 | - Re-enter your credentials 43 | 44 | - Click the Choose File button 45 | 46 | - Select the downloaded `tgz` extension from your file system 47 | 48 | - Click Upload 49 | 50 | - Click Install Now 51 | 52 | - Magento Connect will install the package into your system 53 | 54 | ## Copying Extension Source 55 | 56 | - Ensure your Magento Cache is off, and that Magento is not running in compilation mode 57 | 58 | - Copy the contents of the extension's `app` folder to your server. Be sure you're uploading the contents of the folder, and not replacing your entire system's app folder 59 | 60 | - With the Magento cache off or cleared, browse to `System -> Configuration -> Advanced` and ensure the `Segment_Analytics` extension is installed 61 | 62 | - If you're using the Magento class compiler, recompile your classes 63 | 64 | - If you're using the Magento cache, reenable it 65 | 66 | ## Post Installation Steps 67 | 68 | After installing the extension, you may enter your Segment key at 69 | 70 | System -> Configuration -> Analytics 71 | 72 | If this page returns a 404 (common during a manual install) logout and log back in to clear your cached Magento session. -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Analytics for Magento 3 | 4 | > **NOTE**: Official support from Segment for this plugin is **deprecated**. We are currently looking for community maintainers. The current version of this plugin should be free of bugs but any existing and future development will be paused for the time being. We recommend exploring and using third party alternatives. **Specifically, the folks at Windsor Circle are maintaining an [active fork of the plugin](https://github.com/windsor-circle/analytics-magento) driving towards support for Magento 2.** If you have any questions, please send us an email at friends@segment.com! 5 | 6 | **Analytics for Magento** is a Magento extension for [Segment](https://segment.com) that lets you send data to any analytics tool you want without writing any code yourself! 7 | 8 | - [Installing](#installing) 9 | - [Support](#support) 10 | - [Developing](#developing) 11 | - [Deploying](#deploying) 12 | 13 | 14 | ## Installing 15 | 16 | To get up and running, check out our documentation at [DEPRECATED] [https://segment.com/docs/plugins/magento](https://segment.com/docs/plugins/magento). Installation takes less than five minutes! 17 | 18 | 19 | ## Support 20 | 21 | If you run into issues, be sure to check out the [documentation](https://segment.com/docs/plugins/magento), and you can always reach out to our [support team](https://segment.com/support) for help! 22 | 23 | 24 | ## Developing 25 | 26 | _Note: this section only applies if you are interested in contributing improvements to our Magento extension's source code. You don't need to read this to use the extension in your own store._ 27 | 28 | TODO: We don't yet have detailed instructions for installing a local development version of Magento. 29 | 30 | 31 | ## Deploying 32 | 33 | _Note: this section only applies to Segment teammates, and details how we deploy new versions of the extension to the Magento Connect marketplace for end users of the extension to download._ 34 | 35 | Before deploying, make sure to pull in the latest changes from the remote repository: 36 | 37 | $ git pull origin master 38 | 39 | The first step after making your changes to the extension source is to tag a new release of the extension. To do that, first bump the version number in [`app/etc/modules/Segment_Analytics.xml`](app/code/community/Segment/Analytics/etc/config.xml). 40 | 41 | Then, update [`History.md`](History.md) with a summary of your changes. 42 | 43 | Once you've bumped the version and updated the changelog, you need to rebuild the distribution files in [`dist/`](dist/) by running the build script: 44 | 45 | $ bin/build 46 | 47 | Then commit those changes, and tag the release (where `X.X.X` is the number of the newest version): 48 | 49 | $ git commit -am 'X.X.X' 50 | $ git tag 'X.X.X' 51 | $ git push origin master 52 | $ git push origin X.X.X 53 | 54 | Once you've done that, you'll need to log into our [Magento Connect]() account, and navigate to **Your Account > Developers > Manage Extensions** and click the **Edit** button on the **Analytics for Magento** extension. That will take you to the extension editing page. From there, click the **Versions** tab and then the **Add new version** button. 55 | 56 | Fill out the form for adding a new version, supplying the `X.X.X` version number as the **Release Notes Title** as well, and the list from [`History.md`](History.md) as the **Release Notes**. For the **Versions** check `1.7` and above. Then click the **Continue to upload** button. 57 | 58 | On the upload form page click **Choose File** and find the `analytics-magento-X.X.X` file on your computer from the [`dist/`](dist) directory, then hit **Upload and save**. 59 | 60 | And you're finally done! 61 | 62 | 63 | ## Resources 64 | 65 | - [Analytics for Magento Listing](http://www.magentocommerce.com/magento-connect/extension-171.html) - Our extension's listing on Magento Connect. 66 | - [Magento Tar to Connect](http://alanstorm.com/magento_connect_from_tar) - The script we use to build Magento Connect compatible files. 67 | - [Magento Extension Design Guidelines](http://info.magento.com/rs/magentocommerce/images/0448_Connect_DevStyleguide_v6.pdf?mkt_tok=3RkMMJWWfF9wsRokvK7BZKXonjHpfsX94%2B0oWKSg38431UFwdcjKPmjr1YEGTcZ0dvycMRAVFZl5nQFZHeWbaI9D9fhQDlOxXQ%3D%3D) - Guidelines for extensions to adhere to. 68 | 69 | 70 | ## License 71 | 72 | Copyright © 2014 Segment <friends@segment.com> 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 75 | 76 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 77 | 78 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 79 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Block/Json.php: -------------------------------------------------------------------------------- 1 | getVarName(); 7 | $json = $this->toJsonString(); 8 | 9 | if($this->getAsRawObject()) 10 | { 11 | return $json; 12 | } 13 | 14 | return ''; 17 | } 18 | 19 | public function toJsonString($data=false) 20 | { 21 | $data = $data ? $data : $this->getDataWithoutExtras(); 22 | $json = Mage::helper("core")->jsonEncode($data); 23 | $json = preg_replace('%[\r\n]%','',$json); 24 | return $json; 25 | } 26 | 27 | public function getDataWithoutExtras() 28 | { 29 | $data = $this->getData(); 30 | unset($data['type']); 31 | unset($data['module_name']); 32 | unset($data['var_name']); 33 | unset($data['as_raw_object']); 34 | return $data; 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Block/Template.php: -------------------------------------------------------------------------------- 1 | getLayout()->createBlock('segment_analytics/json') 7 | ->setData($this->getData()) 8 | ->setVarName($var_name) 9 | ->toHtml(); 10 | } 11 | 12 | public function renderDataAsJsonObject($key=false) 13 | { 14 | $data = $key ? $this->getData($key) : $this->getData(); 15 | return $this->getLayout()->createBlock('segment_analytics/json') 16 | ->setData($data) 17 | ->setAsRawObject(true) 18 | ->toHtml(); 19 | } 20 | 21 | public function getContextJson() 22 | { 23 | $renderer = $this->getLayout()->createBlock('segment_analytics/json') 24 | ->setData(array( 25 | 'library'=> array( 26 | 'name'=>'analytics-magento', 27 | 'version'=>(string) Mage::getConfig()->getNode()->modules->Segment_Analytics->version 28 | ))); 29 | return $renderer->toJsonString(); 30 | } 31 | 32 | /** 33 | * Ensure safe JSON string, even for Magento systems still 34 | * running on PHP 5.2 35 | */ 36 | public function getPropertyAsJavascriptString($prop) 37 | { 38 | $data = (string) $this->getData($prop); 39 | if ($prop == 'user_id' && empty($data)) { 40 | $customer = Mage::getSingleton('customer/session')->getCustomer(); 41 | $data = (string) $customer->getId(); 42 | } 43 | $data = json_encode($data); 44 | $data = preg_replace('%[^ $:"\'a-z>0-9_-]%six','',$data); 45 | return $data; 46 | } 47 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Helper/Data.php: -------------------------------------------------------------------------------- 1 | getStore()->isAdmin(); 17 | } 18 | 19 | public function isEnabled() 20 | { 21 | return !$this->isAdmin() && $this->getWriteKey(); 22 | } 23 | 24 | public function getCategoryNamesFromIds($ids) 25 | { 26 | $ids = is_array($ids) ? $ids : array($ids); 27 | $categories = Mage::getModel('catalog/category')->getCollection() 28 | ->addAttributeToSelect('name') 29 | ->addFieldToFilter('entity_id', array('in'=>$ids)); 30 | 31 | $names = array(); 32 | foreach($categories as $category) 33 | { 34 | $names[] = $category->getName(); 35 | } 36 | return $names; 37 | } 38 | 39 | /** 40 | * Changes standard page titles per segment API. Hopefully 41 | * this is kept to a minimum 42 | * @todo refactor if this goes beyond page 43 | */ 44 | public function getNormalizedPageTitle($title) 45 | { 46 | if(strpos($title, $this->__('Search results for')) !== false) 47 | { 48 | $title = 'Search Results'; 49 | } 50 | 51 | return $title; 52 | } 53 | 54 | public function getNormalizedCustomerInformation($data) 55 | { 56 | $swap = array( 57 | 'firstname'=>'first_name', 58 | 'lastname'=>'last_name'); 59 | 60 | //nomalize items from $swap 61 | foreach($swap as $old=>$new) 62 | { 63 | if(!array_key_exists($old, $data)) 64 | { 65 | continue; 66 | } 67 | $data[$new] = $data[$old]; 68 | unset($data[$old]); 69 | } 70 | 71 | //normalize dates 72 | $data = $this->_normalizeDatesToISO8601($data); 73 | 74 | //only 75 | $fields = trim(Mage::getStoreConfig('segment_analytics/options/customer_traits')); 76 | $to_send = preg_split('%[\n\r]%', $fields, -1, PREG_SPLIT_NO_EMPTY); 77 | 78 | $data_final = array(); 79 | foreach($to_send as $field) 80 | { 81 | $data_final[$field] = array_key_exists($field, $data) ? $data[$field] : null; 82 | } 83 | 84 | $data_final = $this->getDataCastAsBooleans($data_final); 85 | 86 | return $data_final; 87 | 88 | } 89 | 90 | public function getNormalizedProductInformation($product) 91 | { 92 | // If passed object, convert to array 93 | if (is_object($product)) { 94 | $product = $product->getData(); 95 | } 96 | 97 | //if passed id, load the product 98 | if(!is_array($product)) 99 | { 100 | $product = Mage::getModel('catalog/product_api')->info($product); 101 | } 102 | 103 | //calculate revenue, if present 104 | $product['id'] = $product['product_id']; 105 | if(array_key_exists('cost',$product)) 106 | { 107 | $product['revenue'] = $product['price'] - $product['cost']; 108 | } 109 | 110 | //ensure category names/labels are sent along 111 | $categories = Mage::getModel('catalog/category')->getCollection() 112 | ->addAttributeToSelect('name') 113 | ->addFieldToFilter('entity_id', array('in'=>$product['category_ids'])); 114 | foreach($categories as $category) 115 | { 116 | $product['categories'][] = $category->getName(); 117 | } 118 | 119 | //cast numerics as floats per segment requirements 120 | $as_float = array('price','weight'); 121 | foreach($as_float as $key) 122 | { 123 | if(!array_key_exists($key, $product)) { continue; } 124 | $product[$key] = (float) $product[$key]; 125 | } 126 | 127 | //segments wants "id" not product_id 128 | if(array_key_exists('product_id', $product)) 129 | { 130 | $product['id'] = $product['product_id']; 131 | unset($product['product_id']); 132 | } 133 | 134 | $denylist = trim(Mage::getStoreConfig('segment_analytics/options/product_properties')); 135 | $deniedFields = preg_split('%[\n\r]%', $denylist, -1, PREG_SPLIT_NO_EMPTY); 136 | 137 | foreach($deniedFields as $key) 138 | { 139 | if(!array_key_exists($key, $product)) { continue; } 140 | unset($product[$key]); 141 | } 142 | 143 | $product = $this->getDataCastAsBooleans($product); 144 | $product = array_filter($product, function($v, $k) { 145 | return !is_null($v); 146 | }); 147 | return $this->_normalizeDatesToISO8601($product); 148 | } 149 | 150 | /** 151 | * Central place for casting of '1' and '0' as boolean 152 | * where we know it needs to happen. Segment API requirement 153 | */ 154 | public function getDataCastAsBooleans($data) 155 | { 156 | $keys_boolean = array('has_options','is_active','customer_is_guest','customer_note_notify', 157 | 'email_sent','forced_shipment_with_invoice','paypal_ipn_customer_notified','is_virtual', 158 | 'is_qty_decimal', 'no_discount','is_nominal'); 159 | foreach($keys_boolean as $key) 160 | { 161 | if(!array_key_exists($key, $data)) { continue; } 162 | $data[$key] = (boolean) $data[$key]; 163 | } 164 | return $this->_normalizeDatesToISO8601($data); 165 | } 166 | 167 | protected function _normalizeDatesToISO8601($data) 168 | { 169 | $date_fields = array('created_at', 'updated_at'); 170 | foreach($date_fields as $key) 171 | { 172 | if(!array_key_exists($key, $data)) 173 | { 174 | continue; 175 | } 176 | $data[$key] = date(DATE_ISO8601,strToTime($data[$key])); 177 | } 178 | return $data; 179 | } 180 | 181 | public function normalizeReviewwData($data) 182 | { 183 | return $this->_normalizeDatesToISO8601($data); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Addedtowishlist.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | $info = Mage::getModel('catalog/product_api') 8 | ->info($params['product_id']); 9 | 10 | $info = Mage::helper('segment_analytics') 11 | ->getNormalizedProductInformation($info); 12 | 13 | $want = array('sku', 'price', 'name'); 14 | foreach($info as $key=>$value) 15 | { 16 | if(!in_array($key, $want)){continue;} 17 | $params[$key] = $value; 18 | } 19 | 20 | $block->setParams($params); 21 | return $block; 22 | } 23 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Addtocart.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | $product = Mage::getModel('catalog/product_api') 8 | ->info($params['product_id']); 9 | 10 | $product = Mage::helper('segment_analytics') 11 | ->getNormalizedProductInformation($product); 12 | 13 | $block->setProduct($product); 14 | 15 | return $block; 16 | } 17 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Alias.php: -------------------------------------------------------------------------------- 1 | _getCustomerSession(); 7 | if($customer->getCustomer()->getData('is_segment_aliased')) 8 | { 9 | return false; 10 | } 11 | $customer->getCustomer()->setData('is_segment_aliased','1')->save(); 12 | $block->setUserId($customer->getId()); 13 | return $block; 14 | } 15 | 16 | 17 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Amlistfav.php: -------------------------------------------------------------------------------- 1 | info($block->getProductId()); 7 | $info = Mage::helper('segment_analytics') 8 | ->getNormalizedProductInformation($info); 9 | $block->setParams($info); 10 | return $block; 11 | } 12 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Base.php: -------------------------------------------------------------------------------- 1 | _getDefaultBlock(); 11 | return $this->getBlock($block); 12 | } 13 | 14 | protected function _getDefaultBlock() 15 | { 16 | $key = Mage::helper('segment_analytics')->getWriteKey(); 17 | $block = $this->getLayout()->createBlock('segment_analytics/template') 18 | ->setTemplate('segment_analytics/'.$this->getName().'.phtml') 19 | ->setKey($key); 20 | if(is_array($this->getData())) 21 | { 22 | $block->addData($this->getData()); 23 | } 24 | return $block; 25 | } 26 | 27 | public function setData($value) 28 | { 29 | $this->_data = $value; 30 | return $this; 31 | } 32 | 33 | public function getData() 34 | { 35 | return $this->_data; 36 | } 37 | 38 | public function setName($value) 39 | { 40 | $this->_name = $value; 41 | return $this; 42 | } 43 | 44 | public function getName() 45 | { 46 | return $this->_name; 47 | } 48 | 49 | public function getLayout() 50 | { 51 | return Mage::getSingleton('core/layout'); 52 | } 53 | 54 | public function getFullActionName($delimiter='_') 55 | { 56 | return $this->getRequest()->getRequestedRouteName().$delimiter. 57 | $this->getRequest()->getRequestedControllerName().$delimiter. 58 | $this->getRequest()->getRequestedActionName(); 59 | } 60 | 61 | public function getRequest() 62 | { 63 | return Mage::app()->getRequest(); 64 | } 65 | 66 | 67 | protected function _getCustomerSession() 68 | { 69 | return Mage::getSingleton('customer/session'); 70 | } 71 | 72 | protected function _getCustomer() 73 | { 74 | $customer = Mage::getSingleton('customer/session')->getCustomer(); 75 | 76 | //pull entire customer, including eav attributes not initially populated 77 | $full_customer = Mage::getModel('customer/customer')->getCollection() 78 | ->addAttributeToSelect('*')->addFieldToFilter('entity_id', $customer->getId()) 79 | ->getFirstItem(); 80 | return $full_customer; 81 | } 82 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Customerloggedin.php: -------------------------------------------------------------------------------- 1 | _getCustomer(); 7 | $block->setUserId($customer->getId()); 8 | 9 | $data = $block->getData(); 10 | $data = Mage::helper('segment_analytics')->getNormalizedCustomerInformation($data); 11 | $block->setData($data); 12 | 13 | return $block; 14 | } 15 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Customerloggedout.php: -------------------------------------------------------------------------------- 1 | getCustomer(); 7 | foreach(array('password_hash') as $key) 8 | { 9 | if(!array_key_exists($key, $customer)) { continue; } 10 | unset($customer[$key]); 11 | } 12 | $customer = Mage::helper('segment_analytics')->getNormalizedCustomerInformation($customer); 13 | $block->setUserId($customer['entity_id']); 14 | return $block; 15 | } 16 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Customerregistered.php: -------------------------------------------------------------------------------- 1 | getData(); 7 | $data = Mage::helper('segment_analytics')->getNormalizedCustomerInformation($data); 8 | $block->setData($data); 9 | return $block; 10 | } 11 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Filteredproducts.php: -------------------------------------------------------------------------------- 1 | _getCustomer(); 7 | 8 | if(!$customer->getId()) 9 | { 10 | return false; 11 | } 12 | 13 | $gender_label = $customer->getResource() 14 | ->getAttribute('gender') 15 | ->getSource() 16 | ->getOptionText($customer->getData('gender')); 17 | 18 | $address = Mage::getModel('customer/address')->load( 19 | $customer->getDefaultBilling() 20 | ); 21 | 22 | $block->setUserId($customer->getId()) 23 | ->addData($customer->getData()) 24 | ->setFullName($customer->getName()) 25 | ->setName($customer->getName()) 26 | ->setEmail($customer->getEmail()) 27 | ->setGroupId($customer->getGroupId()) 28 | ->setTaxClassId($customer->getTaxClassId()) 29 | ->setSharedStoreIds((array)$customer->getSharedStoreIds()) 30 | ->setSharedWebsiteIds((array)$customer->getSharedWebsiteIds()) 31 | ->setGender($gender_label) 32 | ->setFirstName($customer->getFirstname()) 33 | ->setLastName($customer->getLastname()) 34 | ->setMiddleName($customer->getMiddlename()) 35 | ->setTotalOrders( 36 | Mage::getSingleton('segment_analytics/query_totalpurchased') 37 | ->fetchTotalOrders($customer->getId()) 38 | ) 39 | ->setTotalSpent( 40 | Mage::getSingleton('segment_analytics/query_totalspent') 41 | ->fetchTotalSpent($customer->getId()) 42 | ) 43 | ->unsetData('password_hash') 44 | ->unsetData('firstname') 45 | ->unsetData('lastname') 46 | ->unsetData('middlename'); 47 | 48 | if($address) 49 | { 50 | $region = Mage::getModel('directory/region')->load($address->getRegionId()); 51 | $street = $address->getStreet(); 52 | $street = implode("\n", $street); 53 | $block 54 | ->setData('city', $address->getCity()) 55 | ->setData('country', $address->getCountryId()) 56 | ->setData('postalCode', $address->getPostcode()) 57 | ->setData('state', $region->getCode()) 58 | ->setData('street', $street); 59 | } 60 | $data = $block->getData(); 61 | $data = Mage::helper('segment_analytics')->getNormalizedCustomerInformation($data); 62 | $block->setData($data); 63 | return $block; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Init.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | 8 | $params['category'] = Mage::helper('segment_analytics') 9 | ->getCategoryNamesFromIds($params['request']['id']); 10 | $block->setParams($params); 11 | 12 | return $block; 13 | } 14 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Orderplaced.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | 8 | $info = Mage::getModel('sales/order_api') 9 | ->info($params['increment_id']); 10 | 11 | $params['total'] = (float) $info['grand_total']; 12 | $params['revenue'] = (float) $info['subtotal']; 13 | $params['status'] = $info['status']; 14 | $params['shipping'] = (float) $info['shipping_amount']; 15 | $params['tax'] = (float) $info['tax_amount']; 16 | $params['discount'] = (-1 * (float) $info['discount_amount']); 17 | $params['products'] = array(); 18 | foreach($info['items'] as $item) 19 | { 20 | $tmp = array(); 21 | $tmp['sku'] = $item['sku']; 22 | $tmp['name'] = $item['name']; 23 | $tmp['price'] = (float) $item['price']; 24 | $tmp['quantity'] = (float) $item['qty_ordered']; 25 | $tmp['product_id'] = (int) $item['product_id']; 26 | 27 | $params['products'][] = $tmp; 28 | } 29 | 30 | 31 | //the serialized information 32 | $block->setParams($params); 33 | 34 | return $block; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Page.php: -------------------------------------------------------------------------------- 1 | _getCategoryNames(); 7 | $product = $this->_getCurrentProduct(); 8 | if($names) 9 | { 10 | $block->setCategoryNames($names) 11 | ->setPageTitle('Category Listing') 12 | ->setFullCategoryName(implode(' -> ',$names)); 13 | return $block; 14 | } 15 | 16 | if($product) 17 | { 18 | $block->setPageName('Product'); 19 | return $block; 20 | } 21 | 22 | $title = Mage::getSingleton('core/layout')->getBlock('head')->getTitle(); 23 | $title = Mage::helper('segment_analytics')->getNormalizedPageTitle($title); 24 | 25 | $block->setPageName($title); 26 | 27 | return $block; 28 | } 29 | 30 | protected function _getCurrentProduct() 31 | { 32 | return Mage::registry('product'); 33 | } 34 | 35 | protected function _getCategoryPageHandles() 36 | { 37 | return array('catalog_category_view'); 38 | } 39 | 40 | protected function _getCategoryNames() 41 | { 42 | 43 | if(!in_array($this->getFullActionName(), $this->_getCategoryPageHandles())) 44 | { 45 | return; 46 | } 47 | 48 | $current_category = Mage::registry('current_category'); 49 | $category = $current_category; 50 | if(!$current_category) 51 | { 52 | return; 53 | } 54 | $ids = array($category->getId()); 55 | $categories = array($category); 56 | while($parent_id = $category->getParentId()) 57 | { 58 | $ids[] = $parent_id; 59 | $category = Mage::getModel('catalog/category')->load($parent_id); 60 | $categories[] = $category; 61 | } 62 | //pop off root 63 | array_pop($categories); 64 | $names = array(); 65 | foreach($categories as $category) 66 | { 67 | $names[] = $category->getName(); 68 | } 69 | $names = array_reverse($names); 70 | return $names; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Removefromcart.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | $product = Mage::getModel('catalog/product_api') 8 | ->info($params['product_id']); 9 | 10 | $product = Mage::helper('segment_analytics') 11 | ->getNormalizedProductInformation($product); 12 | 13 | $block->setProduct($product); 14 | 15 | return $block; 16 | } 17 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Reviewedproduct.php: -------------------------------------------------------------------------------- 1 | getReview(); 7 | unset($review['customer_id']); 8 | unset($review['form_key']); 9 | $review = Mage::helper('segment_analytics')->normalizeReviewwData($review); 10 | $block->setReview($review); 11 | return $block; 12 | } 13 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Searchedproducts.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | // $product = Mage::getModel('catalog/product_api')->info($params['id']); 8 | 9 | $product = Mage::helper('segment_analytics') 10 | ->getNormalizedProductInformation($params['id']); 11 | 12 | $block->setParams($product); 13 | return $block; 14 | } 15 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Controller/Viewedreviews.php: -------------------------------------------------------------------------------- 1 | getParams(); 7 | 8 | $info = Mage::getModel('catalog/product_api') 9 | ->info($params['id']); 10 | 11 | $info = Mage::helper('segment_analytics') 12 | ->getNormalizedProductInformation($info); 13 | 14 | $want = array('sku', 'price', 'name'); 15 | foreach($info as $key=>$value) 16 | { 17 | if(!in_array($key, $want)){continue;} 18 | $params[$key] = $value; 19 | } 20 | 21 | $block->setParams($params); 22 | return $block; 23 | } 24 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Front/Controller.php: -------------------------------------------------------------------------------- 1 | action = $action; 27 | $o_action->data = $action_data; 28 | 29 | $session = $this->_getSession(); 30 | $deferred = $session->getDeferredActions(); 31 | $deferred = $deferred ? $deferred : array(); 32 | $deferred[] = $o_action; 33 | $session->setDeferredActions($deferred); 34 | 35 | return $this; 36 | } 37 | 38 | public function clearDeferredActions() 39 | { 40 | Mage::getSingleton('segment_analytics/session') 41 | ->setDeferredActions(array()) 42 | ->setDeferredActionsData(array()); 43 | #Mage::Log("Cleared Deferred Action"); 44 | return $this; 45 | } 46 | 47 | public function getDeferredActions() 48 | { 49 | $actions = Mage::getSingleton('segment_analytics/session') 50 | ->getDeferredActions(); 51 | $actions = $actions ? $actions : array(); 52 | return $actions; 53 | } 54 | 55 | protected function _getSession() 56 | { 57 | return Mage::getSingleton('segment_analytics/session'); 58 | } 59 | 60 | public function addAction($action,$data=array()) 61 | { 62 | $this->_actions[] = $action; 63 | $this->_actionsData[$action] = $data; 64 | return $this; 65 | } 66 | 67 | public function getBlocks() 68 | { 69 | $blocks[] = array(); 70 | foreach($this->_actions as $action) 71 | { 72 | $class = 'Segment_Analytics_Model_Controller_' . ucwords($action); 73 | $controller = new $class; 74 | $controller->setName($action) 75 | ->setData($this->_actionsData[$action]); 76 | $blocks[$action][] = $controller->dispatch(); 77 | } 78 | 79 | foreach($this->getDeferredActions() as $action) 80 | { 81 | $class = 'Segment_Analytics_Model_Controller_' . ucwords($action->action); 82 | $controller = new $class; 83 | $controller->setName($action->action) 84 | ->setData($action->data); 85 | $blocks[$action->action][] = $controller->dispatch(); 86 | } 87 | 88 | //reorder based on sort priority, filter out !blocks 89 | $blocks_ordered = array(); 90 | $sort_order = $this->getSortOrder(); 91 | $orders = array_keys($sort_order); 92 | sort($orders); 93 | foreach($orders as $order) 94 | { 95 | $action = $sort_order[$order]; 96 | if(!array_key_exists($action, $blocks)) { continue; } 97 | $blocks_ordered[$action] = $blocks[$action]; 98 | unset($blocks[$action]); 99 | } 100 | 101 | //now any blocks not included in the sort order 102 | foreach($blocks as $block) 103 | { 104 | $blocks_ordered[] = $block; 105 | } 106 | $this->clearDeferredActions(); 107 | 108 | //flatten array 109 | $final = array(); 110 | foreach($blocks_ordered as $array) 111 | { 112 | foreach($array as $block) 113 | { 114 | $final[] = $block; 115 | } 116 | 117 | } 118 | return $final; 119 | } 120 | 121 | protected function getSortOrder() 122 | { 123 | return array( 124 | 10=>'init', 125 | 30=>'alias', 126 | 20=>'page', 127 | 40=>'identity', 128 | ); 129 | } 130 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Observer.php: -------------------------------------------------------------------------------- 1 | getBlock('before_body_end'); 18 | if(!$before_body_end) 19 | { 20 | Mage::Log("No before body end in " . __METHOD__); 21 | return; 22 | } 23 | 24 | if(!Mage::helper('segment_analytics')->isEnabled()) 25 | { 26 | return; 27 | } 28 | 29 | $container = $layout->createBlock('core/text_list', self::CONTAINER_BLOCKNAME); 30 | $before_body_end->append($container); 31 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 32 | $blocks = $front->getBlocks(); 33 | 34 | foreach($blocks as $block) 35 | { 36 | if(!$block) { continue; } 37 | $items = $block = is_array($block) ? $block : array($block); 38 | 39 | foreach($items as $block) 40 | { 41 | $container->append($block); 42 | } 43 | } 44 | #Mage::Log("Finished addContainerBlocks"); 45 | } 46 | 47 | /** 48 | * Adds the "always" items 49 | */ 50 | public function addFrotnendScripts($observer) 51 | { 52 | $layout = $observer->getLayout(); 53 | if(!$layout) 54 | { 55 | return; 56 | } 57 | if(!Mage::helper('segment_analytics')->isEnabled()) 58 | { 59 | return; 60 | } 61 | 62 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 63 | $front->addAction('init'); 64 | $front->addDeferredAction('identity'); 65 | $front->addAction('page'); 66 | } 67 | 68 | public function loggedIn($observer) 69 | { 70 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 71 | $front->addDeferredAction('alias'); 72 | $front->addDeferredAction('identity'); 73 | $front->addDeferredAction('customerloggedin'); 74 | } 75 | 76 | public function loggedOut($observer) 77 | { 78 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 79 | $front->addDeferredAction('customerloggedout', array( 80 | 'customer'=>$this->_getCustomerData() 81 | )); 82 | } 83 | 84 | public function addToCart($observer) 85 | { 86 | $product = $observer->getProduct(); 87 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 88 | $front->addDeferredAction('addtocart', 89 | array('params'=>array('product_id'=>$product->getId())) 90 | ); 91 | } 92 | 93 | public function removeFromCart($observer) 94 | { 95 | $product = $observer->getQuoteItem()->getProduct(); 96 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 97 | $front->addDeferredAction('removefromcart', 98 | array('params'=>array('product_id'=>$product->getId())) 99 | ); 100 | } 101 | 102 | public function customerRegistered($observer) 103 | { 104 | $customer = $observer->getCustomer(); 105 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 106 | $front->addDeferredAction('customerregistered', 107 | array('customer_id'=>$customer->getEntityId()) 108 | ); 109 | } 110 | 111 | public function loadedSearch($observer) 112 | { 113 | $o = $observer->getDataObject(); 114 | if(!$o){return;} 115 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 116 | $front->addDeferredAction('searchedproducts', 117 | array('query'=>$o->getQueryText()) 118 | ); 119 | } 120 | 121 | public function categoryViewForFiltering($observer) 122 | { 123 | $action = $observer->getAction(); 124 | if(!$action){ return; } 125 | 126 | $request = $action->getRequest(); 127 | if(!$request) { return; } 128 | 129 | $params = $request->getParams(); 130 | 131 | //use presense of "dir" to flag for filtering. 132 | //no need for an action handle check 133 | if(!array_key_exists('dir', $params)) 134 | { 135 | return; 136 | } 137 | 138 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 139 | $front->addDeferredAction('filteredproducts', 140 | array('params'=>$params) 141 | ); 142 | 143 | } 144 | 145 | public function productView($observer) 146 | { 147 | $action = $observer->getAction(); 148 | if(!$action){ return; } 149 | 150 | $request = $action->getRequest(); 151 | if(!$request) { return; } 152 | 153 | $params = $request->getParams(); 154 | 155 | if (!in_array($action->getFullActionName(), array('catalog_product_view'))) 156 | { 157 | return; 158 | } 159 | 160 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 161 | $front->addDeferredAction('viewedproduct', 162 | array('params'=>$params) 163 | ); 164 | } 165 | 166 | public function favSaved($observer) 167 | { 168 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 169 | $item = $observer->getData('data_object'); 170 | 171 | if($item->getResourceName() == 'amlist/item') 172 | { 173 | $front->addDeferredAction('amlistfav', 174 | array('product_id'=>$item->getData('product_id')) 175 | ); 176 | } 177 | } 178 | 179 | public function reviewView($observer) 180 | { 181 | $action = $observer->getAction(); 182 | if(!$action){ return; } 183 | 184 | $request = $action->getRequest(); 185 | if(!$request) { return; } 186 | 187 | $params = $request->getParams(); 188 | 189 | if (!in_array($action->getFullActionName(), array('review_product_list'))) 190 | { 191 | return; 192 | } 193 | 194 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 195 | $front->addDeferredAction('viewedreviews', 196 | array('params'=>$params) 197 | ); 198 | 199 | } 200 | 201 | public function newsletterSubscriber($observer) 202 | { 203 | $subscriber = $observer->getDataObject(); 204 | if(!$subscriber->getSubscriberStatus()) 205 | { 206 | return; 207 | } 208 | 209 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 210 | $front->addDeferredAction('subscribenewsletter', 211 | array('subscriber'=>$subscriber->getData()) 212 | ); 213 | } 214 | 215 | public function wishlistAddProduct($observer) 216 | { 217 | $product = $observer->getProduct(); 218 | $wishlist = $observer->getWishlist(); 219 | 220 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 221 | $front->addDeferredAction('addedtowishlist', 222 | array('params'=>array('product_id'=>$product->getId())) 223 | ); 224 | 225 | } 226 | 227 | public function viewedImageFrontendTrack($observer) 228 | { 229 | if(!Mage::helper('segment_analytics')->isEnabled()) 230 | { 231 | return; 232 | } 233 | 234 | $action = $observer->getAction(); 235 | if(!$action){ return; } 236 | 237 | $layout = Mage::getSingleton('core/layout'); 238 | 239 | $content = $layout->getBlock('content'); 240 | if(!$content) { return; } 241 | 242 | $content->append( 243 | $layout->createBlock('segment_analytics/template') 244 | ->setTemplate('segment_analytics/image-frontend.phtml') 245 | ); 246 | } 247 | 248 | public function orderPlaced($observer) 249 | { 250 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 251 | $front->addDeferredAction('orderplaced', 252 | array('params'=>array( 253 | 'order_id'=>$observer->getOrder()->getId(), 254 | 'increment_id'=>$observer->getOrder()->getIncrementId(), 255 | )) 256 | ); 257 | } 258 | 259 | public function logBlockHtml($observer) 260 | { 261 | if($observer->getBlock()->getNameInLayout() != self::CONTAINER_BLOCKNAME) 262 | { 263 | return; 264 | } 265 | 266 | #Mage::Log($observer->getTransport()->getHtml(), Zend_Log::INFO, 'segment.log'); 267 | } 268 | 269 | public function addClickedShareJavascript($observer) 270 | { 271 | $action = $observer->getAction(); 272 | if(!$action){ return; } 273 | 274 | if($action->getFullActionName() != 'catalog_product_view') 275 | { 276 | return; 277 | } 278 | 279 | $layout = Mage::getSingleton('core/layout'); 280 | 281 | $content = $layout->getBlock('content'); 282 | if(!$content) 283 | { 284 | return; 285 | } 286 | 287 | $block = $layout->createBlock('segment_analytics/template') 288 | ->setTemplate('segment_analytics/share-frontend.phtml'); 289 | 290 | $content->append($block); 291 | } 292 | 293 | public function addClickedReviewTabJavascript($observer) 294 | { 295 | $action = $observer->getAction(); 296 | if(!$action){ return; } 297 | 298 | if($action->getFullActionName() != 'catalog_product_view') 299 | { 300 | return; 301 | } 302 | 303 | $layout = Mage::getSingleton('core/layout'); 304 | 305 | $content = $layout->getBlock('content'); 306 | if(!$content) 307 | { 308 | return; 309 | } 310 | $block = $layout->createBlock('segment_analytics/template') 311 | ->setTemplate('segment_analytics/review-frontend.phtml'); 312 | 313 | $content->append($block); 314 | } 315 | 316 | protected function _getCustomer() 317 | { 318 | $customer = Mage::getSingleton('customer/session')->getCustomer(); 319 | 320 | //pull entire customer, including eav attributes not initially populated 321 | $full_customer = Mage::getModel('customer/customer')->getCollection() 322 | ->addAttributeToSelect('*')->addFieldToFilter('entity_id', $customer->getId()) 323 | ->getFirstItem(); 324 | 325 | return $full_customer; 326 | } 327 | 328 | protected function _getCustomerData() 329 | { 330 | $customer = $this->_getCustomer(); 331 | if($customer) 332 | { 333 | $customer = Mage::helper('segment_analytics')->getNormalizedCustomerInformation($customer->getData()); 334 | return $customer; 335 | } 336 | return array(); 337 | } 338 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Observer/Admin.php: -------------------------------------------------------------------------------- 1 | getAction(); 7 | if(!$action) 8 | { 9 | return; 10 | } 11 | 12 | if($action->getRequest()->getParam('section') !== 'segment_analytics') 13 | { 14 | return; 15 | } 16 | 17 | $layout = Mage::getSingleton('core/layout'); 18 | $content = $layout->getBlock('content'); 19 | 20 | if(!$content) 21 | { 22 | return; 23 | } 24 | 25 | $json = new stdClass; 26 | $json->content = $layout->createBlock('adminhtml/template') 27 | ->setTemplate('segment_analytics/welcome.phtml') 28 | ->toHtml(); 29 | } 30 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Observer/Layered.php: -------------------------------------------------------------------------------- 1 | getAction(); 15 | if(!$action){ return; } 16 | 17 | if (!in_array($action->getFullActionName(), array('catalog_category_view'))) 18 | { 19 | return; 20 | } 21 | 22 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 23 | $front->addDeferredAction('layerednavfilter', 24 | array('params'=>array('request'=>Mage::app()->getRequest()->getParams())) 25 | ); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Observer/Review.php: -------------------------------------------------------------------------------- 1 | getObject(); 8 | } 9 | 10 | public function reviewedProduct($observer) 11 | { 12 | $review = self::$_review; 13 | if(!$review->getId()) 14 | { 15 | return; 16 | } 17 | 18 | $front = Segment_Analytics_Model_Front_Controller::getInstance(); 19 | $front->addDeferredAction('reviewedproduct', 20 | array('review'=>$review->getData()) 21 | ); 22 | } 23 | 24 | 25 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Query/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segment-boneyard/analytics-magento/HEAD/app/code/community/Segment/Analytics/Model/Query/.DS_Store -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Query/Totalpurchased.php: -------------------------------------------------------------------------------- 1 | getConnection('core_read'); 8 | $sql = 'SELECT count(customer_id) as total FROM ' . $core_resource->getTableName('sales/order') . ' ' . 9 | 'WHERE customer_id = ?'; 10 | $query = $read->query($sql,$customer_id); 11 | 12 | $result = $query->execute(); 13 | $row = $query->fetch(); 14 | 15 | return array_key_exists('total', $row) ? $row['total'] : 0; 16 | } 17 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Query/Totalspent.php: -------------------------------------------------------------------------------- 1 | getConnection('core_read'); 8 | $sql = 'SELECT sum(grand_total) as total FROM ' . $core_resource->getTableName('sales/order') . ' ' . 9 | 'WHERE customer_id = ?'; 10 | $query = $read->query($sql,$customer_id); 11 | $result = $query->execute(); 12 | $row = $query->fetch(); 13 | 14 | return array_key_exists('total', $row) ? $row['total'] : 0; 15 | 16 | } 17 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/Model/Resource/Setup.php: -------------------------------------------------------------------------------- 1 | init('segment_analytics'); 11 | } 12 | } -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/controllers/IndexController.php: -------------------------------------------------------------------------------- 1 | loadLayout(); 6 | $this->renderLayout(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/etc/adminhtml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Segment Options 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 2.0.1 6 | 7 | 8 | 9 | 10 | 11 | standard 12 | 13 | Segment_Analytics 14 | segment_analytics 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Segment_Analytics 24 | Segment_Analytics_Model_Resource_Setup 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | singleton 34 | segment_analytics/observer 35 | addFrotnendScripts 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | singleton 44 | segment_analytics/observer 45 | loggedIn 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | singleton 54 | segment_analytics/observer 55 | loggedOut 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | singleton 64 | segment_analytics/observer 65 | addToCart 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | singleton 74 | segment_analytics/observer 75 | removeFromCart 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | singleton 84 | segment_analytics/observer 85 | addContainerBlock 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | singleton 94 | segment_analytics/observer 95 | loadedSearch 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | singleton 104 | segment_analytics/observer 105 | customerRegistered 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | singleton 114 | segment_analytics/observer 115 | addClickedShareJavascript 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | singleton 124 | segment_analytics/observer 125 | addClickedReviewTabJavascript 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | singleton 134 | segment_analytics/observer 135 | viewedImageFrontendTrack 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | singleton 144 | segment_analytics/observer 145 | categoryViewForFiltering 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | singleton 154 | segment_analytics/observer_admin 155 | addExplainationTextToConfigScreen 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | singleton 164 | segment_analytics/observer_layered 165 | flagIsFiltered 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | singleton 174 | segment_analytics/observer 175 | productGalleryViewed 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | singleton 185 | segment_analytics/observer_layered 186 | addLayeredLimitation 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | singleton 195 | segment_analytics/observer 196 | reviewView 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | singleton 205 | segment_analytics/observer 206 | productView 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | singleton 215 | segment_analytics/observer 216 | favSaved 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | singleton 225 | segment_analytics/observer_review 226 | markReviewSaved 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | singleton 235 | segment_analytics/observer_review 236 | reviewedProduct 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | singleton 245 | segment_analytics/observer 246 | newsletterSubscriber 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | singleton 255 | segment_analytics/observer 256 | wishlistAddProduct 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | singleton 265 | segment_analytics/observer 266 | orderPlaced 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | singleton 275 | segment_analytics/observer 276 | logBlockHtml 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | Segment_Analytics_Block 286 | 287 | 288 | 289 | 290 | Segment_Analytics_Model 291 | 292 | 293 | 294 | 295 | Segment_Analytics_Helper 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | created_at 305 | user_id 306 | email 307 | first_name 308 | last_name 309 | middle_name 310 | name 311 | is_active 312 | updated_at 313 | total_orders 314 | total_spent 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 0 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/etc/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | general 6 | text 7 | 101 8 | 1 9 | 1 10 | 1 11 | 12 | 13 | 14 | text 15 | 9999 16 | 1 17 | 1 18 | 1 19 | 20 | 21 | 22 | 23 | Your Unique Segment Write Key 24 | text 25 | 26 | 27 | 10 28 | 1 29 | 1 30 | 1 31 | 32 | 33 | 34 | Flushing will ensure you don't misattribute events to a logged-out user. You may opt not to flush if you want to continue tracking users by ID after they logout. Click here for more info. 35 | select 36 | adminhtml/system_config_source_yesno 37 | 15 38 | 1 39 | 1 40 | 1 41 | 42 | 43 | 44 | Which Magento Customer Data Fields to Send 45 | textarea 46 | 20 47 | 1 48 | 1 49 | 1 50 | 51 | 52 | 53 | Which Magento Product Data Fields would you like to deny from properties of your calls? 54 | textarea 55 | 30 56 | 1 57 | 1 58 | 1 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/sql/segment_analytics_setup/install-0.0.2.php: -------------------------------------------------------------------------------- 1 | startSetup(); 3 | $entity = $this->getEntityTypeId('customer'); 4 | 5 | /* create the new attribute */ 6 | $this->addAttribute($entity, 'is_segment_aliased', array( 7 | 'type' => 'text', /* input type */ 8 | 'label' => 'Segment Aliased', /* Label for the user to read */ 9 | 'input' => 'text', /* input type */ 10 | 'visible' => FALSE, /* users can see it */ 11 | 'required' => FALSE, /* is it required, self-explanatory */ 12 | 'default_value' => 'default', /* default value */ 13 | 'adminhtml_only' => '1' /* use in admin html only */ 14 | )); 15 | 16 | /* save the setup */ 17 | $this->endSetup(); -------------------------------------------------------------------------------- /app/code/community/Segment/Analytics/sql/segment_analytics_setup/upgrade-0.0.2-0.0.3.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | segment_analytics 15 | 16 | '; 17 | 18 | if(is_writable(dirname($path_local))) 19 | { 20 | file_put_contents($path_local, $xml); 21 | } -------------------------------------------------------------------------------- /app/design/adminhtml/default/default/template/segment_analytics/welcome-container.phtml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/design/adminhtml/default/default/template/segment_analytics/welcome.phtml: -------------------------------------------------------------------------------- 1 |

Welcome

2 |

3 | Analytics for Magento is a Magento extension for Segment that lets you send data to any analytics tool you want without writing any code yourself! 4 |

-------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/addedtowishlist.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_addedtowishlist");?> 2 | 8 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/addtocart.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_addtocart'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/alias.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_alias'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/amlistfav.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_amlistfav");?> 2 | 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/customerloggedin.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_customerloggedin'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/customerloggedout.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_customerloggedout'); 2 | $flush = Mage::helper('segment_analytics')->flushAfterLogout(); 3 | ?> 4 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/customerregistered.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_customerregistered'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/filteredproducts.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_filtered'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/identity.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_identity'); 3 | 4 | $json_to_send = Mage::helper('core')->jsonDecode($this->renderDataAsJsonObject()); 5 | unset($json_to_send['key']); 6 | unset($json_to_send['user_id']); 7 | 8 | if(array_key_exists('gender', $json_to_send) && $json_to_send['gender'] === false) 9 | { 10 | unset($json_to_send['gender']); 11 | } 12 | $json_to_send = Mage::helper('core')->jsonEncode($json_to_send); 13 | ?> 14 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/image-frontend.phtml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/init.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_init'); ?> 2 | 3 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/layerednavfilter.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_layerednavfilter");?> 2 | 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/orderplaced.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_orderplaced");?> 2 | 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/page.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_page');?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/removefromcart.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_removefromcart'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/review-frontend.phtml: -------------------------------------------------------------------------------- 1 | setReviewLabel(Mage::helper('core')->__('Reviews')) 5 | ->renderDataAsJsonVar('segment_analytics_frontend_review'); 6 | ?> 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/reviewedproduct.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_reviewedproduct");?> 2 | 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/searchedproducts.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar('segment_analytics_searched'); ?> 2 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/share-frontend.phtml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/subscribenewsletter.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_subscribenewsletter");?> 2 | 7 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/viewedproduct.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_viewedproduct"); 4 | ?> 5 | 10 | -------------------------------------------------------------------------------- /app/design/frontend/base/default/template/segment_analytics/viewedreviews.phtml: -------------------------------------------------------------------------------- 1 | renderDataAsJsonVar("segment_analytics_viewedreviews");?> 2 | 7 | -------------------------------------------------------------------------------- /app/etc/modules/Segment_Analytics.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | community 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /bin/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo 3 | 4 | # 5 | # Remove existing files. 6 | # 7 | 8 | echo "Removing exising distribution files..." 9 | rm -rf dist 10 | mkdir dist 11 | 12 | # 13 | # Tar the current extension directory. 14 | # 15 | 16 | echo "Bundling the current extension code..." 17 | tar -cf tmp.tar ./app 18 | 19 | # 20 | # Convert the .tar file to a Magento Connect compatible version. 21 | # 22 | 23 | echo "Rebundling the package in a Magento-compatible format..." 24 | php ./support/MagentoTarToConnect/magento-tar-to-connect.php ./support/config.php 25 | rm tmp.tar 26 | 27 | # 28 | # Duplicate the .tgz file as "latest" for convenient linking. 29 | # 30 | 31 | echo "Creating a '-latest.tgz' distribution file for convenient linking..." 32 | if [[ $(find dist/*.tgz) =~ dist/(.+)-(.+)\.tgz ]] 33 | then 34 | cp $BASH_REMATCH dist/${BASH_REMATCH[1]}-latest.tgz 35 | else 36 | echo "Unable to find a versioned .tgz file to copy." 37 | exit 1 38 | fi 39 | 40 | # 41 | # Done! 42 | # 43 | 44 | echo 45 | echo "Built for Magento Connect!" 46 | echo "The new distribution files are located in ./dist" 47 | echo 48 | exit 0 -------------------------------------------------------------------------------- /dist/analytics-2.0.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segment-boneyard/analytics-magento/HEAD/dist/analytics-2.0.1.tgz -------------------------------------------------------------------------------- /dist/analytics-latest.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segment-boneyard/analytics-magento/HEAD/dist/analytics-latest.tgz -------------------------------------------------------------------------------- /dist/var/connect/analytics.xml: -------------------------------------------------------------------------------- 1 | 2 | <_>55fb4faf7c243<_create>analyticscommunity21Segment lets you integrate 100+ analytics and marketing tools without writing any code yourself!Analytics for Magento is a Magento extension by Segment that lets you integrate any analytics or marketing tool you want with the flick of a switch! No code required. When you turn on the plugin, Segment automatically starts tracking important actions, like when users view items, add products to carts, and complete orders. To send this data along to your preferred tools, just go to the Segment control panel and toggle them on. This will save you months of time installing analytics.MIT2.0.1stableSegmentsegmentiofriends@segment.io5.2.06.0.0magecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagecommunitymagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmagedesignmageetc/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Block/Json.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Block/Template.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/controllers/IndexController.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/etc/adminhtml.xml/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/etc/config.xml/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/etc/system.xml/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Helper/Data.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Observer.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Session.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Addedtowishlist.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Addtocart.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Alias.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Amlistfav.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Base.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Customerloggedin.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Customerloggedout.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Customerregistered.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Filteredproducts.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Identity.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Init.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Layerednavfilter.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Orderplaced.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Page.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Removefromcart.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Reviewedproduct.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Searchedproducts.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Subscribenewsletter.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Viewedproduct.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Controller/Viewedreviews.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Front/Controller.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Observer/Admin.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Observer/Layered.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Observer/Review.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Query/Totalpurchased.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Query/Totalspent.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/Model/Resource/Setup.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/sql/segment_analytics_setup/install-0.0.2.php/private/tmp/tmpf1KLkA/app/code/community/Segment/Analytics/sql/segment_analytics_setup/upgrade-0.0.2-0.0.3.php/private/tmp/tmpf1KLkA/app/design/adminhtml/default/default/template/segment_analytics/welcome-container.phtml/private/tmp/tmpf1KLkA/app/design/adminhtml/default/default/template/segment_analytics/welcome.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/addedtowishlist.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/addtocart.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/alias.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/amlistfav.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/customerloggedin.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/customerloggedout.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/customerregistered.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/filteredproducts.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/identity.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/image-frontend.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/init.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/layerednavfilter.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/orderplaced.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/page.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/removefromcart.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/review-frontend.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/reviewedproduct.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/searchedproducts.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/share-frontend.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/subscribenewsletter.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/viewedproduct.phtml/private/tmp/tmpf1KLkA/app/design/frontend/base/default/template/segment_analytics/viewedreviews.phtml/private/tmp/tmpf1KLkA/app/etc/modules/Segment_Analytics.xmlfilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefilefile 3 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/README.md: -------------------------------------------------------------------------------- 1 | MagentoTarToConnect 2 | =================== 3 | 4 | A small shell script to automatically package tar archives into Magento's Connect 2.0 format. 5 | 6 | ### Description 7 | 8 | Under the hood Magento Connect 2.0 packages are actually tar'ed and gziped files with a specially formatted package manifest. Well, they're almost `tar` and `gzip` files. Magento implemented their own archiving and unarchiving code in PHP, and this code occasionally has problems with tar archives created via standard OS tools. 9 | 10 | This shell script will take a standard tar archive, untar it, build the Connect `package.xml` manifest, and then re-tar and gzip the files **using Magento's code** (included in the `vendor` library here, but you can substitute your own). This decreases the likelihood your package will be incompatible with Magento Connect. 11 | 12 | ## Usage 13 | 14 | The syntax for using this script is as following 15 | 16 | $ ./magento-tar-to-connect.php example-config.php 17 | 18 | Where `example-config.php` is a PHP file which returns a set of configuration key/value pairs. These key/value pairs provide the script with the location of an archive file, the output location, as well as the bare minimum Magento Connect fields needed to create a valid extension. An example file might look something like this 19 | 20 | '/fakehome/Documents/github/Pulsestorm/var/build', 26 | 'archive_files' => 'Pulstorm_Example.tar', 27 | 28 | //The Magento Connect extension name. Must be unique on Magento Connect 29 | //Has no relation to your code module name. Will be the Connect extension name 30 | 'extension_name' => 'Pulstorm_Example', 31 | 32 | //Your extension version. By default, if you're creating an extension from a 33 | //single Magento module, the tar-to-connect script will look to make sure this 34 | //matches the module version. You can skip this check by setting the 35 | //skip_version_compare value to true 36 | 'extension_version' => '1.0.3', 37 | 'skip_version_compare' => false, 38 | 39 | //You can also have the package script use the version in the module you 40 | //are packaging with. 41 | 'auto_detect_version' => false, 42 | 43 | //Where on your local system you'd like to build the files to 44 | 'path_output' => '/fakehome/Pulsestorm/var/build-connect', 45 | 46 | //Magento Connect license value. 47 | 'stability' => 'stable', 48 | 49 | //Magento Connect license value 50 | 'license' => 'MIT', 51 | 52 | //Magento Connect channel value. This should almost always (always?) be community 53 | 'channel' => 'community', 54 | 55 | //Magento Connect information fields. 56 | 'summary' => 'Provides navigation shortcuts for the admin console\'s navigation and global search', 57 | 'description' => 'This extension provides Magento admin console users with an "application launcher". This application launcher provides instant access to the admin console\'s navigation, every system configuration search section, as well as the Magento global search. The Pulse Storm launcher is a free, open source, must have extension for anyone working with Magento. ', 58 | 'notes' => 'Typo fixes, properly aborts ajax requests.', 59 | 60 | //Magento Connect author information. If author_email is foo@example.com, script will 61 | //prompt you for the correct name. Should match your http://www.magentocommerce.com/ 62 | //login email address 63 | 'author_name' => 'Alan Storm', 64 | 'author_user' => 'alanstorm', 65 | 'author_email' => 'foo@example.com', 66 | 67 | //PHP min/max fields for Connect. I don't know if anyone uses these, but you should 68 | //probably check that they're accurate 69 | 'php_min' => '5.2.0', 70 | 'php_max' => '6.0.0' 71 | ); 72 | 73 | ## Building a `phar` with Phing 74 | 75 | The project also includes a `phing` build.xml file. You can use this to create an executable `phar` of the script. If you're not familiar, a `phar` is sort of like a stand alone PHP executable. You can [read more here](http://php.net/phar). 76 | 77 | $ phing create_phar 78 | 79 | 80 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/_cli_stub.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | setPharMode(true); 8 | // $application->run(); 9 | 10 | __HALT_COMPILER(); -------------------------------------------------------------------------------- /support/MagentoTarToConnect/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/example-config.php: -------------------------------------------------------------------------------- 1 | '/fakehome/Documents/github/Pulsestorm/var/build', 7 | 'archive_files' => 'Pulstorm_Example.tar', 8 | 9 | //The Magento Connect extension name. Must be unique on Magento Connect 10 | //Has no relation to your code module name. Will be the Connect extension name 11 | 'extension_name' => 'Pulstorm_Example', 12 | 13 | //Your extension version. By default, if you're creating an extension from a 14 | //single Magento module, the tar-to-connect script will look to make sure this 15 | //matches the module version. You can skip this check by setting the 16 | //skip_version_compare value to true 17 | 'extension_version' => '1.0.3', 18 | 'skip_version_compare' => false, 19 | 20 | //You can also have the package script use the version in the module you 21 | //are packaging with. 22 | 'auto_detect_version' => false, 23 | 24 | //Where on your local system you'd like to build the files to 25 | 'path_output' => '/fakehome/Pulsestorm/var/build-connect', 26 | 27 | //Magento Connect license value. 28 | 'stability' => 'stable', 29 | 30 | //Magento Connect license value 31 | 'license' => 'MIT', 32 | 33 | //Magento Connect channel value. This should almost always (always?) be community 34 | 'channel' => 'community', 35 | 36 | //Magento Connect information fields. 37 | 'summary' => 'Provides navigation shortcuts for the admin console\'s navigation and gloal search', 38 | 'description' => 'This extension provides Magento admin console users with an "application launcher". This application launcher provides instant access to the admin console\'s navigation, every system configuration search section, as well as the Magento global search. The Pulse Storm launcher is a free, open source, must have extension for anyone working with Magento. ', 39 | 'notes' => 'Typo fixes, properly aborts ajax requests.', 40 | 41 | //Magento Connect author information. If author_email is foo@example.com, script will 42 | //prompt you for the correct name. Should match your http://www.magentocommerce.com/ 43 | //login email address 44 | 'author_name' => 'Alan Storm', 45 | 'author_user' => 'alanstorm', 46 | 'author_email' => 'foo@example.com', 47 | 48 | //PHP min/max fields for Connect. I don't know if anyone uses these, but you should 49 | //probably check that they're accurate 50 | 'php_min' => '5.2.0', 51 | 'php_max' => '6.0.0', 52 | 53 | //PHP extension dependencies. An array containing one or more of either: 54 | // - a single string (the name of the extension dependency); use this if the 55 | // extension version does not matter 56 | // - an associative array with 'name', 'min', and 'max' keys which correspond 57 | // to the extension's name and min/max required versions 58 | //Example: 59 | // array('json', array('name' => 'mongo', 'min' => '1.3.0', 'max' => '1.4.0')) 60 | 'extensions' => array() 61 | ); 62 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/magento-tar-to-connect.php: -------------------------------------------------------------------------------- 1 | xpath("dir[@name='".$part."']"); 61 | if(count($nodes) > 0) 62 | { 63 | $node = array_pop($nodes); 64 | } 65 | else 66 | { 67 | $node = $node->addChild('dir'); 68 | $node->addAttribute('name', $part); 69 | } 70 | } 71 | 72 | $node = $node->addChild('file'); 73 | $node->addAttribute('name',$single_file); 74 | $node->addAttribute('hash',md5_file($full_dir)); 75 | } 76 | 77 | function create_package_xml($files, $base_dir, $config) 78 | { 79 | $xml = simplexml_load_string(''); 80 | $xml->name = $config['extension_name']; 81 | $xml->version = $config['extension_version']; 82 | $xml->stability = $config['stability']; 83 | $xml->license = $config['license']; 84 | $xml->channel = $config['channel']; 85 | $xml->extends = ''; 86 | $xml->summary = $config['summary']; 87 | $xml->description = $config['description']; 88 | $xml->notes = $config['notes']; 89 | 90 | $authors = $xml->addChild('authors'); 91 | $author = $authors->addChild('author'); 92 | $author->name = $config['author_name']; 93 | $author->user = $config['author_user']; 94 | $author->email = $config['author_email']; 95 | 96 | $xml->date = date('Y-m-d'); 97 | $xml->time = date('G:i:s'); 98 | $xml->compatible = ''; 99 | $dependencies = $xml->addChild('dependencies'); 100 | $required = $dependencies->addChild('required'); 101 | $php = $required->addChild('php'); 102 | $php->min = $config['php_min']; //'5.2.0'; 103 | $php->max = $config['php_max']; //'6.0.0'; 104 | 105 | // add php extension dependencies 106 | if (is_array($config['extensions'])) { 107 | foreach ($config['extensions'] as $extinfo) { 108 | $extension = $required->addChild('extension'); 109 | if (is_array($extinfo)) { 110 | $extension->name = $extinfo['name']; 111 | $extension->min = isset($extinfo['min']) ? $extinfo['min'] : ""; 112 | $extension->max = isset($extinfo['max']) ? $extinfo['max'] : ""; 113 | } else { 114 | $extension->name = $extinfo; 115 | $extension->min = ""; 116 | $extension->max = ""; 117 | } 118 | } 119 | } 120 | 121 | $node = $xml->addChild('contents'); 122 | $node = $node->addChild('target'); 123 | $node->addAttribute('name', 'mage'); 124 | 125 | // $files = $this->recursiveGlob($temp_dir); 126 | // $files = array_unique($files); 127 | $temp_dir = false; 128 | foreach($files as $file) 129 | { 130 | //$this->addFileNode($node,$temp_dir,$file); 131 | create_package_xml_add_node($node, $file, $base_dir); 132 | } 133 | //file_put_contents($temp_dir . '/package.xml', $xml->asXml()); 134 | 135 | return $xml->asXml(); 136 | } 137 | 138 | function get_temp_dir() 139 | { 140 | $name = tempnam(sys_get_temp_dir(),'tmp'); 141 | unlink($name); 142 | $name = $name; 143 | mkdir($name,0777,true); 144 | return $name; 145 | } 146 | 147 | function validate_config($config) 148 | { 149 | $keys = array('base_dir','archive_files','path_output', 150 | ); 151 | foreach($keys as $key) 152 | { 153 | if(!array_key_exists($key, $config)) 154 | { 155 | error("Config file missing key [$key]"); 156 | } 157 | } 158 | 159 | if($config['author_email'] == 'foo@example.com') 160 | { 161 | $email = input("Email Address is configured with foo@example.com. Enter a new address"); 162 | if(trim($email) != '') 163 | { 164 | $config['author_email'] = trim($email); 165 | } 166 | } 167 | 168 | if(!array_key_exists('extensions', $config)) 169 | { 170 | $config['extensions'] = null; 171 | } 172 | return $config; 173 | 174 | 175 | } 176 | 177 | function load_config($config_name=false) 178 | { 179 | if(!$config_name) 180 | { 181 | $config_name = basename(__FILE__,'php') . 'config.php'; 182 | } 183 | if(!file_exists($config_name)) 184 | { 185 | error("Could not find $config_name. Create this file, or pass in an alternate"); 186 | } 187 | $config = include $config_name; 188 | $config = validate_config($config); 189 | return $config; 190 | } 191 | 192 | function get_module_version($files) 193 | { 194 | $configs = array(); 195 | foreach($files as $file) 196 | { 197 | if(basename($file) == 'config.xml') 198 | { 199 | $configs[] = $file; 200 | } 201 | } 202 | 203 | foreach($configs as $file) 204 | { 205 | $xml = simplexml_load_file($file); 206 | $version_strings = $xml->xpath('//version'); 207 | foreach($version_strings as $version) 208 | { 209 | $version = (string) $version; 210 | if(!empty($version)) 211 | { 212 | return (string)$version; 213 | } 214 | } 215 | } 216 | 217 | foreach($configs as $file) 218 | { 219 | $xml = simplexml_load_file($file); 220 | $modules = $xml->xpath('//modules'); 221 | foreach($modules[0] as $module) 222 | { 223 | $version = (string)$module->version; 224 | if(!empty($version)) 225 | { 226 | return $version; 227 | } 228 | } 229 | } 230 | } 231 | 232 | function check_module_version_vs_package_version($files, $extension_version) 233 | { 234 | $configs = array(); 235 | foreach($files as $file) 236 | { 237 | if(basename($file) == 'config.xml') 238 | { 239 | $configs[] = $file; 240 | } 241 | } 242 | 243 | foreach($configs as $file) 244 | { 245 | $xml = simplexml_load_file($file); 246 | $version_strings = $xml->xpath('//version'); 247 | foreach($version_strings as $version) 248 | { 249 | if($version != $extension_version) 250 | { 251 | error( 252 | "Extension Version [$extension_version] does not match " . 253 | "module version [$version] found in a config.xml file. Add " . 254 | "'skip_version_compare' => true to configuration to skip this check." 255 | ); 256 | } 257 | } 258 | } 259 | } 260 | 261 | function main($argv) 262 | { 263 | $this_script = array_shift($argv); 264 | $config_file = array_shift($argv); 265 | $config = load_config($config_file); 266 | 267 | $base_dir = $config['base_dir']; //'/Users/alanstorm/Documents/github/Pulsestorm/var/build'; 268 | $archive_files = $config['archive_files']; //'Pulsestorm_Modulelist.tar'; 269 | $path_output = $config['path_output']; //'/Users/alanstorm/Desktop/working'; 270 | $archive_connect = $config['extension_name'] . '-' . $config['extension_version'] . '.tgz'; 271 | 272 | $temp_dir = get_temp_dir(); 273 | if($base_dir['0'] !== '/') 274 | { 275 | $base_dir = getcwd() . '/' . $base_dir; 276 | } 277 | chdir($temp_dir); 278 | if(!file_exists($base_dir . '/' . $archive_files)) 279 | { 280 | error('Can\'t find specified archive, bailing' . "\n[" . $base_dir . '/' . $archive_files.']'); 281 | exit; 282 | } 283 | shell_exec('cp ' . $base_dir . '/' . $archive_files . ' ' . $temp_dir); 284 | if(preg_match('/\.zip$/', $archive_files)) { 285 | shell_exec('unzip -o ' . $temp_dir . '/' . $archive_files); 286 | } else { 287 | shell_exec('tar -xf ' . $temp_dir . '/' . $archive_files); 288 | } 289 | shell_exec('rm ' . $temp_dir . '/' . $archive_files); 290 | 291 | $all = glob_recursive($temp_dir . '/*'); 292 | $dirs = glob_recursive($temp_dir .'/*',GLOB_ONLYDIR); 293 | $files = array_diff($all, $dirs); 294 | 295 | if(isset($config['auto_detect_version']) && $config['auto_detect_version'] == true) 296 | { 297 | $config['extension_version'] = get_module_version($files); 298 | $archive_connect = $config['extension_name'] . '-' . $config['extension_version'] . '.tgz'; 299 | } 300 | 301 | if(!$config['skip_version_compare']) 302 | { 303 | check_module_version_vs_package_version($files, $config['extension_version']); 304 | } 305 | 306 | $xml = create_package_xml($files,$temp_dir,$config); 307 | 308 | file_put_contents($temp_dir . '/package.xml',$xml); 309 | 310 | if(!is_dir($path_output)) 311 | { 312 | mkdir($path_output, 0777, true); 313 | } 314 | 315 | $archiver = new Mage_Archive_Tar; 316 | $archiver->pack($temp_dir,$path_output.'/'.$archive_files,true); 317 | 318 | shell_exec('gzip ' . $path_output . '/' . $archive_files); 319 | shell_exec('mv ' . $path_output . '/' . $archive_files.'.gz '.$path_output.'/' . $archive_connect); 320 | // Creating extension xml for connect using the extension name 321 | create_extension_xml($files, $config, $temp_dir, $path_output); 322 | } 323 | /** 324 | * extrapolate the target module using the file absolute path 325 | * @param string $filePath 326 | * @return string 327 | */ 328 | function extract_target($filePath) 329 | { 330 | foreach (get_target_map() as $tMap) { 331 | $pattern = '#' . $tMap['path'] . '#'; 332 | if (preg_match($pattern, $filePath)) { 333 | return $tMap['target']; 334 | } 335 | } 336 | return 'mage'; 337 | } 338 | /** 339 | * get target map 340 | * @return array 341 | */ 342 | function get_target_map() 343 | { 344 | return array( 345 | array('path' => 'app/etc', 'target' => 'mageetc'), 346 | array('path' => 'app/code/local', 'target' => 'magelocal'), 347 | array('path' => 'app/code/community', 'target' => 'magecommunity'), 348 | array('path' => 'app/code/core', 'target' => 'magecore'), 349 | array('path' => 'app/design', 'target' => 'magedesign'), 350 | array('path' => 'lib', 'target' => 'magelib'), 351 | array('path' => 'app/locale', 'target' => 'magelocale'), 352 | array('path' => 'media/', 'target' => 'magemedia'), 353 | array('path' => 'skin/', 'target' => 'mageskin'), 354 | array('path' => 'http://', 'target' => 'mageweb'), 355 | array('path' => 'https://', 'target' => 'mageweb'), 356 | array('path' => 'Test/', 'target' => 'magetest'), 357 | ); 358 | } 359 | function create_extension_xml($files, $config, $tempDir, $path_output) 360 | { 361 | $extensionPath = $tempDir . DIRECTORY_SEPARATOR . 'var/connect/'; 362 | if (!is_dir($extensionPath)) { 363 | mkdir($extensionPath, 0777, true); 364 | } 365 | $extensionFileName = $extensionPath . $config['extension_name'] . '.xml'; 366 | file_put_contents($extensionFileName, build_extension_xml($files, $config)); 367 | shell_exec('cp -Rf ' . $tempDir . DIRECTORY_SEPARATOR . 'var '. $path_output); 368 | } 369 | function build_extension_xml($files, $config) 370 | { 371 | $xml = simplexml_load_string('<_/>'); 372 | $xml->addChild('form_key')->value = isset($config['form_key']) ? $config['form_key'] : uniqid(); 373 | $xml->addChild('_create')->value = isset($config['_create']) ? $config['_create'] : ''; 374 | $xml->addChild('name')->value = $config['extension_name']; 375 | $xml->addChild('channel')->value = $config['channel']; 376 | $versionIds = $xml->addChild('version_ids'); 377 | $versionIds->addChild('version_ids')->value = 2; 378 | $versionIds->addChild('version_ids')->value = 1; 379 | $xml->addChild('summary')->value = $config['summary']; 380 | $xml->addChild('description')->value = $config['description']; 381 | $xml->addChild('license')->value = $config['license']; 382 | $xml->addChild('license_uri')->value = isset($config['license_uri']) ? $config['license_uri'] : ''; 383 | $xml->addChild('version')->value = $config['extension_version']; 384 | $xml->addChild('stability')->value = $config['stability']; 385 | $xml->addChild('notes')->value = $config['notes']; 386 | 387 | $authors = $xml->addChild('authors'); 388 | $authorName = $authors->addChild('name'); 389 | $authorName->addChild('name')->value = $config['author_name']; 390 | 391 | $authorUser = $authors->addChild('user'); 392 | $authorUser->addChild('user')->value = $config['author_user']; 393 | 394 | $authorEmail = $authors->addChild('email'); 395 | $authorEmail->addChild('email')->value = $config['author_email']; 396 | 397 | $xml->addChild('depends_php_min')->value = $config['php_min']; 398 | $xml->addChild('depends_php_max')->value = $config['php_max']; 399 | 400 | $node = $xml->addChild('contents'); 401 | $targetNode = $node->addChild('target'); 402 | $pathNode = $node->addChild('path'); 403 | $typeNode = $node->addChild('type'); 404 | $includeNode = $node->addChild('include'); 405 | $ignoreNode = $node->addChild('ignore'); 406 | 407 | foreach ($files as $file) { 408 | $targetNode->addChild('target')->value = extract_target($file); 409 | $pathNode->addChild('path')->value = $file; 410 | $typeNode->addChild('type')->value = 'file'; 411 | $includeNode->addChild('include'); 412 | $ignoreNode->addChild('ignore'); 413 | } 414 | 415 | return $xml->asXml(); 416 | } 417 | main($argv); 418 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/vendor/magento/downloader/lib/Mage/Archive/Abstract.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | class Mage_Archive_Abstract 35 | { 36 | /** 37 | * Write data to file. If file can't be opened - throw exception 38 | * 39 | * @param string $destination 40 | * @param string $data 41 | * @return boolean 42 | * @throws Mage_Exception 43 | */ 44 | protected function _writeFile($destination, $data) 45 | { 46 | $destination = trim($destination); 47 | if(false === file_put_contents($destination, $data)) { 48 | throw new Mage_Exception("Can't write to file: " . $destination); 49 | } 50 | return true; 51 | } 52 | 53 | /** 54 | * Read data from file. If file can't be opened, throw to exception. 55 | * 56 | * @param string $source 57 | * @return string 58 | * @throws Mage_Exception 59 | */ 60 | protected function _readFile($source) 61 | { 62 | $data = ''; 63 | if (is_file($source) && is_readable($source)) { 64 | $data = @file_get_contents($source); 65 | if ($data === false) { 66 | throw new Mage_Exception("Can't get contents from: " . $source); 67 | } 68 | } 69 | return $data; 70 | } 71 | 72 | /** 73 | * Get file name from source (URI) without last extension. 74 | * 75 | * @param string $source 76 | * @param bool $withExtension 77 | * @return mixed|string 78 | */ 79 | public function getFilename($source, $withExtension=false) 80 | { 81 | $file = str_replace(dirname($source) . DS, '', $source); 82 | if (!$withExtension) { 83 | $file = substr($file, 0, strrpos($file, '.')); 84 | } 85 | return $file; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/vendor/magento/downloader/lib/Mage/Archive/Helper/File.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | class Mage_Archive_Helper_File 35 | { 36 | /** 37 | * Full path to directory where file located 38 | * 39 | * @var string 40 | */ 41 | protected $_fileLocation; 42 | 43 | /** 44 | * File name 45 | * 46 | * @var string 47 | */ 48 | protected $_fileName; 49 | 50 | /** 51 | * Full path (directory + filename) to file 52 | * 53 | * @var string 54 | */ 55 | protected $_filePath; 56 | 57 | /** 58 | * File permissions that will be set if file opened in write mode 59 | * 60 | * @var int 61 | */ 62 | protected $_chmod; 63 | 64 | /** 65 | * File handler 66 | * 67 | * @var pointer 68 | */ 69 | protected $_fileHandler; 70 | 71 | /** 72 | * Set file path via constructor 73 | * 74 | * @param string $filePath 75 | */ 76 | public function __construct($filePath) 77 | { 78 | $pathInfo = pathinfo($filePath); 79 | 80 | $this->_filePath = $filePath; 81 | $this->_fileLocation = isset($pathInfo['dirname']) ? $pathInfo['dirname'] : ''; 82 | $this->_fileName = isset($pathInfo['basename']) ? $pathInfo['basename'] : ''; 83 | } 84 | 85 | /** 86 | * Close file if it's not closed before object destruction 87 | */ 88 | public function __destruct() 89 | { 90 | if ($this->_fileHandler) { 91 | $this->_close(); 92 | } 93 | } 94 | 95 | /** 96 | * Open file 97 | * 98 | * @param string $mode 99 | * @param int $chmod 100 | * @throws Mage_Exception 101 | */ 102 | public function open($mode = 'w+', $chmod = 0666) 103 | { 104 | if ($this->_isWritableMode($mode)) { 105 | if (!is_writable($this->_fileLocation)) { 106 | throw new Mage_Exception('Permission denied to write to ' . $this->_fileLocation); 107 | } 108 | 109 | if (is_file($this->_filePath) && !is_writable($this->_filePath)) { 110 | throw new Mage_Exception("Can't open file " . $this->_fileName . " for writing. Permission denied."); 111 | } 112 | } 113 | 114 | if ($this->_isReadableMode($mode) && (!is_file($this->_filePath) || !is_readable($this->_filePath))) { 115 | if (!is_file($this->_filePath)) { 116 | throw new Mage_Exception('File ' . $this->_filePath . ' does not exist'); 117 | } 118 | 119 | if (!is_readable($this->_filePath)) { 120 | throw new Mage_Exception('Permission denied to read file ' . $this->_filePath); 121 | } 122 | } 123 | 124 | $this->_open($mode); 125 | 126 | $this->_chmod = $chmod; 127 | } 128 | 129 | /** 130 | * Write data to file 131 | * 132 | * @param string $data 133 | */ 134 | public function write($data) 135 | { 136 | $this->_checkFileOpened(); 137 | $this->_write($data); 138 | } 139 | 140 | /** 141 | * Read data from file 142 | * 143 | * @param int $length 144 | * @return string|boolean 145 | */ 146 | public function read($length = 4096) 147 | { 148 | $data = false; 149 | $this->_checkFileOpened(); 150 | if ($length > 0) { 151 | $data = $this->_read($length); 152 | } 153 | 154 | return $data; 155 | } 156 | 157 | /** 158 | * Check whether end of file reached 159 | * 160 | * @return boolean 161 | */ 162 | public function eof() 163 | { 164 | $this->_checkFileOpened(); 165 | return $this->_eof(); 166 | } 167 | 168 | /** 169 | * Close file 170 | */ 171 | public function close() 172 | { 173 | $this->_checkFileOpened(); 174 | $this->_close(); 175 | $this->_fileHandler = false; 176 | @chmod($this->_filePath, $this->_chmod); 177 | } 178 | 179 | /** 180 | * Implementation of file opening 181 | * 182 | * @param string $mode 183 | * @throws Mage_Exception 184 | */ 185 | protected function _open($mode) 186 | { 187 | $this->_fileHandler = @fopen($this->_filePath, $mode); 188 | 189 | if (false === $this->_fileHandler) { 190 | throw new Mage_Exception('Failed to open file ' . $this->_filePath); 191 | } 192 | } 193 | 194 | /** 195 | * Implementation of writing data to file 196 | * 197 | * @param string $data 198 | * @throws Mage_Exception 199 | */ 200 | protected function _write($data) 201 | { 202 | $result = @fwrite($this->_fileHandler, $data); 203 | 204 | if (false === $result) { 205 | throw new Mage_Exception('Failed to write data to ' . $this->_filePath); 206 | } 207 | } 208 | 209 | /** 210 | * Implementation of file reading 211 | * 212 | * @param int $length 213 | * @throws Mage_Exception 214 | */ 215 | protected function _read($length) 216 | { 217 | $result = fread($this->_fileHandler, $length); 218 | 219 | if (false === $result) { 220 | throw new Mage_Exception('Failed to read data from ' . $this->_filePath); 221 | } 222 | 223 | return $result; 224 | } 225 | 226 | /** 227 | * Implementation of EOF indicator 228 | * 229 | * @return boolean 230 | */ 231 | protected function _eof() 232 | { 233 | return feof($this->_fileHandler); 234 | } 235 | 236 | /** 237 | * Implementation of file closing 238 | */ 239 | protected function _close() 240 | { 241 | fclose($this->_fileHandler); 242 | } 243 | 244 | /** 245 | * Check whether requested mode is writable mode 246 | * 247 | * @param string $mode 248 | */ 249 | protected function _isWritableMode($mode) 250 | { 251 | return preg_match('/(^[waxc])|(\+$)/', $mode); 252 | } 253 | 254 | /** 255 | * Check whether requested mode is readable mode 256 | * 257 | * @param string $mode 258 | */ 259 | protected function _isReadableMode($mode) { 260 | return !$this->_isWritableMode($mode); 261 | } 262 | 263 | /** 264 | * Check whether file is opened 265 | * 266 | * @throws Mage_Exception 267 | */ 268 | protected function _checkFileOpened() 269 | { 270 | if (!$this->_fileHandler) { 271 | throw new Mage_Exception('File not opened'); 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/vendor/magento/downloader/lib/Mage/Archive/Interface.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | interface Mage_Archive_Interface 35 | { 36 | /** 37 | * Pack file or directory. 38 | * 39 | * @param string $source 40 | * @param string $destination 41 | * @return string 42 | */ 43 | public function pack($source, $destination); 44 | 45 | /** 46 | * Unpack file or directory. 47 | * 48 | * @param string $source 49 | * @param string $destination 50 | * @return string 51 | */ 52 | public function unpack($source, $destination); 53 | } 54 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/vendor/magento/downloader/lib/Mage/Archive/Tar.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | class Mage_Archive_Tar extends Mage_Archive_Abstract implements Mage_Archive_Interface 35 | { 36 | /** 37 | * Tar block size 38 | * 39 | * @const int 40 | */ 41 | const TAR_BLOCK_SIZE = 512; 42 | 43 | /** 44 | * Keep file or directory for packing. 45 | * 46 | * @var string 47 | */ 48 | protected $_currentFile; 49 | 50 | /** 51 | * Keep path to file or directory for packing. 52 | * 53 | * @var mixed 54 | */ 55 | protected $_currentPath; 56 | 57 | /** 58 | * Skip first level parent directory. Example: 59 | * use test/fip.php instead test/test/fip.php; 60 | * 61 | * @var mixed 62 | */ 63 | protected $_skipRoot; 64 | 65 | /** 66 | * Tarball data writer 67 | * 68 | * @var Mage_Archive_Helper_File 69 | */ 70 | protected $_writer; 71 | 72 | /** 73 | * Tarball data reader 74 | * 75 | * @var Mage_Archive_Helper_File 76 | */ 77 | protected $_reader; 78 | 79 | /** 80 | * Path to file where tarball should be placed 81 | * 82 | * @var string 83 | */ 84 | protected $_destinationFilePath; 85 | 86 | /** 87 | * Initialize tarball writer 88 | * 89 | * @return Mage_Archive_Tar 90 | */ 91 | protected function _initWriter() 92 | { 93 | $this->_writer = new Mage_Archive_Helper_File($this->_destinationFilePath); 94 | $this->_writer->open('w'); 95 | 96 | return $this; 97 | } 98 | 99 | /** 100 | * Returns string that is used for tar's header parsing 101 | * 102 | * @return string 103 | */ 104 | protected static final function _getFormatParseHeader() 105 | { 106 | return 'a100name/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1type/a100symlink/a6magic/a2version/' 107 | . 'a32uname/a32gname/a8devmajor/a8devminor/a155prefix/a12closer'; 108 | } 109 | 110 | /** 111 | * Destroy tarball writer 112 | * 113 | * @return Mage_Archive_Tar 114 | */ 115 | protected function _destroyWriter() 116 | { 117 | if ($this->_writer instanceof Mage_Archive_Helper_File) { 118 | $this->_writer->close(); 119 | $this->_writer = null; 120 | } 121 | 122 | return $this; 123 | } 124 | 125 | /** 126 | * Get tarball writer 127 | * 128 | * @return Mage_Archive_Helper_File 129 | */ 130 | protected function _getWriter() 131 | { 132 | if (!$this->_writer) { 133 | $this->_initWriter(); 134 | } 135 | 136 | return $this->_writer; 137 | } 138 | 139 | /** 140 | * Initialize tarball reader 141 | * 142 | * @return Mage_Archive_Tar 143 | */ 144 | protected function _initReader() 145 | { 146 | $this->_reader = new Mage_Archive_Helper_File($this->_getCurrentFile()); 147 | $this->_reader->open('r'); 148 | 149 | return $this; 150 | } 151 | 152 | /** 153 | * Destroy tarball reader 154 | * 155 | * @return Mage_Archive_Tar 156 | */ 157 | protected function _destroyReader() 158 | { 159 | if ($this->_reader instanceof Mage_Archive_Helper_File) { 160 | $this->_reader->close(); 161 | $this->_reader = null; 162 | } 163 | 164 | return $this; 165 | } 166 | 167 | /** 168 | * Get tarball reader 169 | * 170 | * @return Mage_Archive_Helper_File 171 | */ 172 | protected function _getReader() 173 | { 174 | if (!$this->_reader) { 175 | $this->_initReader(); 176 | } 177 | 178 | return $this->_reader; 179 | } 180 | 181 | /** 182 | * Set option that define ability skip first catalog level. 183 | * 184 | * @param mixed $skipRoot 185 | * @return Mage_Archive_Tar 186 | */ 187 | protected function _setSkipRoot($skipRoot) 188 | { 189 | $this->_skipRoot = $skipRoot; 190 | return $this; 191 | } 192 | 193 | /** 194 | * Set file which is packing. 195 | * 196 | * @param string $file 197 | * @return Mage_Archive_Tar 198 | */ 199 | protected function _setCurrentFile($file) 200 | { 201 | $this->_currentFile = $file .((!is_link($file) && is_dir($file) && substr($file, -1) != DS) ? DS : ''); 202 | return $this; 203 | } 204 | 205 | /** 206 | * Set path to file where tarball should be placed 207 | * 208 | * @param string $destinationFilePath 209 | * @return Mage_Archive_Tar 210 | */ 211 | protected function _setDestinationFilePath($destinationFilePath) 212 | { 213 | $this->_destinationFilePath = $destinationFilePath; 214 | return $this; 215 | } 216 | 217 | /** 218 | * Retrieve file which is packing. 219 | * 220 | * @return string 221 | */ 222 | protected function _getCurrentFile() 223 | { 224 | return $this->_currentFile; 225 | } 226 | 227 | /** 228 | * Set path to file which is packing. 229 | * 230 | * @param string $path 231 | * @return Mage_Archive_Tar 232 | */ 233 | protected function _setCurrentPath($path) 234 | { 235 | if ($this->_skipRoot && is_dir($path)) { 236 | $this->_currentPath = $path.(substr($path, -1)!=DS?DS:''); 237 | } else { 238 | $this->_currentPath = dirname($path) . DS; 239 | } 240 | return $this; 241 | } 242 | 243 | /** 244 | * Retrieve path to file which is packing. 245 | * 246 | * @return string 247 | */ 248 | protected function _getCurrentPath() 249 | { 250 | return $this->_currentPath; 251 | } 252 | 253 | /** 254 | * Walk through directory and add to tar file or directory. 255 | * Result is packed string on TAR format. 256 | * 257 | * @deprecated after 1.7.0.0 258 | * @param boolean $skipRoot 259 | * @return string 260 | */ 261 | protected function _packToTar($skipRoot=false) 262 | { 263 | $file = $this->_getCurrentFile(); 264 | $header = ''; 265 | $data = ''; 266 | if (!$skipRoot) { 267 | $header = $this->_composeHeader(); 268 | $data = $this->_readFile($file); 269 | $data = str_pad($data, floor(((is_dir($file) ? 0 : filesize($file)) + 512 - 1) / 512) * 512, "\0"); 270 | } 271 | $sub = ''; 272 | if (is_dir($file)) { 273 | $treeDir = scandir($file); 274 | if (empty($treeDir)) { 275 | throw new Mage_Exception('Can\'t scan dir: ' . $file); 276 | } 277 | array_shift($treeDir); /* remove './'*/ 278 | array_shift($treeDir); /* remove '../'*/ 279 | foreach ($treeDir as $item) { 280 | $sub .= $this->_setCurrentFile($file.$item)->_packToTar(false); 281 | } 282 | } 283 | $tarData = $header . $data . $sub; 284 | $tarData = str_pad($tarData, floor((strlen($tarData) - 1) / 1536) * 1536, "\0"); 285 | return $tarData; 286 | } 287 | 288 | /** 289 | * Recursively walk through file tree and create tarball 290 | * 291 | * @param boolean $skipRoot 292 | * @param boolean $finalize 293 | * @throws Mage_Exception 294 | */ 295 | protected function _createTar($skipRoot = false, $finalize = false) 296 | { 297 | if (!$skipRoot) { 298 | $this->_packAndWriteCurrentFile(); 299 | } 300 | 301 | $file = $this->_getCurrentFile(); 302 | 303 | if (is_dir($file)) { 304 | $dirFiles = scandir($file); 305 | 306 | if (false === $dirFiles) { 307 | throw new Mage_Exception('Can\'t scan dir: ' . $file); 308 | } 309 | 310 | array_shift($dirFiles); /* remove './'*/ 311 | array_shift($dirFiles); /* remove '../'*/ 312 | 313 | foreach ($dirFiles as $item) { 314 | $this->_setCurrentFile($file . $item)->_createTar(); 315 | } 316 | } 317 | 318 | if ($finalize) { 319 | $this->_getWriter()->write(str_repeat("\0", self::TAR_BLOCK_SIZE * 12)); 320 | } 321 | } 322 | 323 | /** 324 | * Write current file to tarball 325 | */ 326 | protected function _packAndWriteCurrentFile() 327 | { 328 | $archiveWriter = $this->_getWriter(); 329 | $archiveWriter->write($this->_composeHeader()); 330 | 331 | $currentFile = $this->_getCurrentFile(); 332 | 333 | $fileSize = 0; 334 | 335 | if (is_file($currentFile) && !is_link($currentFile)) { 336 | $fileReader = new Mage_Archive_Helper_File($currentFile); 337 | $fileReader->open('r'); 338 | 339 | while (!$fileReader->eof()) { 340 | $archiveWriter->write($fileReader->read()); 341 | } 342 | 343 | $fileReader->close(); 344 | 345 | $fileSize = filesize($currentFile); 346 | } 347 | 348 | $appendZerosCount = (self::TAR_BLOCK_SIZE - $fileSize % self::TAR_BLOCK_SIZE) % self::TAR_BLOCK_SIZE; 349 | $archiveWriter->write(str_repeat("\0", $appendZerosCount)); 350 | } 351 | 352 | /** 353 | * Compose header for current file in TAR format. 354 | * If length of file's name greater 100 characters, 355 | * method breaks header into two pieces. First contains 356 | * header and data with long name. Second contain only header. 357 | * 358 | * @param boolean $long 359 | * @return string 360 | */ 361 | protected function _composeHeader($long = false) 362 | { 363 | $file = $this->_getCurrentFile(); 364 | $path = $this->_getCurrentPath(); 365 | $infoFile = stat($file); 366 | $nameFile = str_replace($path, '', $file); 367 | $nameFile = str_replace('\\', '/', $nameFile); 368 | $packedHeader = ''; 369 | $longHeader = ''; 370 | if (!$long && strlen($nameFile)>100) { 371 | $longHeader = $this->_composeHeader(true); 372 | $longHeader .= str_pad($nameFile, floor((strlen($nameFile) + 512 - 1) / 512) * 512, "\0"); 373 | } 374 | $header = array(); 375 | $header['100-name'] = $long?'././@LongLink':substr($nameFile, 0, 100); 376 | $header['8-mode'] = $long ? ' ' 377 | : str_pad(substr(sprintf("%07o", $infoFile['mode']),-4), 6, '0', STR_PAD_LEFT); 378 | $header['8-uid'] = $long || $infoFile['uid']==0?"\0\0\0\0\0\0\0":sprintf("%07o", $infoFile['uid']); 379 | $header['8-gid'] = $long || $infoFile['gid']==0?"\0\0\0\0\0\0\0":sprintf("%07o", $infoFile['gid']); 380 | $header['12-size'] = $long ? sprintf("%011o", strlen($nameFile)) : sprintf("%011o", is_dir($file) 381 | ? 0 : filesize($file)); 382 | $header['12-mtime'] = $long?'00000000000':sprintf("%011o", $infoFile['mtime']); 383 | $header['8-check'] = sprintf('% 8s', ''); 384 | $header['1-type'] = $long ? 'L' : (is_link($file) ? 2 : (is_dir($file) ? 5 : 0)); 385 | $header['100-symlink'] = is_link($file) ? readlink($file) : ''; 386 | $header['6-magic'] = 'ustar '; 387 | $header['2-version'] = ' '; 388 | $a=function_exists('posix_getpwuid')?posix_getpwuid (fileowner($file)):array('name'=>''); 389 | $header['32-uname'] = $a['name']; 390 | $a=function_exists('posix_getgrgid')?posix_getgrgid (filegroup($file)):array('name'=>''); 391 | $header['32-gname'] = $a['name']; 392 | $header['8-devmajor'] = ''; 393 | $header['8-devminor'] = ''; 394 | $header['155-prefix'] = ''; 395 | $header['12-closer'] = ''; 396 | 397 | $packedHeader = ''; 398 | foreach ($header as $key=>$element) { 399 | $length = explode('-', $key); 400 | $packedHeader .= pack('a' . $length[0], $element); 401 | } 402 | 403 | $checksum = 0; 404 | for ($i = 0; $i < 512; $i++) { 405 | $checksum += ord(substr($packedHeader, $i, 1)); 406 | } 407 | $packedHeader = substr_replace($packedHeader, sprintf("%07o", $checksum)."\0", 148, 8); 408 | 409 | return $longHeader . $packedHeader; 410 | } 411 | 412 | /** 413 | * Read TAR string from file, and unpacked it. 414 | * Create files and directories information about discribed 415 | * in the string. 416 | * 417 | * @param string $destination path to file is unpacked 418 | * @return array list of files 419 | * @throws Mage_Exception 420 | */ 421 | protected function _unpackCurrentTar($destination) 422 | { 423 | $archiveReader = $this->_getReader(); 424 | $list = array(); 425 | 426 | while (!$archiveReader->eof()) { 427 | $header = $this->_extractFileHeader(); 428 | 429 | if (!$header) { 430 | continue; 431 | } 432 | 433 | $currentFile = $destination . $header['name']; 434 | $dirname = dirname($currentFile); 435 | 436 | if (in_array($header['type'], array("0",chr(0), ''))) { 437 | 438 | if(!file_exists($dirname)) { 439 | $mkdirResult = @mkdir($dirname, 0777, true); 440 | 441 | if (false === $mkdirResult) { 442 | throw new Mage_Exception('Failed to create directory ' . $dirname); 443 | } 444 | } 445 | 446 | $this->_extractAndWriteFile($header, $currentFile); 447 | $list[] = $currentFile; 448 | 449 | } elseif ($header['type'] == '5') { 450 | 451 | if(!file_exists($dirname)) { 452 | $mkdirResult = @mkdir($currentFile, $header['mode'], true); 453 | 454 | if (false === $mkdirResult) { 455 | throw new Mage_Exception('Failed to create directory ' . $currentFile); 456 | } 457 | } 458 | $list[] = $currentFile . DS; 459 | } elseif ($header['type'] == '2') { 460 | 461 | $symlinkResult = @symlink($header['symlink'], $currentFile); 462 | 463 | if (false === $symlinkResult) { 464 | throw new Mage_Exception('Failed to create symlink ' . $currentFile . ' to ' . $header['symlink']); 465 | } 466 | } 467 | } 468 | 469 | return $list; 470 | } 471 | 472 | /** 473 | * Get header from TAR string and unpacked it by format. 474 | * 475 | * @deprecated after 1.7.0.0 476 | * @param resource $pointer 477 | * @return string 478 | */ 479 | protected function _parseHeader(&$pointer) 480 | { 481 | $firstLine = fread($pointer, 512); 482 | 483 | if (strlen($firstLine)<512){ 484 | return false; 485 | } 486 | 487 | $fmt = self::_getFormatParseHeader(); 488 | $header = unpack ($fmt, $firstLine); 489 | 490 | $header['mode']=$header['mode']+0; 491 | $header['uid']=octdec($header['uid']); 492 | $header['gid']=octdec($header['gid']); 493 | $header['size']=octdec($header['size']); 494 | $header['mtime']=octdec($header['mtime']); 495 | $header['checksum']=octdec($header['checksum']); 496 | 497 | if ($header['type'] == "5") { 498 | $header['size'] = 0; 499 | } 500 | 501 | $checksum = 0; 502 | $firstLine = substr_replace($firstLine, ' ', 148, 8); 503 | for ($i = 0; $i < 512; $i++) { 504 | $checksum += ord(substr($firstLine, $i, 1)); 505 | } 506 | 507 | $isUstar = 'ustar' == strtolower(substr($header['magic'], 0, 5)); 508 | 509 | $checksumOk = $header['checksum'] == $checksum; 510 | if (isset($header['name']) && $checksumOk) { 511 | if ($header['name'] == '././@LongLink' && $header['type'] == 'L') { 512 | $realName = substr(fread($pointer, floor(($header['size'] + 512 - 1) / 512) * 512), 0, $header['size']); 513 | $headerMain = $this->_parseHeader($pointer); 514 | $headerMain['name'] = $realName; 515 | return $headerMain; 516 | } else { 517 | if ($header['size']>0) { 518 | $header['data'] = substr(fread($pointer, floor(($header['size'] + 512 - 1) / 512) * 512), 0, $header['size']); 519 | } else { 520 | $header['data'] = ''; 521 | } 522 | return $header; 523 | } 524 | } 525 | return false; 526 | } 527 | 528 | /** 529 | * Read and decode file header information from tarball 530 | * 531 | * @return array|boolean 532 | */ 533 | protected function _extractFileHeader() 534 | { 535 | $archiveReader = $this->_getReader(); 536 | 537 | $headerBlock = $archiveReader->read(self::TAR_BLOCK_SIZE); 538 | 539 | if (strlen($headerBlock) < self::TAR_BLOCK_SIZE) { 540 | return false; 541 | } 542 | 543 | $header = unpack(self::_getFormatParseHeader(), $headerBlock); 544 | 545 | $header['mode'] = octdec($header['mode']); 546 | $header['uid'] = octdec($header['uid']); 547 | $header['gid'] = octdec($header['gid']); 548 | $header['size'] = octdec($header['size']); 549 | $header['mtime'] = octdec($header['mtime']); 550 | $header['checksum'] = octdec($header['checksum']); 551 | 552 | if ($header['type'] == "5") { 553 | $header['size'] = 0; 554 | } 555 | 556 | $checksum = 0; 557 | $headerBlock = substr_replace($headerBlock, ' ', 148, 8); 558 | 559 | for ($i = 0; $i < 512; $i++) { 560 | $checksum += ord(substr($headerBlock, $i, 1)); 561 | } 562 | 563 | $checksumOk = $header['checksum'] == $checksum; 564 | if (isset($header['name']) && $checksumOk) { 565 | 566 | if (!($header['name'] == '././@LongLink' && $header['type'] == 'L')) { 567 | $header['name'] = trim($header['name']); 568 | return $header; 569 | } 570 | 571 | $realNameBlockSize = floor(($header['size'] + self::TAR_BLOCK_SIZE - 1) / self::TAR_BLOCK_SIZE) 572 | * self::TAR_BLOCK_SIZE; 573 | $realNameBlock = $archiveReader->read($realNameBlockSize); 574 | $realName = substr($realNameBlock, 0, $header['size']); 575 | 576 | $headerMain = $this->_extractFileHeader(); 577 | $headerMain['name'] = trim($realName); 578 | return $headerMain; 579 | } 580 | 581 | return false; 582 | } 583 | 584 | /** 585 | * Extract next file from tarball by its $header information and save it to $destination 586 | * 587 | * @param array $fileHeader 588 | * @param string $destination 589 | */ 590 | protected function _extractAndWriteFile($fileHeader, $destination) 591 | { 592 | $fileWriter = new Mage_Archive_Helper_File($destination); 593 | $fileWriter->open('w', $fileHeader['mode']); 594 | 595 | $archiveReader = $this->_getReader(); 596 | 597 | $filesize = $fileHeader['size']; 598 | $bytesExtracted = 0; 599 | 600 | while ($filesize > $bytesExtracted && !$archiveReader->eof()) { 601 | $block = $archiveReader->read(self::TAR_BLOCK_SIZE); 602 | $nonExtractedBytesCount = $filesize - $bytesExtracted; 603 | 604 | $data = substr($block, 0, $nonExtractedBytesCount); 605 | $fileWriter->write($data); 606 | 607 | $bytesExtracted += strlen($block); 608 | } 609 | } 610 | 611 | /** 612 | * Pack file to TAR (Tape Archiver). 613 | * 614 | * @param string $source 615 | * @param string $destination 616 | * @param boolean $skipRoot 617 | * @return string 618 | */ 619 | public function pack($source, $destination, $skipRoot = false) 620 | { 621 | $this->_setSkipRoot($skipRoot); 622 | $source = realpath($source); 623 | $tarData = $this->_setCurrentPath($source) 624 | ->_setDestinationFilePath($destination) 625 | ->_setCurrentFile($source); 626 | 627 | $this->_initWriter(); 628 | $this->_createTar($skipRoot, true); 629 | $this->_destroyWriter(); 630 | 631 | return $destination; 632 | } 633 | 634 | /** 635 | * Unpack file from TAR (Tape Archiver). 636 | * 637 | * @param string $source 638 | * @param string $destination 639 | * @return string 640 | */ 641 | public function unpack($source, $destination) 642 | { 643 | $this->_setCurrentFile($source) 644 | ->_setCurrentPath($source); 645 | 646 | $this->_initReader(); 647 | $this->_unpackCurrentTar($destination); 648 | $this->_destroyReader(); 649 | 650 | return $destination; 651 | } 652 | 653 | /** 654 | * Extract one file from TAR (Tape Archiver). 655 | * 656 | * @param string $file 657 | * @param string $source 658 | * @param string $destination 659 | * @return string 660 | */ 661 | public function extract($file, $source, $destination) 662 | { 663 | $this->_setCurrentFile($source); 664 | $this->_initReader(); 665 | 666 | $archiveReader = $this->_getReader(); 667 | $extractedFile = ''; 668 | 669 | while (!$archiveReader->eof()) { 670 | $header = $this->_extractFileHeader(); 671 | if ($header['name'] == $file) { 672 | $extractedFile = $destination . basename($header['name']); 673 | $this->_extractAndWriteFile($header, $extractedFile); 674 | break; 675 | } 676 | 677 | if ($header['type'] != 5){ 678 | $skipBytes = floor(($header['size'] + self::TAR_BLOCK_SIZE - 1) / self::TAR_BLOCK_SIZE) 679 | * self::TAR_BLOCK_SIZE; 680 | $archiveReader->read($skipBytes); 681 | } 682 | } 683 | 684 | $this->_destroyReader(); 685 | return $extractedFile; 686 | } 687 | } 688 | -------------------------------------------------------------------------------- /support/MagentoTarToConnect/vendor/magento/downloader/lib/Mage/Exception.php: -------------------------------------------------------------------------------- 1 | 33 | */ 34 | class Mage_Exception extends Exception 35 | {} 36 | -------------------------------------------------------------------------------- /support/config.php: -------------------------------------------------------------------------------- 1 | dirname(__FILE__) . '/..', 7 | 'archive_files' => 'tmp.tar', 8 | 9 | //The Magento Connect extension name. Must be unique on Magento Connect 10 | //Has no relation to your code module name. Will be the Connect extension name 11 | 'extension_name' => 'analytics', 12 | 13 | //Your extension version. By default, if you're creating an extension from a 14 | //single Magento module, the tar-to-connect script will look to make sure this 15 | //matches the module version. You can skip this check by setting the 16 | //skip_version_compare value to true 17 | 'extension_version' => '0.0.0', 18 | 'skip_version_compare' => false, 19 | 20 | //You can also have the package script use the version in the module you 21 | //are packaging with. 22 | 'auto_detect_version' => true, 23 | 24 | //Where on your local system you'd like to build the files to 25 | 'path_output' => dirname(__FILE__) . '/../dist', 26 | 27 | //Magento Connect license value. 28 | 'stability' => 'stable', 29 | 30 | //Magento Connect license value 31 | 'license' => 'MIT', 32 | 33 | //Magento Connect channel value. This should almost always (always?) be community 34 | 'channel' => 'community', 35 | 36 | //Magento Connect information fields. 37 | 'summary' => 'Segment lets you integrate 100+ analytics and marketing tools without writing any code yourself!', 38 | 'description' => 'Analytics for Magento is a Magento extension by Segment that lets you integrate any analytics or marketing tool you want with the flick of a switch! No code required. When you turn on the plugin, Segment automatically starts tracking important actions, like when users view items, add products to carts, and complete orders. To send this data along to your preferred tools, just go to the Segment control panel and toggle them on. This will save you months of time installing analytics.', 39 | 'notes' => '', 40 | 41 | //Magento Connect author information. If author_email is foo@example.com, script will 42 | //prompt you for the correct name. Should match your http://www.magentocommerce.com/ 43 | //login email address 44 | 'author_name' => 'Segment', 45 | 'author_user' => 'segmentio', 46 | 'author_email' => 'friends@segment.io', 47 | 48 | //PHP min/max fields for Connect. I don't know if anyone uses these, but you should 49 | //probably check that they're accurate 50 | 'php_min' => '5.2.0', 51 | 'php_max' => '6.0.0', 52 | 53 | //PHP extension dependencies. An array containing one or more of either: 54 | // - a single string (the name of the extension dependency); use this if the 55 | // extension version does not matter 56 | // - an associative array with 'name', 'min', and 'max' keys which correspond 57 | // to the extension's name and min/max required versions 58 | //Example: 59 | // array('json', array('name' => 'mongo', 'min' => '1.3.0', 'max' => '1.4.0')) 60 | 'extensions' => array() 61 | ); --------------------------------------------------------------------------------