Version Notes
1.0.0
Download this release
Release Info
Developer | OSF Global |
Extension | OSF_Integrator_for_IngramMicro |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments.php +54 -0
- app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments/Grid.php +89 -0
- app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments/Renderer/Status.php +34 -0
- app/code/community/Osf/IngramMicro/Block/Adminhtml/System/Config/Frontend/Button.php +58 -0
- app/code/community/Osf/IngramMicro/Helper/Connect.php +139 -0
- app/code/community/Osf/IngramMicro/Helper/Data.php +83 -0
- app/code/community/Osf/IngramMicro/Helper/Error.php +38 -0
- app/code/community/Osf/IngramMicro/Helper/Ftp.php +79 -0
- app/code/community/Osf/IngramMicro/LICENSE.txt +20 -0
- app/code/community/Osf/IngramMicro/Model/Adminhtml/System/Config/Backend/Catmap.php +42 -0
- app/code/community/Osf/IngramMicro/Model/Callback.php +51 -0
- app/code/community/Osf/IngramMicro/Model/Catmap.php +28 -0
- app/code/community/Osf/IngramMicro/Model/Import.php +257 -0
- app/code/community/Osf/IngramMicro/Model/Observer.php +124 -0
- app/code/community/Osf/IngramMicro/Model/Order.php +383 -0
- app/code/community/Osf/IngramMicro/Model/Queue.php +33 -0
- app/code/community/Osf/IngramMicro/Model/Resource/Catmap.php +28 -0
- app/code/community/Osf/IngramMicro/Model/Resource/Catmap/Collection.php +28 -0
- app/code/community/Osf/IngramMicro/Model/Resource/Queue.php +28 -0
- app/code/community/Osf/IngramMicro/Model/Resource/Queue/Collection.php +28 -0
- app/code/community/Osf/IngramMicro/Model/Shipnotice.php +172 -0
- app/code/community/Osf/IngramMicro/Model/Source.php +45 -0
- app/code/community/Osf/IngramMicro/controllers/CallbackController.php +34 -0
- app/code/community/Osf/IngramMicro/controllers/IndexController.php +66 -0
- app/code/community/Osf/IngramMicro/etc/config.xml +132 -0
- app/code/community/Osf/IngramMicro/etc/system.xml +188 -0
- app/code/community/Osf/IngramMicro/lib/magmi/conf/Ingrammicro/CategoryImporter.conf +5 -0
- app/code/community/Osf/IngramMicro/lib/magmi/conf/Ingrammicro/plugins.conf +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/engines/magmi_productimportengine.php +1924 -0
- app/code/community/Osf/IngramMicro/lib/magmi/engines/magmi_utilityengine.php +86 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/dbhelper.class.php +661 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/fshelper.php +478 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/license.txt +19 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_config.php +274 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_defs.php +14 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_engine.php +559 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_loggers.php +71 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_mixin.php +44 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_pluginhelper.php +197 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_statemanager.php +71 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_utils.php +180 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_valueparser.php +62 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_version.php +5 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/properties.php +218 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/remotefilegetter.php +381 -0
- app/code/community/Osf/IngramMicro/lib/magmi/inc/timecounter.php +278 -0
- app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/magmi_datapump.php +38 -0
- app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/magmi_datapumpdatasource.php +15 -0
- app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/productimport_datapump.php +87 -0
- app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/pumpfactory.ini +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/optimizer/magmi_optimizer_plugin.php +39 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/reindex/magmi_reindexing_plugin.php +112 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/reindex/options_panel.php +54 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/columnmapper/000_columnmapper.php +113 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/columnmapper/options_panel.php +25 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/defaultvalues/00_default_values.php +93 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/defaultvalues/options_panel.php +23 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/02_genericmapper.php +118 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/__common__.csv +4 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/backorders.csv +3 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/country_of_manufacture.csv +246 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/msrp_display_actual_price_type.csv +4 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/msrp_enabled.csv +3 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/options_container.csv +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/page_layout.csv +6 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/status.csv +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/tax_class_id.csv +4 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/visibility.csv +4 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/options_panel.php +8 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/importlimiter/01_importlimiter.php +167 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/importlimiter/options_panel.php +54 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/productdeleter/options_panel.php +8 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/productdeleter/productdeleter.php +61 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/skufinder/001_skufinder.php +95 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/skufinder/options_panel.php +10 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/categories/categoryimport.php +464 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/categories/options_panel.php +56 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/customoptions/options_panel.php +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/customoptions/pablo_customoptions.php +372 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/downloadable/downloadableprocessor.php +302 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/downloadable/options_panel.php +10 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/imageprocessor/imageitattributeemprocessor.php +654 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/imageprocessor/options_panel.php +144 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/itemindexer/options_panel.php +22 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/itemindexer/otfindexer.php +396 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/03_valuereplacer.php +102 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/helper/remapper.php +77 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/options_panel.php +61 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuetrim/options_panel.php +2 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuetrim/valuetrimmer.php +90 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/obsolete.txt +1 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_datasource.php +24 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_default_options_panel.php +1 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_defaultattributehandler.php +433 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_generalimport_plugin.php +16 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_item_processor.php +102 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_plugin.php +337 -0
- app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_utility_plugin.php +15 -0
- app/code/community/Osf/IngramMicro/lib/magmi/state/magmistate +1 -0
- app/code/community/Osf/IngramMicro/lib/magmi/state/progress.txt +0 -0
- app/code/community/Osf/IngramMicro/lib/magmi/state/timings.txt +50 -0
- app/code/community/Osf/IngramMicro/lib/magmi/state/trace.txt +0 -0
- app/code/community/Osf/IngramMicro/sql/osf_ingrammicro_setup/install-0.0.1.php +99 -0
- app/design/adminhtml/default/default/template/osf/ingrammicro/system/config/button.phtml +1 -0
- app/etc/modules/Osf_IngramMicro.xml +9 -0
- package.xml +18 -0
app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Shipments Block
|
11 |
+
*
|
12 |
+
* @category Osf IngramMicro
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Block_Adminhtml_Shipments extends Mage_Adminhtml_Block_Sales_Order_View_Tab_Shipments
|
18 |
+
{
|
19 |
+
protected function _prepareColumns()
|
20 |
+
{
|
21 |
+
$this->addColumn('increment_id', array(
|
22 |
+
'header' => Mage::helper('sales')->__('Shipment #'),
|
23 |
+
'index' => 'increment_id',
|
24 |
+
));
|
25 |
+
|
26 |
+
$this->addColumn('shipping_name', array(
|
27 |
+
'header' => Mage::helper('sales')->__('Ship to Name'),
|
28 |
+
'index' => 'shipping_name',
|
29 |
+
));
|
30 |
+
|
31 |
+
$this->addColumn('shipment_status', array(
|
32 |
+
'header' => Mage::helper('sales')->__('Ingrammicro Shipment Status'),
|
33 |
+
'index' => 'shipment_status',
|
34 |
+
'renderer' => 'Osf_IngramMicro_Block_Adminhtml_Shipments_Renderer_Status',
|
35 |
+
));
|
36 |
+
|
37 |
+
$this->addColumn('created_at', array(
|
38 |
+
'header' => Mage::helper('sales')->__('Date Shipped'),
|
39 |
+
'index' => 'created_at',
|
40 |
+
'type' => 'datetime',
|
41 |
+
));
|
42 |
+
|
43 |
+
$this->addColumn('total_qty', array(
|
44 |
+
'header' => Mage::helper('sales')->__('Total Qty'),
|
45 |
+
'index' => 'total_qty',
|
46 |
+
'type' => 'number',
|
47 |
+
));
|
48 |
+
|
49 |
+
return parent::_prepareColumns();
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/* Filename: Shipments.php */
|
54 |
+
/* Location: app/code/local/Osf/IngramMicro/Block/Adminhtml/Shipments.php */
|
app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments/Grid.php
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Grid Block
|
11 |
+
*
|
12 |
+
* @category Osf IngramMicro
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Block_Adminhtml_Shipments_Grid extends Mage_Adminhtml_Block_Sales_Shipment_Grid
|
18 |
+
{
|
19 |
+
protected function _prepareColumns()
|
20 |
+
{
|
21 |
+
$this->addColumn('increment_id', array(
|
22 |
+
'header' => Mage::helper('sales')->__('Shipment #'),
|
23 |
+
'index' => 'increment_id',
|
24 |
+
'type' => 'text',
|
25 |
+
));
|
26 |
+
|
27 |
+
$this->addColumn('created_at', array(
|
28 |
+
'header' => Mage::helper('sales')->__('Date Shipped'),
|
29 |
+
'index' => 'created_at',
|
30 |
+
'type' => 'datetime',
|
31 |
+
));
|
32 |
+
|
33 |
+
$this->addColumn('order_increment_id', array(
|
34 |
+
'header' => Mage::helper('sales')->__('Order #'),
|
35 |
+
'index' => 'order_increment_id',
|
36 |
+
'type' => 'text',
|
37 |
+
));
|
38 |
+
|
39 |
+
$this->addColumn('order_created_at', array(
|
40 |
+
'header' => Mage::helper('sales')->__('Order Date'),
|
41 |
+
'index' => 'order_created_at',
|
42 |
+
'type' => 'datetime',
|
43 |
+
));
|
44 |
+
|
45 |
+
$this->addColumn('shipment_status', array(
|
46 |
+
'header' => Mage::helper('sales')->__('Ingrammicro Shipment Status'),
|
47 |
+
'index' => 'shipment_status',
|
48 |
+
'type' => 'text',
|
49 |
+
'renderer' => 'Osf_IngramMicro_Block_Adminhtml_Shipments_Renderer_Status',
|
50 |
+
));
|
51 |
+
|
52 |
+
$this->addColumn('shipping_name', array(
|
53 |
+
'header' => Mage::helper('sales')->__('Ship to Name'),
|
54 |
+
'index' => 'shipping_name',
|
55 |
+
));
|
56 |
+
|
57 |
+
$this->addColumn('total_qty', array(
|
58 |
+
'header' => Mage::helper('sales')->__('Total Qty'),
|
59 |
+
'index' => 'total_qty',
|
60 |
+
'type' => 'number',
|
61 |
+
));
|
62 |
+
|
63 |
+
$this->addColumn('action',
|
64 |
+
array(
|
65 |
+
'header' => Mage::helper('sales')->__('Action'),
|
66 |
+
'width' => '50px',
|
67 |
+
'type' => 'action',
|
68 |
+
'getter' => 'getId',
|
69 |
+
'actions' => array(
|
70 |
+
array(
|
71 |
+
'caption' => Mage::helper('sales')->__('View'),
|
72 |
+
'url' => array('base'=>'*/sales_shipment/view'),
|
73 |
+
'field' => 'shipment_id'
|
74 |
+
)
|
75 |
+
),
|
76 |
+
'filter' => false,
|
77 |
+
'sortable' => false,
|
78 |
+
'is_system' => true
|
79 |
+
));
|
80 |
+
|
81 |
+
$this->addExportType('*/*/exportCsv', Mage::helper('sales')->__('CSV'));
|
82 |
+
$this->addExportType('*/*/exportExcel', Mage::helper('sales')->__('Excel XML'));
|
83 |
+
|
84 |
+
return parent::_prepareColumns();
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/* Filename: Grid.php */
|
89 |
+
/* Location: app/code/local/Osf/IngramMicro/Block/Adminhtml/Shipments/Grid.php */
|
app/code/community/Osf/IngramMicro/Block/Adminhtml/Shipments/Renderer/Status.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Status Block
|
11 |
+
*
|
12 |
+
* @category Osf IngramMicro
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Block_Adminhtml_Shipments_Renderer_Status extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
|
18 |
+
{
|
19 |
+
public function render(Varien_Object $row)
|
20 |
+
{
|
21 |
+
$label = '';
|
22 |
+
if( is_null($row->getShipmentStatus()) ){
|
23 |
+
$shipment = Mage::getModel('sales/order_shipment')->load( $row->getEntityId() );
|
24 |
+
$label = Mage::getModel('osf_ingrammicro/source')->getStatusText($shipment->getShipmentStatus());
|
25 |
+
} else {
|
26 |
+
$label = Mage::getModel('osf_ingrammicro/source')->getStatusText($row->getShipmentStatus());
|
27 |
+
}
|
28 |
+
|
29 |
+
return $label;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
/* Filename: Status.php */
|
34 |
+
/* Location: app/code/local/Osf/IngramMicro/Block/Adminhtml/Shipments/Renderer/Status.php */
|
app/code/community/Osf/IngramMicro/Block/Adminhtml/System/Config/Frontend/Button.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Button Block
|
11 |
+
*
|
12 |
+
* @category Osf IngramMicro
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Block_Adminhtml_System_Config_Frontend_Button
|
18 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field
|
19 |
+
{
|
20 |
+
/*
|
21 |
+
* Set template
|
22 |
+
*/
|
23 |
+
protected function _construct()
|
24 |
+
{
|
25 |
+
parent::_construct();
|
26 |
+
$this->setTemplate('osf/ingrammicro/system/config/button.phtml');
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Return element html
|
31 |
+
*
|
32 |
+
* @param Varien_Data_Form_Element_Abstract $element
|
33 |
+
* @return string
|
34 |
+
*/
|
35 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
|
36 |
+
{
|
37 |
+
return $this->_toHtml();
|
38 |
+
}
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Generate button html
|
44 |
+
*
|
45 |
+
* @return string
|
46 |
+
*/
|
47 |
+
public function getButtonHtml()
|
48 |
+
{
|
49 |
+
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
50 |
+
->setData(array(
|
51 |
+
'id' => 'osf_ingrammicro_button',
|
52 |
+
'label' => $this->helper('adminhtml')->__('Manual import'),
|
53 |
+
'onclick' => 'window.open(\'' . Mage::helper("adminhtml")->getUrl("ingrammicro/index/startImport") . '\'); return false;'
|
54 |
+
));
|
55 |
+
|
56 |
+
return $button->toHtml();
|
57 |
+
}
|
58 |
+
}
|
app/code/community/Osf/IngramMicro/Helper/Connect.php
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Connect Helper
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngraMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Helper_Connect extends Mage_Core_Helper_Data
|
18 |
+
{
|
19 |
+
|
20 |
+
public $ftpHost;
|
21 |
+
public $ftpUser;
|
22 |
+
public $ftpPass;
|
23 |
+
public $XMLEndpoint;
|
24 |
+
public $tmpLocation;
|
25 |
+
public $prodFileName;
|
26 |
+
public $logFile = 'ingrammicro.log';
|
27 |
+
public $vendor = 'Ingrammicro';
|
28 |
+
protected $logH = 'Error: ';
|
29 |
+
|
30 |
+
public function __construct()
|
31 |
+
{
|
32 |
+
$this->ftpHost = Mage::getStoreConfig('osf_ingrammicro/ftplogin/ftp_host');
|
33 |
+
$this->ftpUser = Mage::getStoreConfig('osf_ingrammicro/ftplogin/ftp_user');
|
34 |
+
$this->ftpPass = Mage::helper('core')->decrypt(Mage::getStoreConfig('osf_ingrammicro/ftplogin/ftp_password'));
|
35 |
+
$this->ftpRemoteDir = Mage::getStoreConfig('osf_ingrammicro/ftplogin/ftp_remote_dir');
|
36 |
+
$this->prodFileName = Mage::getStoreConfig('osf_ingrammicro/ftplogin/ftp_prod_file');
|
37 |
+
$this->XMLEndpoint = Mage::getStoreConfig('osf_ingrammicro/xmllogin/xml_endpoint');
|
38 |
+
$this->XMLUser = Mage::getStoreConfig('osf_ingrammicro/xmllogin/xml_username');
|
39 |
+
$this->XMLPass = Mage::helper('core')->decrypt(Mage::getStoreConfig('osf_ingrammicro/xmllogin/xml_password'));
|
40 |
+
$this->tmpLocation = Mage::getBaseDir('var') . DS . 'ingrammicro' . DS;
|
41 |
+
|
42 |
+
// check if the ingrammicro folder exists if not create it
|
43 |
+
if(false === $this->checkDir())
|
44 |
+
return false;
|
45 |
+
return true;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get the products file from Ingram Micro FTP
|
50 |
+
*
|
51 |
+
* @param none
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function getProductsFile()
|
55 |
+
{
|
56 |
+
//init the ftp and download the products file
|
57 |
+
$ftp = Mage::helper('osf_ingrammicro/ftp');
|
58 |
+
if(is_null($this->ftpHost) || is_null($this->ftpUser) || is_null($this->ftpPass)){
|
59 |
+
// move this log to ingrammicro log
|
60 |
+
Mage::log( $this->vendor . ': Error: ftphost or ftpuser or ftppass can not be empty', null, $this->logFile);
|
61 |
+
return false;
|
62 |
+
}
|
63 |
+
|
64 |
+
Mage::log( $this->vendor . ': Start downloading import file', null, $this->logFile);
|
65 |
+
$ftp->setRemoteDirectory($this->ftpRemoteDir);
|
66 |
+
$ftp->ftpConnect($this->ftpHost, $this->ftpUser, $this->ftpPass);
|
67 |
+
$ftp->downloadFile($this->tmpLocation . $this->prodFileName, $this->prodFileName);
|
68 |
+
$ftp->ftpClose();
|
69 |
+
Mage::log( $this->vendor . ': End downloading import file', null, $this->logFile);
|
70 |
+
|
71 |
+
// Checking the download file extension
|
72 |
+
$fileObj = new SplFileInfo($this->tmpLocation . $this->prodFileName);
|
73 |
+
|
74 |
+
if($fileObj->getExtension() === 'ZIP'){
|
75 |
+
|
76 |
+
// init the zip archive object and open so i can unzip the file
|
77 |
+
$zip = new ZipArchive;
|
78 |
+
$result = $zip->open($this->tmpLocation . $this->prodFileName);
|
79 |
+
|
80 |
+
// checking the result of the open zip
|
81 |
+
if($result === true){
|
82 |
+
$zip->extractTo($this->tmpLocation);
|
83 |
+
$zip->close();
|
84 |
+
} else {
|
85 |
+
throw new Exception("Zip: Failed, code: ". $result, 1);
|
86 |
+
}
|
87 |
+
|
88 |
+
// prepareing the name of the file because inside of the archive is a TXT file
|
89 |
+
$filename = str_replace($fileObj->getExtension(), 'TXT', $this->prodFileName);
|
90 |
+
} else {
|
91 |
+
// if the file is not archived the file name is ok
|
92 |
+
$filename = $this->prodFileName;
|
93 |
+
}
|
94 |
+
|
95 |
+
//$filename = 'PRICE.TXT';
|
96 |
+
|
97 |
+
$fullPath = Mage::getBaseDir('var') . DS . 'ingrammicro' . DS . $filename;
|
98 |
+
return $fullPath;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Send the process order xml request
|
103 |
+
*
|
104 |
+
* @param string
|
105 |
+
* @return string
|
106 |
+
*/
|
107 |
+
public function sendXMLRequest($xml)
|
108 |
+
{
|
109 |
+
/* init the http client */
|
110 |
+
$client = new Zend_Http_Client($this->XMLEndpoint);
|
111 |
+
/* set the method type and the timeout for the http call */
|
112 |
+
$client->setMethod(Zend_Http_Client::POST);
|
113 |
+
$client->setConfig(array(
|
114 |
+
'timeout' => 30)
|
115 |
+
);
|
116 |
+
|
117 |
+
$client->setRawData($xml, 'text/xml');
|
118 |
+
|
119 |
+
/* makeing the request to the server and receiving the request */
|
120 |
+
$response = $client->request();
|
121 |
+
return $response->getBody();
|
122 |
+
}
|
123 |
+
|
124 |
+
public function checkDir() {
|
125 |
+
if(file_exists($this->tmpLocation) === false){
|
126 |
+
if(!mkdir($this->tmpLocation, 0777, true)){
|
127 |
+
Mage::log($this->logH . 'Ingrammicro folder does not exist in var folder and it could not be created',
|
128 |
+
null,
|
129 |
+
$this->logFile);
|
130 |
+
return false;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
return true;
|
134 |
+
}
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
+
/* Filename: Connect.php */
|
139 |
+
/* Location: app/code/local/Osf/IngraMicro/Helper/Connect.php */
|
app/code/community/Osf/IngramMicro/Helper/Data.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/* Require the Magmi files */
|
4 |
+
require_once( Mage::getModuleDir('', 'Osf_IngramMicro') . DS . "lib/magmi/inc/magmi_defs.php");
|
5 |
+
require_once( Mage::getModuleDir('', 'Osf_IngramMicro') . DS . "lib/magmi/integration/inc/magmi_datapump.php");
|
6 |
+
/* End require Magmi files */
|
7 |
+
|
8 |
+
/**
|
9 |
+
*
|
10 |
+
* Osf Global Services
|
11 |
+
*
|
12 |
+
* NOTICE OF LICENSE
|
13 |
+
*
|
14 |
+
* This source file is subject to the EULA
|
15 |
+
* that is bundled with this package in the file LICENSE.txt.
|
16 |
+
*
|
17 |
+
* Data Helper
|
18 |
+
*
|
19 |
+
* @category OSF
|
20 |
+
* @package OSF_IngraMicro
|
21 |
+
* @author OSF Global Services
|
22 |
+
*
|
23 |
+
*/
|
24 |
+
class Osf_IngramMicro_Helper_Data extends Mage_Core_Helper_Data {
|
25 |
+
|
26 |
+
protected $importArray = array();
|
27 |
+
protected $profile = "Ingrammicro";
|
28 |
+
public $resource;
|
29 |
+
public $writeConn;
|
30 |
+
public $readConn;
|
31 |
+
public $vendorTable;
|
32 |
+
public $vendorId;
|
33 |
+
public $logFile;
|
34 |
+
|
35 |
+
public function __construct(){
|
36 |
+
// getting the resources
|
37 |
+
$this->resource = Mage::getSingleton('core/resource');
|
38 |
+
$this->writeConn = $this->resource->getConnection('core_write');
|
39 |
+
$this->readConn = $this->resource->getConnection('core_read');
|
40 |
+
$this->logFile = 'ingrammicro.log';
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Starts the import using Magmi
|
45 |
+
*
|
46 |
+
* @param none
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
+
public function startMagmiImport()
|
50 |
+
{
|
51 |
+
/* Factory Create the product import */
|
52 |
+
$magmiDp = Magmi_DataPumpFactory::getDataPumpInstance("productimport");
|
53 |
+
|
54 |
+
/* Init the profile and the import method */
|
55 |
+
$magmiDp->beginImportSession($this->profile,"create");
|
56 |
+
|
57 |
+
/* looping thought the entire array of products */
|
58 |
+
foreach ($this->importArray as $productKey => $productValue) {
|
59 |
+
$res = $magmiDp->ingest($productValue);
|
60 |
+
if($res['ok'] !== true){
|
61 |
+
Mage::log('Magmi: Import of product failed, sku:' . $productValue['sku'], null,$this->logFile);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/* End import session */
|
66 |
+
$magmiDp->endImportsession();
|
67 |
+
return;
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Set the import array data
|
72 |
+
*
|
73 |
+
* @param array
|
74 |
+
* @return array
|
75 |
+
*/
|
76 |
+
public function setImportArray($dataIn)
|
77 |
+
{
|
78 |
+
return $this->importArray = $dataIn;
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
/* Filename: Data.php */
|
83 |
+
/* Location: app/code/local/Osf/IngramMicro/Helper/Data.php */
|
app/code/community/Osf/IngramMicro/Helper/Error.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* Osf Global Services
|
5 |
+
*
|
6 |
+
* NOTICE OF LICENSE
|
7 |
+
*
|
8 |
+
* This source file is subject to the EULA
|
9 |
+
* that is bundled with this package in the file LICENSE.txt.
|
10 |
+
*
|
11 |
+
* Error Helper
|
12 |
+
*
|
13 |
+
* @category OSF
|
14 |
+
* @package OSF_IngraMicro
|
15 |
+
* @author OSF Global Services
|
16 |
+
*
|
17 |
+
*/
|
18 |
+
class Osf_IngramMicro_Helper_Error extends Mage_Core_Helper_Data {
|
19 |
+
public $logFile;
|
20 |
+
|
21 |
+
public function __construct(){
|
22 |
+
$this->logFile = 'ingrammicro.log';
|
23 |
+
parent::__construct();
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Receive calls from ingram micro with ship notices
|
28 |
+
*
|
29 |
+
* @param array
|
30 |
+
* @return string
|
31 |
+
*/
|
32 |
+
public function buildXmlErrorMsg($errors){
|
33 |
+
foreach ($errors as $error) {
|
34 |
+
$errorMsg[] = trim($error->message);
|
35 |
+
}
|
36 |
+
return $errorMsg;
|
37 |
+
}
|
38 |
+
}
|
app/code/community/Osf/IngramMicro/Helper/Ftp.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* FTP Helper
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Helper_Ftp extends Mage_Core_Helper_Data {
|
18 |
+
|
19 |
+
private $conn;
|
20 |
+
private $dir;
|
21 |
+
/**
|
22 |
+
* Set Remote Directory
|
23 |
+
* @param string $dir
|
24 |
+
*/
|
25 |
+
public function setRemoteDirectory( $dir ) {
|
26 |
+
$this->dir = $dir;
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Connect to FTP
|
31 |
+
*/
|
32 |
+
public function ftpConnect($host,$user,$pass)
|
33 |
+
{
|
34 |
+
|
35 |
+
$this->conn = ftp_connect($host);
|
36 |
+
if($this->conn === false){
|
37 |
+
throw new Exception("Ftp: Could not connect!", 1);
|
38 |
+
}
|
39 |
+
if(!ftp_login($this->conn, $user, $pass)){
|
40 |
+
throw new Exception("Ftp: Could not login!", 1);
|
41 |
+
}
|
42 |
+
if(!ftp_pasv($this->conn, true)){
|
43 |
+
throw new Exception("Ftp: Could not enter passive mode!", 1);
|
44 |
+
}
|
45 |
+
|
46 |
+
if ( !ftp_chdir($this->conn, $this->dir) ) {
|
47 |
+
throw new Exception("Ftp: Could not change directory!", 1);
|
48 |
+
}
|
49 |
+
|
50 |
+
return;// $this->conn;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Download a file from the server
|
55 |
+
*
|
56 |
+
* @param string $localFile
|
57 |
+
* @param string $remoteFile
|
58 |
+
* @param string $type
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
public function downloadFile($localFile, $remoteFile, $type=FTP_BINARY)
|
62 |
+
{
|
63 |
+
return ftp_get($this->conn, $localFile, $remoteFile, $type);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Close the ftp connection
|
68 |
+
*
|
69 |
+
* @param none
|
70 |
+
* @return bool
|
71 |
+
*/
|
72 |
+
public function ftpClose()
|
73 |
+
{
|
74 |
+
return ftp_close($this->conn);
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
/* Filename: Ftp.php */
|
79 |
+
/* Location: app/code/local/Osf/IngraMicro/Helper/Ftp.php */
|
app/code/community/Osf/IngramMicro/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
IMPORTANT-READ CAREFULLY: This End-User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and OSF GLOBAL SERVICES for the use of OSF GLOBAL SERVICES software, which includes computer software and may include other associated media. YOU AGREE TO BE BOUND BY THE TERMS OF THIS EULA BY INSTALLING, COPYING, OR OTHERWISE USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT INSTALL, COPY, OR USE THE SOFTWARE;
|
3 |
+
|
4 |
+
1. RESERVATION OF RIGHTS AND OWNERSHIP. OSF GLOBAL SERVICES reserves all rights not expressly granted to you in this EULA. The Software is protected by copyright and other intellectual property laws and treaties. OSF GLOBAL SERVICES owns the title, copyright, and other intellectual property rights in the Software. The Software is licensed, not sold.
|
5 |
+
|
6 |
+
2. LIMITATIONS ON REVERSE ENGINEERING, DECOMPILATION, AND DISASSEMBLY. You may not reverse engineer, decompile, or disassemble the Software
|
7 |
+
|
8 |
+
3. NO RENTAL/COMMERCIAL HOSTING. You may not rent, lease, lend or provide commercial hosting services with the Software.
|
9 |
+
|
10 |
+
4. LINKS TO THIRD PARTY ENTITIES OR PRODUCTS. You may link to third party entities or products through the use of the Software. The third party entities or products are not under the control of OSF GLOBAL SERVICES, and OSF GLOBAL SERVICES is not responsible for the contents or functionality of any third party entities or products. OSF GLOBAL SERVICES does not promise functionality or compatibility with any 3rd party products, which are not mentioned explicitly in a product description
|
11 |
+
|
12 |
+
5. SUPPORT, UPDATES AND UPGRADES. This licence doesn't include any support, updates and upgrades. If you would require updates, upgrades and support services you will be required to subscribe to support, updates and upgrades plan for the software. Support will include guidance regarding installation, configuration or use of software as well as fixes of software errors and bugs. Depending on the nature of the problem OSF GLOBAL SERVICES at its own discretion may agree to provide additional assistance for a fee subject to a separate written agreement.
|
13 |
+
|
14 |
+
6. TERMINATION. Without prejudice to any other rights, OSF GLOBAL SERVICES may terminate this EULA if you fail to comply with the terms and conditions of this EULA. In such event, you must destroy all copies of the Software and all of its component parts.
|
15 |
+
|
16 |
+
7. LIMITED WARRANTY. FOR ANY DEFECTS THERE IS NO WARRANTY OR CONDITION OF ANY KIND.
|
17 |
+
|
18 |
+
8. EXCLUSION OF INCIDENTAL, CONSEQUENTIAL AND CERTAIN OTHER DAMAGES. IN NO EVENT SHALL OSF GLOBAL SERVICES BE LIABLE FOR ANY SPECIAL, INCIDENTAL, PUNITIVE, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS OR CONFIDENTIAL OR OTHER INFORMATION, FOR BUSINESS INTERRUPTION, FOR PERSONAL INJURY, FOR LOSS OF PRIVACY, FOR FAILURE TO MEET ANY DUTY INCLUDING OF GOOD FAITH OR OF REASONABLE CARE, FOR NEGLIGENCE, AND FOR ANY OTHER PECUNIARY OR OTHER LOSS WHATSOEVER) ARISING OUT OF OR IN ANY WAY RELATED TO THE USE OF OR INABILITY TO USE THE SOFTWARE, THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT OR OTHER SERVICES, INFORMATON, SOFTWARE, AND RELATED CONTENT THROUGH THE SOFTWARE OR OTHERWISE ARISING OUT OF THE USE OF THE SOFTWARE, OR OTHERWISE UNDER OR IN CONNECTION WITH ANY PROVISION OF THIS EULA.
|
19 |
+
|
20 |
+
|
app/code/community/Osf/IngramMicro/Model/Adminhtml/System/Config/Backend/Catmap.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Shipments Block
|
11 |
+
*
|
12 |
+
* @category Osf IngramMicro
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Adminhtml_System_Config_Backend_Catmap
|
18 |
+
extends Mage_Core_Model_Config_Data
|
19 |
+
{
|
20 |
+
public function _afterSave()
|
21 |
+
{
|
22 |
+
$csv_file = $_FILES["groups"]["tmp_name"]["general"]["fields"]["category_mapping_import"]["value"];
|
23 |
+
|
24 |
+
if ( $csv_file ) {
|
25 |
+
//Extract data from CSV file
|
26 |
+
$csv = new Varien_File_Csv;
|
27 |
+
$csv->setDelimiter("|");
|
28 |
+
$data = $csv->getData( $csv_file );
|
29 |
+
|
30 |
+
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
|
31 |
+
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
|
32 |
+
$table = Mage::getSingleton('core/resource')->getTableName('osf_ingrammicro/catmap');
|
33 |
+
|
34 |
+
$read->query("DELETE from $table");
|
35 |
+
$result_num = $write->insertArray(
|
36 |
+
$table,
|
37 |
+
array('ingrammicro_category','magento_category'),
|
38 |
+
$data
|
39 |
+
);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
app/code/community/Osf/IngramMicro/Model/Callback.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Callback Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_Ingrammicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Callback extends Mage_Core_Model_Abstract
|
18 |
+
{
|
19 |
+
public $logFile = 'ingrammicro.log';
|
20 |
+
|
21 |
+
public function receiveShipNotice($xmlString){
|
22 |
+
Mage::log('IngramMicro: ASN: Start process', null,$this->logFile);
|
23 |
+
if(empty($xmlString)){
|
24 |
+
Mage::log('IngramMicro: Error: The ship notice is empty', null,$this->logFile);
|
25 |
+
return false;
|
26 |
+
}
|
27 |
+
|
28 |
+
// turn on custom error handeling
|
29 |
+
libxml_use_internal_errors(true);
|
30 |
+
$xmlData = simplexml_load_string($xmlString);
|
31 |
+
|
32 |
+
// get errors if they exist
|
33 |
+
$errors = libxml_get_errors();
|
34 |
+
if(!empty($errors)){
|
35 |
+
Mage::log('IngramMicro: Error: XML parsing errors: ' . $xmlString, null,$this->logFile);
|
36 |
+
return false;
|
37 |
+
}
|
38 |
+
|
39 |
+
$result = Mage::getModel('osf_ingrammicro/shipnotice')->processShipNotice($xmlData);
|
40 |
+
if($result !== true){
|
41 |
+
Mage::log('IngramMicro: Error: General Error' . $xmlString, null,$this->logFile);
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
return true;
|
46 |
+
}
|
47 |
+
|
48 |
+
}
|
49 |
+
|
50 |
+
/* Filename: Callback.php */
|
51 |
+
/* Location: app/code/local/Osf/Ingrammicro/Model/Callback.php */
|
app/code/community/Osf/IngramMicro/Model/Catmap.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Catmap Model
|
11 |
+
*
|
12 |
+
* @method ()
|
13 |
+
*
|
14 |
+
* @category Osf
|
15 |
+
* @package Osf_Ingrammicro
|
16 |
+
* @author Osf Global Services
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Osf_Ingrammicro_Model_Catmap extends Mage_Core_Model_Abstract {
|
20 |
+
|
21 |
+
protected function _construct() {
|
22 |
+
$this->_init('osf_ingrammicro/catmap');
|
23 |
+
}
|
24 |
+
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Filename: Catmap.php */
|
28 |
+
/* Location: app/code/local/Osf/Ingrammicro/Model/Catmap.php */
|
app/code/community/Osf/IngramMicro/Model/Import.php
ADDED
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Import Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Import extends Mage_Core_Model_Abstract
|
18 |
+
{
|
19 |
+
public $fileHeader = array();
|
20 |
+
public $readConnection;
|
21 |
+
public $resource;
|
22 |
+
public $categoryMap;
|
23 |
+
public $ingramMicroVendorId;
|
24 |
+
public $test_mode;
|
25 |
+
public $allowedSkus;
|
26 |
+
protected $logFile = 'ingrammicro.log';
|
27 |
+
protected $vendor = 'Ingrammicro';
|
28 |
+
|
29 |
+
public function _construct()
|
30 |
+
{
|
31 |
+
|
32 |
+
$this->resource = Mage::getSingleton('core/resource');
|
33 |
+
$this->buildCategoryMap();
|
34 |
+
$this->readConnection = Mage::getSingleton('core/resource')->getConnection('core_read');
|
35 |
+
$this->test_mode = Mage::getStoreConfig('osf_ingrammicro/general/test_mode');
|
36 |
+
$this->buildAllowedSkus();
|
37 |
+
if(!$this->checkMagmiConfig()){
|
38 |
+
echo "Could not create magmi config file. Please make the folder ... temporary writeable";
|
39 |
+
die();
|
40 |
+
}
|
41 |
+
parent::_construct();
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Process the received csv
|
46 |
+
*
|
47 |
+
* @param none
|
48 |
+
* @return bool
|
49 |
+
*/
|
50 |
+
public function processData()
|
51 |
+
{
|
52 |
+
|
53 |
+
/* getting the file from the server */
|
54 |
+
$productsFile = Mage::helper('osf_ingrammicro/connect')->getProductsFile();
|
55 |
+
if($productsFile === false){
|
56 |
+
Mage::log("Ingram Micro: Error in getting products file", null, $this->logFile);
|
57 |
+
return false;
|
58 |
+
}
|
59 |
+
|
60 |
+
$file = new SplFileObject($productsFile);
|
61 |
+
|
62 |
+
/* init vars */
|
63 |
+
$productsData = array();
|
64 |
+
$row1 = 0;
|
65 |
+
$fileHeader = array();
|
66 |
+
|
67 |
+
/* looping throught the csv */
|
68 |
+
$index = 0;
|
69 |
+
while(!$file->eof()){
|
70 |
+
$row = $file->fgetcsv(",");
|
71 |
+
|
72 |
+
if ( $this->test_mode && $index > 5 ) {
|
73 |
+
break;
|
74 |
+
}
|
75 |
+
|
76 |
+
if( isset($row[1]) && !empty( $this->allowedSkus ) && !in_array( trim($row[1]), $this->allowedSkus) ){
|
77 |
+
continue;
|
78 |
+
}
|
79 |
+
|
80 |
+
/* setting the product data */
|
81 |
+
if ( isset($row[1])) {
|
82 |
+
$productsData[] = $this->createDataArr($row);
|
83 |
+
}
|
84 |
+
$index++;
|
85 |
+
}
|
86 |
+
|
87 |
+
Mage::log( $this->vendor . ": Magmi import started", null, $this->logFile);
|
88 |
+
|
89 |
+
/* setting the data to be imported and starting the import */
|
90 |
+
Mage::helper('osf_ingrammicro/data')->setImportArray($productsData);
|
91 |
+
Mage::helper('osf_ingrammicro/data')->startMagmiImport();
|
92 |
+
|
93 |
+
Mage::log( $this->vendor . ": Magmi import finished", null, $this->logFile);
|
94 |
+
|
95 |
+
echo "Import finished.";
|
96 |
+
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Construct the product array for import
|
102 |
+
*
|
103 |
+
* @param array $row
|
104 |
+
* @return array $productData
|
105 |
+
*/
|
106 |
+
public function createDataArr($row)
|
107 |
+
{
|
108 |
+
|
109 |
+
$productData = array();
|
110 |
+
$productData['sku'] = $row[1];
|
111 |
+
|
112 |
+
Mage::log( $this->vendor . ": Start building data array", null, $this->logFile);
|
113 |
+
|
114 |
+
if( !$this->productExists( $row[1] ) ){
|
115 |
+
|
116 |
+
$productData['url_key'] = Mage::getModel('catalog/product_url')->formatUrlKey( trim($row[4]) );
|
117 |
+
$productData['url_rewrite'] = 1;
|
118 |
+
$productData['mpn'] = trim($row[7]);
|
119 |
+
$productData['name'] = trim($row[4]);
|
120 |
+
$productData['short_description'] = trim($row[4]);
|
121 |
+
$productData['description'] = trim($row[4]);
|
122 |
+
$productData['manufacturer'] = trim($row[3]);
|
123 |
+
$productData['brand'] = trim($row[3]);
|
124 |
+
$productData['msrp'] = (float)$row[6];
|
125 |
+
$productData['is_oversized'] = ($row[18] === 'N')? 1 : 0;
|
126 |
+
$productData['osf_product_cost'] = (float)$row[14];
|
127 |
+
$productData['price'] = (float)$row[14];
|
128 |
+
$productData['weight'] = (!empty($row[8]))? (float)$row[8] : 1;
|
129 |
+
$productData['upc'] = $row[9];
|
130 |
+
$productData['item_length'] = (float)$row[10];
|
131 |
+
$productData['item_width'] = (float)$row[12];
|
132 |
+
$productData['item_height'] = (float)$row[13];
|
133 |
+
$productData['visibility'] = Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE;
|
134 |
+
$productData['tax_class_id'] = 2;
|
135 |
+
$productData['type_id'] = Mage_Catalog_Model_Product_Type::TYPE_SIMPLE;
|
136 |
+
$productData['attribute_set_id'] = 4;
|
137 |
+
if ( isset( $this->categoryMap[trim($row[20]) . '_' . trim($row[18])]['category_paths'] ) ) {
|
138 |
+
$productData['categories'] = $this->categoryMap[trim($row[20]) . '_' . trim($row[18])]['category_paths'];
|
139 |
+
}
|
140 |
+
$productData['osf_product_vendor'] = $this->vendor;
|
141 |
+
}
|
142 |
+
|
143 |
+
$productData['cost'] = (float)$row[14];
|
144 |
+
$productData['inventory'] = trim($row[23]);
|
145 |
+
$productData['qty'] = trim($row[23]);
|
146 |
+
$productData['status'] = ($row[0] !== 'D')? Mage_Catalog_Model_Product_Status::STATUS_ENABLED
|
147 |
+
: Mage_Catalog_Model_Product_Status::STATUS_DISABLED;
|
148 |
+
|
149 |
+
Mage::log( $this->vendor . ": Finish building data array", null, $this->logFile);
|
150 |
+
|
151 |
+
return $productData;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Check if a product with the sku exists in Magento
|
156 |
+
*
|
157 |
+
* @param array $sku
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
public function productExists($sku)
|
161 |
+
{
|
162 |
+
$tableName = $this->resource->getTableName('catalog_product_entity');
|
163 |
+
$select = $this->readConnection
|
164 |
+
->select()
|
165 |
+
->from($tableName, array(new Zend_Db_Expr('count(entity_id)')))
|
166 |
+
->where($this->readConnection->quoteInto('sku=?', $sku));
|
167 |
+
$countSku = $this->readConnection->fetchOne($select);
|
168 |
+
|
169 |
+
return ($countSku != 0)? true :false;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Validate the product based on the required validations
|
174 |
+
*
|
175 |
+
* @param array $row
|
176 |
+
* @return bool
|
177 |
+
*/
|
178 |
+
public function validate($row) {
|
179 |
+
|
180 |
+
//Check if product can be mapped with a category
|
181 |
+
if (isset($row[20]) && isset($row[18])) {
|
182 |
+
$catMap = $this->getCategoryId( trim($row[20]) . '_' . trim($row[18]) );
|
183 |
+
if ( !isset($catMap['category_paths']) ) {
|
184 |
+
return false;
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
//It seems like sometimes a space appears at the end of import files.
|
189 |
+
if ( !isset($row[1])) {
|
190 |
+
return false;
|
191 |
+
}
|
192 |
+
|
193 |
+
return true;
|
194 |
+
}
|
195 |
+
|
196 |
+
public function buildCategoryMap() {
|
197 |
+
|
198 |
+
$collection = Mage::getModel('osf_ingrammicro/catmap')->getCollection();
|
199 |
+
|
200 |
+
foreach ( $collection as $entry ) {
|
201 |
+
$this->categoryMap[ $entry->getIngrammicroCategory() ]['category_paths'] = $entry->getMagentoCategory();
|
202 |
+
}
|
203 |
+
|
204 |
+
return;
|
205 |
+
}
|
206 |
+
|
207 |
+
/**
|
208 |
+
* Check if the db configuration for magmi exists and if not create it
|
209 |
+
*
|
210 |
+
* @return bool
|
211 |
+
*/
|
212 |
+
public function checkMagmiConfig()
|
213 |
+
{
|
214 |
+
$filename = Mage::getModuleDir('', 'Osf_IngramMicro') . DS . 'lib' . DS . "magmi/conf/magmi.ini";
|
215 |
+
if(file_exists($filename)){
|
216 |
+
return true;
|
217 |
+
}
|
218 |
+
|
219 |
+
$config = Mage::getConfig()->getResourceConnectionConfig("default_setup");
|
220 |
+
$file = new SplFileObject($filename,"w");
|
221 |
+
$fileText = "[DATABASE]\nconnectivity = \"net\"\nhost = \""
|
222 |
+
. $config->host . "\"\nport = \"3306\"\nunix_socket = \ndbname = \""
|
223 |
+
. $config->dbname . "\"\nuser = \""
|
224 |
+
. $config->username . "\"\npassword = "
|
225 |
+
. $config->password . "\ntable_prefix = \n[MAGENTO]\nversion = \"1.7.x\"\nbasedir = \"../../\"\n[GLOBAL]\n"
|
226 |
+
."step = \"0.5\"\nmultiselect_sep = \",\"\ndirmask = \"755\"\nfilemask = \"644\"\n";
|
227 |
+
|
228 |
+
try{
|
229 |
+
$file->fwrite($fileText);
|
230 |
+
} catch (Exception $e){
|
231 |
+
Mage::log('Magmi Conf folder not writeable');
|
232 |
+
return false;
|
233 |
+
}
|
234 |
+
|
235 |
+
return true;
|
236 |
+
}
|
237 |
+
|
238 |
+
public function buildAllowedSkus(){
|
239 |
+
|
240 |
+
$filename = Mage::getStoreConfig('osf_ingrammicro/ftplogin/filtered_skus_file');
|
241 |
+
if ( is_file( Mage::getBaseDir('media') . DS . 'admin-config-uploads' . DS . $filename ) ) {
|
242 |
+
$allowedSkusFile = Mage::getBaseDir('media') . DS . 'admin-config-uploads' . DS . $filename;
|
243 |
+
$skusFile = new SplFileObject($allowedSkusFile);
|
244 |
+
while ( !$skusFile->eof() ) {
|
245 |
+
$row = $skusFile->fgetcsv();
|
246 |
+
$this->allowedSkus[] = trim($row[0]);
|
247 |
+
}
|
248 |
+
}
|
249 |
+
|
250 |
+
return;
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
|
255 |
+
|
256 |
+
/* Filename: Import.php */
|
257 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Import.php */
|
app/code/community/Osf/IngramMicro/Model/Observer.php
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Observer Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Observer extends Mage_Core_Model_Abstract {
|
18 |
+
|
19 |
+
protected $vendor = 'Ingrammicro';
|
20 |
+
protected $logFile = 'ingrammicro.log';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Process the order so it can be sent to Ingrammicro
|
24 |
+
*
|
25 |
+
* @param object
|
26 |
+
* @return object
|
27 |
+
*/
|
28 |
+
public function processOrder($observer)
|
29 |
+
{
|
30 |
+
|
31 |
+
Mage::log('Ingrammicro: Start procesing order', null, $this->logFile);
|
32 |
+
|
33 |
+
// get the order from Magento
|
34 |
+
$order = $observer->getOrder();
|
35 |
+
|
36 |
+
// check if order is in
|
37 |
+
if( $order->getStatus() == Mage_Sales_Model_Order::STATE_PROCESSING ){
|
38 |
+
Mage::log($this->vendor . ': End processing order, order already processed', null, $this->logFile);
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
|
42 |
+
$orderItems = $this->checkItems($order->getAllItems());
|
43 |
+
if ( $orderItems === false ) {
|
44 |
+
Mage::log($this->vendor . ': End processing order, no ' . $this->vendor .' items', null, $this->logFile);
|
45 |
+
return $this;
|
46 |
+
}
|
47 |
+
|
48 |
+
// check that the order has a shipment
|
49 |
+
$shipments = $order->getShipmentsCollection();
|
50 |
+
if(count($shipments) > 0){
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
|
54 |
+
$shipment = $this->createShipment($order,$orderItems);
|
55 |
+
|
56 |
+
// build the xml that will be sent to Ingram Micro
|
57 |
+
$xmlData = Mage::getModel('osf_ingrammicro/order')->buildOrderArray($order, $shipment);
|
58 |
+
Mage::log($xmlData, null, $this->logFile);
|
59 |
+
|
60 |
+
// send the process order request
|
61 |
+
$xmlResponse = Mage::helper('osf_ingrammicro/connect')->sendXMLRequest($xmlData);
|
62 |
+
Mage::log($xmlResponse, null, $this->logFile);
|
63 |
+
|
64 |
+
// process the response that has arrived from Ingrammicro
|
65 |
+
$response = Mage::getModel('osf_ingrammicro/order')->processOrderResponse($xmlResponse, $order, $xmlData);
|
66 |
+
Mage::log('Ingrammicro: After process response', null, $this->logFile);
|
67 |
+
|
68 |
+
Mage::log('Ingrammicro: End procesing order', null, $this->logFile);
|
69 |
+
return $this;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Check if the order contains products from ingrammicro and return the items
|
74 |
+
* @param $items
|
75 |
+
* @return bool
|
76 |
+
*/
|
77 |
+
public function checkItems($items)
|
78 |
+
{
|
79 |
+
$outItems = array();
|
80 |
+
foreach ($items as $item) {
|
81 |
+
$p_id = $item->getProduct()->getId();
|
82 |
+
$vendor = Mage::getModel('catalog/product')->load($p_id)->getData('osf_product_vendor');
|
83 |
+
if(trim($vendor) == $this->vendor){
|
84 |
+
$outItems[] = $item;
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
return (empty($outItems))? false : $outItems;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Create the shipment for the order
|
93 |
+
*
|
94 |
+
* @param $items
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
+
public function createShipment($order, $orderItems)
|
98 |
+
{
|
99 |
+
$itemsQtys = array();
|
100 |
+
foreach ($orderItems as $orderItem) {
|
101 |
+
$itemsQtys[$orderItem->getId()] = $orderItem->getData('qty_ordered');
|
102 |
+
}
|
103 |
+
|
104 |
+
$shipment = $order->prepareShipment($itemsQtys);
|
105 |
+
if ($shipment) {
|
106 |
+
$shipment->register();
|
107 |
+
$shipment->setShipmentStatus(Osf_IngramMicro_Model_Source::SHIPMENT_STATUS_PENDING);
|
108 |
+
$shipment->addComment($this->vendor . ' Items');
|
109 |
+
$shipment->getOrder()->setIsInProcess(true);
|
110 |
+
|
111 |
+
try {
|
112 |
+
$shipment->save();
|
113 |
+
} catch (Mage_Core_Exception $e) {
|
114 |
+
Mage::log($this->vendor . ': ' . $e->getMessage(), null, $this->logFile);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
return $shipment;
|
119 |
+
}
|
120 |
+
|
121 |
+
}
|
122 |
+
|
123 |
+
/* Filename: Observer.php */
|
124 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Observer.php */
|
app/code/community/Osf/IngramMicro/Model/Order.php
ADDED
@@ -0,0 +1,383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Order Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_Ingrammicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_Ingrammicro_Model_Order extends Mage_Core_Model_Abstract {
|
18 |
+
|
19 |
+
protected $account_number;
|
20 |
+
protected $XMLUser;
|
21 |
+
protected $XMLPass;
|
22 |
+
protected $XMLObj;
|
23 |
+
protected $order;
|
24 |
+
protected $queue;
|
25 |
+
protected $logFile = 'ingrammicro.log';
|
26 |
+
|
27 |
+
public function _construct()
|
28 |
+
{
|
29 |
+
$this->account_number = Mage::getStoreConfig('osf_ingrammicro/general/account_number');
|
30 |
+
$this->XMLUser = Mage::getStoreConfig('osf_ingrammicro/xmllogin/xml_username');
|
31 |
+
$this->XMLPass = Mage::helper('core')->decrypt(Mage::getStoreConfig('osf_ingrammicro/xmllogin/xml_password'));
|
32 |
+
$this->test_mode = Mage::getStoreConfig('osf_ingrammicro/general/test_mode');
|
33 |
+
|
34 |
+
parent::_construct();
|
35 |
+
}
|
36 |
+
|
37 |
+
private function _addChildElement( &$parent, $key, $value ) {
|
38 |
+
|
39 |
+
if (is_array($value)) {
|
40 |
+
$node = $parent->addChild($key);
|
41 |
+
foreach ($value as $k=>$v) {
|
42 |
+
$this->_addChildElement($node, $k, $v);
|
43 |
+
}
|
44 |
+
}else{
|
45 |
+
$node = $parent->addChild($key, $value);
|
46 |
+
}
|
47 |
+
|
48 |
+
return $parent;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Builds an Ingram Micro XML object from order data.
|
53 |
+
* This is used later on to the API
|
54 |
+
* @param array $orderData
|
55 |
+
* @return XML Object
|
56 |
+
*/
|
57 |
+
public function buildXMLData($orderData) {
|
58 |
+
|
59 |
+
$this->XMLObj = new SimpleXMLElement('<?xml version="1.0" encoding="ISO-8859-1"?><OrderRequest></OrderRequest>');
|
60 |
+
|
61 |
+
//version
|
62 |
+
$this->XMLObj->addChild('Version','2.0');
|
63 |
+
|
64 |
+
// credentials
|
65 |
+
$credentials = $this->XMLObj->addChild('TransactionHeader');
|
66 |
+
foreach ($orderData['credentials'] as $key => $value) {
|
67 |
+
$credentials->addChild($key, $value);
|
68 |
+
}
|
69 |
+
|
70 |
+
// Order Header Information
|
71 |
+
$orderHeaderInformation = $this->XMLObj->addChild('OrderHeaderInformation');
|
72 |
+
foreach ($orderData['orderHeaderInformation'] as $lvl1_key => $lvl1_val) {
|
73 |
+
$this->_addChildElement( $orderHeaderInformation, $lvl1_key, $lvl1_val);
|
74 |
+
}
|
75 |
+
|
76 |
+
// Order Request Items
|
77 |
+
$items = $this->XMLObj->addChild('OrderLineInformation');
|
78 |
+
|
79 |
+
$commentText = '';
|
80 |
+
if ($this->test_mode) {
|
81 |
+
$commentText = '///TEST PO DO NOT SHIP';
|
82 |
+
}
|
83 |
+
|
84 |
+
foreach ($orderData['items'] as $item) {
|
85 |
+
$itemNode = $items->addChild('ProductLine');
|
86 |
+
$itemNode->addChild('SKU', $item['sku']);
|
87 |
+
$itemNode->addChild('Quantity', $item['qty']);
|
88 |
+
$itemNode = $items->addChild('CommentLine');
|
89 |
+
$itemNode->addChild('CommentText', $commentText );
|
90 |
+
}
|
91 |
+
|
92 |
+
$this->XMLObj->addChild('ShowDetail','0');
|
93 |
+
|
94 |
+
return $this->XMLObj->asXML();
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Build the order array so it can be sent to xml process
|
99 |
+
*
|
100 |
+
* @param object
|
101 |
+
* @param array
|
102 |
+
* @return string
|
103 |
+
*/
|
104 |
+
public function buildOrderArray($order, $shipment)
|
105 |
+
{
|
106 |
+
$this->order = $order;
|
107 |
+
$data = array(
|
108 |
+
'orderHeaderInformation' => $this->buildOrderHeaderInformation($shipment),
|
109 |
+
'items' => $this->buildItems($shipment),
|
110 |
+
'credentials' => $this->buldCredentials($shipment)
|
111 |
+
);
|
112 |
+
|
113 |
+
return $this->buildXMLData($data);
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Building the credentials element for the request XML object
|
118 |
+
* @param object $shipment Magento Shipment Object
|
119 |
+
* @return array
|
120 |
+
*/
|
121 |
+
public function buldCredentials ( $shipment ) {
|
122 |
+
|
123 |
+
$shipment = array(
|
124 |
+
'SenderID' => 'Website',
|
125 |
+
'ReceiverID' => 'Website',
|
126 |
+
'CountryCode' => 'FT',
|
127 |
+
'LoginID' => $this->XMLUser,
|
128 |
+
'Password' => $this->XMLPass,
|
129 |
+
'TransactionID' => $shipment->getIncrementId()
|
130 |
+
|
131 |
+
);
|
132 |
+
|
133 |
+
return $shipment;
|
134 |
+
}
|
135 |
+
|
136 |
+
public function buildOrderHeaderInformation($shipment) {
|
137 |
+
$shippingAddress = $shipment->getShippingAddress();
|
138 |
+
$streetArr = $shippingAddress->getStreet();
|
139 |
+
|
140 |
+
$customerPO = $shipment->getIncrementId();
|
141 |
+
$endUserPO = $shipment->getIncrementId();
|
142 |
+
$autoRelease = '';
|
143 |
+
if ($this->test_mode) {
|
144 |
+
$autoRelease = 'H';
|
145 |
+
}
|
146 |
+
|
147 |
+
$shipment = array(
|
148 |
+
'BillToSuffix' => '',
|
149 |
+
'AddressingInformation' => array(
|
150 |
+
'CustomerPO' => $customerPO,
|
151 |
+
'ShipToAttention' => '',
|
152 |
+
'EndUserPO' => $endUserPO,
|
153 |
+
'ShipTo' => array(
|
154 |
+
'Address' => array(
|
155 |
+
'ShipToAddress1' => $shippingAddress->getFirstname() . ' ' . $shippingAddress->getLastname(),
|
156 |
+
'ShipToAddress2' => $streetArr[0],
|
157 |
+
'ShipToAddress3' => (count($streetArr) > 1)? $streetArr[1] : null,
|
158 |
+
'ShipToCity' => $shippingAddress->getCity(),
|
159 |
+
'ShipToProvince' => $shippingAddress->getRegion(),
|
160 |
+
'ShipToPostalCode' => trim($shippingAddress->getPostcode()),
|
161 |
+
)
|
162 |
+
),
|
163 |
+
),
|
164 |
+
'ProcessingOptions' => array(
|
165 |
+
'CarrierCode' => '',
|
166 |
+
'AutoRelease' => $autoRelease,
|
167 |
+
'ThirdPartyFreightAccount' => '',
|
168 |
+
'KillOrderAfterLineError' => '',
|
169 |
+
'ShipmentOptions' => array(
|
170 |
+
'BackOrderFlag' => 'Y',
|
171 |
+
'SplitShipmentFlag' => 'n',
|
172 |
+
'SplitLine' => 'N',
|
173 |
+
'ShipFromBranches' => ''
|
174 |
+
)
|
175 |
+
),
|
176 |
+
'DynamicMessage' => array(
|
177 |
+
'MessageLines' => ''
|
178 |
+
)
|
179 |
+
);
|
180 |
+
return $shipment;
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Map order items to array for xml
|
185 |
+
*
|
186 |
+
* @param array
|
187 |
+
* @return array
|
188 |
+
*/
|
189 |
+
public function buildItems($shipment)
|
190 |
+
{
|
191 |
+
$items = array();
|
192 |
+
foreach ($shipment->getAllItems() as $itemObj) {
|
193 |
+
$item = array();
|
194 |
+
$item['sku'] = $itemObj->getSku();
|
195 |
+
$item['customerPartNumber'] = $itemObj->getSku();
|
196 |
+
$item['name'] = $itemObj->getName();
|
197 |
+
$item['price'] = $itemObj->getPrice();
|
198 |
+
$item['qty'] = (int)$itemObj->getQty();
|
199 |
+
$item['comment1'] = null;
|
200 |
+
$item['comment2'] = null;
|
201 |
+
$item['shipfrom'] = null;
|
202 |
+
$item['specialPriceRef'] = null;
|
203 |
+
$items[] = $item;
|
204 |
+
}
|
205 |
+
|
206 |
+
return $items;
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Process the order response
|
211 |
+
*
|
212 |
+
* @param $xmlResponse
|
213 |
+
* @param $order
|
214 |
+
* @param $xmlData
|
215 |
+
* @internal param $object
|
216 |
+
* @return array
|
217 |
+
*/
|
218 |
+
public function processOrderResponse($xmlResponse, $order, $xmlData)
|
219 |
+
{
|
220 |
+
$this->order = $order;
|
221 |
+
$xmlResponseObject = simplexml_load_string($xmlResponse);
|
222 |
+
|
223 |
+
if($xmlResponseObject === false){
|
224 |
+
Mage::log('Ingrammicro: The response was not a xml string', null, $this->logFile);
|
225 |
+
return;
|
226 |
+
}
|
227 |
+
|
228 |
+
if(is_null($xmlResponseObject->TransactionHeader)){
|
229 |
+
Mage::log('Ingrammicro: The response xml does not contain the TransactionHeader node', null, $this->logFile);
|
230 |
+
return;
|
231 |
+
}
|
232 |
+
|
233 |
+
// Check if there is any error in the response
|
234 |
+
if (
|
235 |
+
isset($xmlResponseObject->TransactionHeader->ErrorStatus['ErrorNumber']) &&
|
236 |
+
!empty($xmlResponseObject->TransactionHeader->ErrorStatus['ErrorNumber'])
|
237 |
+
){
|
238 |
+
Mage::log('Order Response Error: ' .
|
239 |
+
$xmlResponseObject->TransactionHeader->ErrorStatus['ErrorNumber'] .
|
240 |
+
'Order Respose Error Details' .
|
241 |
+
$xmlResponseObject->TransactionHeader->ErrorStatus, null, $this->logFile);
|
242 |
+
$this->errorResponse($xmlResponseObject, $xmlData);
|
243 |
+
return;
|
244 |
+
}
|
245 |
+
|
246 |
+
$branchOrderNumber = $xmlResponseObject->BranchOrderNumber;
|
247 |
+
if( isset($branchOrderNumber) ){
|
248 |
+
$this->acceptedResponse($xmlResponseObject);
|
249 |
+
} else {
|
250 |
+
$this->rejectedResponse($xmlResponseObject);
|
251 |
+
}
|
252 |
+
|
253 |
+
return;
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* The accepted response handle
|
258 |
+
*
|
259 |
+
* @param object
|
260 |
+
* @return null
|
261 |
+
*/
|
262 |
+
public function acceptedResponse($xmlObject)
|
263 |
+
{
|
264 |
+
$transactionHeader = $xmlObject->TransactionHeader;
|
265 |
+
$orderNumbers = $xmlObject->OrderInfo->OrderNumbers;
|
266 |
+
|
267 |
+
|
268 |
+
Mage::log('Ingrammicro PO accepted: '. $transactionHeader->TransactionID, null, $this->logFile);
|
269 |
+
|
270 |
+
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($transactionHeader->TransactionID);
|
271 |
+
$shipment->setShipmentStatus(Osf_IngramMicro_Model_Source::SHIPMENT_STATUS_READY);
|
272 |
+
|
273 |
+
//Set shipping comment
|
274 |
+
$comment = 'Ingram Micro Branch Order Number: ' . $orderNumbers->BranchOrderNumber;
|
275 |
+
if (!$comment instanceof Mage_Sales_Model_Order_Shipment_Comment) {
|
276 |
+
$comment = Mage::getModel('sales/order_shipment_comment')
|
277 |
+
->setComment($comment);
|
278 |
+
}
|
279 |
+
|
280 |
+
$shipment->addComment($comment);
|
281 |
+
|
282 |
+
try{
|
283 |
+
$shipment->save();
|
284 |
+
$shipment->getCommentsCollection()->save();
|
285 |
+
} catch (Exception $e){
|
286 |
+
Mage::log('Ingrammicro: Response Error: '. $e->getMessage(), null, $this->logFile);
|
287 |
+
}
|
288 |
+
|
289 |
+
return;
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* The rejected response handle
|
294 |
+
*
|
295 |
+
* @param object
|
296 |
+
* @return null
|
297 |
+
*/
|
298 |
+
public function rejectedResponse($xmlObject)
|
299 |
+
{
|
300 |
+
# TO DO some checks about the response
|
301 |
+
$transactionHeader = $xmlObject->TransactionHeader;
|
302 |
+
Mage::log('Ingrammicro PO rejected', null, $this->logFile);
|
303 |
+
// load the shipment and cancel it
|
304 |
+
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($transactionHeader->TransactionID);
|
305 |
+
$shipment->setShipmentStatus(Osf_IngramMicro_Model_Source::SHIPMENT_STATUS_CANCELED);
|
306 |
+
try{
|
307 |
+
$shipment->save();
|
308 |
+
} catch (Exception $e){
|
309 |
+
Mage::log('Ingrammicro: Response Error: ' . $e->getMessage(), null, $this->logFile);
|
310 |
+
}
|
311 |
+
|
312 |
+
return;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* The error response handle
|
317 |
+
*
|
318 |
+
* @param $orderResponse
|
319 |
+
* @param $xmlData
|
320 |
+
* @throws Exception
|
321 |
+
* @internal param $object
|
322 |
+
* @return null
|
323 |
+
*/
|
324 |
+
public function errorResponse($orderResponse,$xmlData)
|
325 |
+
{
|
326 |
+
# for unknown error need to clarify what to do
|
327 |
+
# to do check if xmlObject is an object
|
328 |
+
$xmlObject = simplexml_load_string($xmlData);
|
329 |
+
$queue = Mage::getModel('osf_ingrammicro/queue')->loadByField('order_id', $this->order->getId());
|
330 |
+
if($queue->getId() === null){
|
331 |
+
$queue = Mage::getModel('osf_ingrammicro/queue');
|
332 |
+
$queue->setOrderId($this->order->getId());
|
333 |
+
$queue->setPoId( $xmlObject->OrderRequest->TransactionHeader->TransactionID );
|
334 |
+
$queue->setOrderXml(trim($xmlData));
|
335 |
+
$queue->setRetry(0);
|
336 |
+
$queue->setPrevError($orderResponse->ErrorMessage . ' : ' . $orderResponse->ErrorDetail);
|
337 |
+
} else {
|
338 |
+
$retry = $queue->getRetry();
|
339 |
+
if($retry >= 5){
|
340 |
+
$queue->delete();
|
341 |
+
}
|
342 |
+
$retry++;
|
343 |
+
$queue->setRetry($retry);
|
344 |
+
}
|
345 |
+
|
346 |
+
$queue->save();
|
347 |
+
|
348 |
+
# Put order on hold
|
349 |
+
$this->order->setStatus(Mage_Sales_Model_Order::STATE_HOLDED);
|
350 |
+
|
351 |
+
try{
|
352 |
+
$this->order->save();
|
353 |
+
// $shipment->save();
|
354 |
+
} catch (Exception $e){
|
355 |
+
Mage::log('Ingrammicro: Response Error: unknown error order on hold'.$e->getMessage(), null, $this->logFile);
|
356 |
+
}
|
357 |
+
|
358 |
+
return;
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
* The retry the orders gave known errors
|
363 |
+
*
|
364 |
+
* @param null
|
365 |
+
* @return null
|
366 |
+
*/
|
367 |
+
public function retry()
|
368 |
+
{
|
369 |
+
$jobs = Mage::getModel('osf_ingrammicro/queue')->getCollection();
|
370 |
+
foreach ($jobs as $job) {
|
371 |
+
$order = Mage::getModel('sales/order')->load($job->getOrderId());
|
372 |
+
$order->setStatus(Mage_Sales_Model_Order::STATE_PROCESSING);
|
373 |
+
$order->save();
|
374 |
+
$xmlResponse = Mage::helper('osf_ingrammicro/connect')->sendXMLRequest($job->getOrderXml());
|
375 |
+
$response = Mage::getModel('osf_ingrammicro/order')->processOrderResponse($xmlResponse, $order, $job->getOrderXml());
|
376 |
+
}
|
377 |
+
|
378 |
+
return;
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
/* Filename: Order.php */
|
383 |
+
/* Location: app/code/local/Osf/Ingrammicro/Model/Order.php */
|
app/code/community/Osf/IngramMicro/Model/Queue.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Queue Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_Ingrammicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_Ingrammicro_Model_Queue extends Mage_Core_Model_Abstract
|
18 |
+
{
|
19 |
+
protected function _construct()
|
20 |
+
{
|
21 |
+
$this->_init('osf_ingrammicro/queue');
|
22 |
+
}
|
23 |
+
|
24 |
+
public function loadByField($field, $fieldValue)
|
25 |
+
{
|
26 |
+
$collection = $this->getCollection()
|
27 |
+
->addFieldToFilter($field, $fieldValue);
|
28 |
+
return $collection->getFirstItem();
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
/* Filename: Queue.php */
|
33 |
+
/* Location: app/code/local/Osf/Ingrammicro/Model/Queue.php */
|
app/code/community/Osf/IngramMicro/Model/Resource/Catmap.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Catmap Model
|
11 |
+
*
|
12 |
+
* @method ()
|
13 |
+
*
|
14 |
+
* @category Osf
|
15 |
+
* @package Osf_IngramMicro
|
16 |
+
* @author Osf Global Services
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Osf_IngramMicro_Model_Resource_Catmap extends Mage_Core_Model_Resource_Db_Abstract
|
20 |
+
{
|
21 |
+
protected function _construct()
|
22 |
+
{
|
23 |
+
$this->_init('osf_ingrammicro/catmap', 'catmap_id');
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Filename: Catmap.php */
|
28 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Resource/Catmap.php */
|
app/code/community/Osf/IngramMicro/Model/Resource/Catmap/Collection.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Catmap Model
|
11 |
+
*
|
12 |
+
* @method ()
|
13 |
+
*
|
14 |
+
* @category Osf
|
15 |
+
* @package Osf_IngraMicro
|
16 |
+
* @author Osf Global Services
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Osf_IngramMicro_Model_Resource_Catmap_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
|
20 |
+
{
|
21 |
+
protected function _construct()
|
22 |
+
{
|
23 |
+
$this->_init('osf_ingrammicro/catmap');
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Filename: Collection.php */
|
28 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Resource/Catmap/Collection.php */
|
app/code/community/Osf/IngramMicro/Model/Resource/Queue.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Queue Model
|
11 |
+
*
|
12 |
+
* @method ()
|
13 |
+
*
|
14 |
+
* @category Osf
|
15 |
+
* @package Osf_IngramMicro
|
16 |
+
* @author Osf Global Services
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Osf_IngramMicro_Model_Resource_Queue extends Mage_Core_Model_Resource_Db_Abstract
|
20 |
+
{
|
21 |
+
protected function _construct()
|
22 |
+
{
|
23 |
+
$this->_init('osf_ingrammicro/queue', 'queue_id');
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Filename: Queue.php */
|
28 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Queue.php */
|
app/code/community/Osf/IngramMicro/Model/Resource/Queue/Collection.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Queue Model
|
11 |
+
*
|
12 |
+
* @method ()
|
13 |
+
*
|
14 |
+
* @category Osf
|
15 |
+
* @package Osf_IngraMicro
|
16 |
+
* @author Osf Global Services
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Osf_IngramMicro_Model_Resource_Queue_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
|
20 |
+
{
|
21 |
+
protected function _construct()
|
22 |
+
{
|
23 |
+
$this->_init('osf_ingrammicro/queue');
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
/* Filename: Queue.php */
|
28 |
+
/* Location: app/code/local/Osf/IngramMicro/Model/Queue.php */
|
app/code/community/Osf/IngramMicro/Model/Shipnotice.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Shipnotice Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_Ingrammicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Shipnotice extends Mage_Core_Model_Abstract {
|
18 |
+
|
19 |
+
|
20 |
+
|
21 |
+
public $logFile;
|
22 |
+
|
23 |
+
public function _construct()
|
24 |
+
{
|
25 |
+
$this->logFile = 'ingrammicro.log';
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Process the ship notice
|
31 |
+
*
|
32 |
+
* @param object
|
33 |
+
* @return bool
|
34 |
+
*/
|
35 |
+
public function processShipNotice($xmlData)
|
36 |
+
{
|
37 |
+
$despatchAdviceHeader = $xmlData->DespatchAdviceHeader;
|
38 |
+
if(empty($despatchAdviceHeader)){
|
39 |
+
return 'receiveShipNotice_missing_despatchAdviceHeader';
|
40 |
+
}
|
41 |
+
|
42 |
+
$purchaseOrderId = $despatchAdviceHeader->CustomerPO;
|
43 |
+
if(empty($purchaseOrderId)){
|
44 |
+
return 'receiveShipNotice_missing_CustomerPO';
|
45 |
+
}
|
46 |
+
|
47 |
+
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($purchaseOrderId);
|
48 |
+
if(is_null($shipment->getId())){
|
49 |
+
return 'receiveShipNotice_shipment_not_found';
|
50 |
+
}
|
51 |
+
|
52 |
+
$order = $shipment->getOrder();
|
53 |
+
if(is_null($order->getId())){
|
54 |
+
return 'receiveShipNotice_order_not_found';
|
55 |
+
}
|
56 |
+
|
57 |
+
// create the invoice
|
58 |
+
$invoice = $this->createInvoice($xmlData, $order, $shipment);
|
59 |
+
|
60 |
+
if($invoice === false){
|
61 |
+
$error = true;
|
62 |
+
}
|
63 |
+
|
64 |
+
// set the shipment status to shipped
|
65 |
+
$shipment->setShipmentStatus(Osf_IngramMicro_Model_Source::SHIPMENT_STATUS_SHIPPED);
|
66 |
+
|
67 |
+
// send shippment email
|
68 |
+
$shipment->sendEmail(true, '');
|
69 |
+
$shipment->setEmailSent(true);
|
70 |
+
|
71 |
+
try {
|
72 |
+
$shipment->save();
|
73 |
+
} catch(Exception $e) {
|
74 |
+
Mage::log('Ingrammicro: Ship Notice Error:'. $e->getMessage(), null, $this->logFile);
|
75 |
+
return 'receiveShipNotice_other_errors';
|
76 |
+
}
|
77 |
+
|
78 |
+
return true;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Create and invoice based on the ship noitice
|
83 |
+
*
|
84 |
+
* @param object
|
85 |
+
* @return bool
|
86 |
+
*/
|
87 |
+
public function createInvoice($xmlData, $order, $shipment)
|
88 |
+
{
|
89 |
+
// init and build an array with the received sku from the ship notices items
|
90 |
+
$shippedSku = array();
|
91 |
+
|
92 |
+
// check if the order was processed before
|
93 |
+
if($shipment->getShipmentStatus() == Osf_IngramMicro_Model_Source::SHIPMENT_STATUS_SHIPPED){
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
|
97 |
+
$trackingNumbers = array();
|
98 |
+
foreach ($xmlData->LineHeader->LineItem as $item) {
|
99 |
+
$sku = (string)$item->Product['SKU'];
|
100 |
+
$qty = (int)$item->Product['DespatchQuantity'];
|
101 |
+
$shippedSku[$sku] = $qty;
|
102 |
+
$trackingNumbers[] = $item->PackageHeader->IdentificationHeader->Identification['TrackingNumber'];
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
|
107 |
+
$uniqueTrackNumbers = array_unique($trackingNumbers);
|
108 |
+
|
109 |
+
// add tracking number
|
110 |
+
foreach ($uniqueTrackNumbers as $trackNumber) {
|
111 |
+
$trackNo = Mage::getModel('sales/order_shipment_track')
|
112 |
+
->setNumber($trackNumber)
|
113 |
+
->setCarrierCode($xmlData->ConsignmentHeader->CarrierCode)
|
114 |
+
->setTitle($xmlData->ConsignmentHeader->CarrierName);
|
115 |
+
$shipment->addTrack($trackNo);
|
116 |
+
}
|
117 |
+
|
118 |
+
// get the order items
|
119 |
+
$items = $order->getItemsCollection();
|
120 |
+
$orderItemsCount = count($items);
|
121 |
+
$asnItemsCount = count($xmlData->LineHeader->LineItem);
|
122 |
+
|
123 |
+
// init and build an array for the invoice with the qtys and ids
|
124 |
+
$qtys = array();
|
125 |
+
foreach($items as $orderItem){
|
126 |
+
|
127 |
+
if(in_array($orderItem->getSku(), array_keys($shippedSku))){
|
128 |
+
$qtys[$orderItem->getId()] = $shippedSku[$orderItem->getSku()];
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
// add the invoiced qtys
|
133 |
+
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice($qtys);
|
134 |
+
$amount = $invoice->getGrandTotal();
|
135 |
+
$invoice->register()->pay();
|
136 |
+
$invoice->getOrder()->setIsInProcess(true);
|
137 |
+
|
138 |
+
// adding a commnet to the order
|
139 |
+
$history = $invoice->getOrder()->addStatusHistoryComment(
|
140 |
+
'Amount of $' . $amount . ' captured automatically.', false
|
141 |
+
);
|
142 |
+
$history->setIsCustomerNotified(true);
|
143 |
+
// save order
|
144 |
+
$order->save();
|
145 |
+
|
146 |
+
// make the invoice transaction
|
147 |
+
Mage::getModel('core/resource_transaction')
|
148 |
+
->addObject($invoice)
|
149 |
+
->addObject($invoice->getOrder())
|
150 |
+
->save();
|
151 |
+
|
152 |
+
// save invoice and send the email to the costumer
|
153 |
+
try {
|
154 |
+
$invoice->save();
|
155 |
+
// send email to customer
|
156 |
+
$invoice->sendEmail(true, '');
|
157 |
+
if($orderItemsCount == $asnItemsCount){
|
158 |
+
$order->setStatus(Mage_Sales_Model_Order::STATE_COMPLETE);
|
159 |
+
$order->save();
|
160 |
+
}
|
161 |
+
} catch (Exception $e){
|
162 |
+
Mage::log('Ingram Micro: Invoice could not be created:'. $e->getMessage(), null, $this->logFile);
|
163 |
+
return false;
|
164 |
+
}
|
165 |
+
|
166 |
+
return true;
|
167 |
+
}
|
168 |
+
|
169 |
+
}
|
170 |
+
|
171 |
+
/* Filename: Shipnotice.php */
|
172 |
+
/* Location: app/code/local/Osf/Ingrammicro/Model/Shipnotice.php */
|
app/code/community/Osf/IngramMicro/Model/Source.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Source Model
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_Ingrammicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_Model_Source extends Varien_Object {
|
18 |
+
|
19 |
+
const SHIPMENT_STATUS_PENDING = 0;
|
20 |
+
const SHIPMENT_STATUS_READY = 1;
|
21 |
+
const SHIPMENT_STATUS_SHIPPED = 2;
|
22 |
+
const SHIPMENT_STATUS_CANCELED = 3;
|
23 |
+
const SHIPMENT_STATUS_ONHOLD = 4;
|
24 |
+
|
25 |
+
public $statuses;
|
26 |
+
|
27 |
+
public function _construct() {
|
28 |
+
|
29 |
+
$this->statuses = array(
|
30 |
+
"Pending",
|
31 |
+
"Ready",
|
32 |
+
"Shipped",
|
33 |
+
"Canceled",
|
34 |
+
"Onhold"
|
35 |
+
);
|
36 |
+
}
|
37 |
+
|
38 |
+
public function getStatusText($status) {
|
39 |
+
|
40 |
+
return $this->statuses[$status];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
/* Filename: Source.php */
|
45 |
+
/* Location: app/code/community/Osf/Ingrammicro/Model/Source.php */
|
app/code/community/Osf/IngramMicro/controllers/CallbackController.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Callback controller
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_CallbackController extends Mage_Core_Controller_Front_Action
|
18 |
+
{
|
19 |
+
public function apiAction()
|
20 |
+
{
|
21 |
+
if(!$this->getRequest()->isPost()){
|
22 |
+
$this->_redirect('/');
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
$xmlString = $this->getRequest()->getRawBody();
|
27 |
+
Mage::log('IngramMicro: Received ASN: '.$xmlString, null,'ingrammicro.log');
|
28 |
+
Mage::getModel('osf_ingrammicro/callback')->receiveShipNotice($xmlString);
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
/* Filename: CallbackController.php */
|
34 |
+
/* Location: ../app/code/local/Osf/IngramMicro/controllers/CallbackController.php */
|
app/code/community/Osf/IngramMicro/controllers/IndexController.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
* Index controller
|
11 |
+
*
|
12 |
+
* @category Osf
|
13 |
+
* @package Osf_IngramMicro
|
14 |
+
* @author Osf Global Services
|
15 |
+
*/
|
16 |
+
|
17 |
+
class Osf_IngramMicro_IndexController extends Mage_Core_Controller_Front_Action
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* The default index action
|
21 |
+
*
|
22 |
+
* @return string
|
23 |
+
*
|
24 |
+
*/
|
25 |
+
public function indexAction()
|
26 |
+
{
|
27 |
+
echo "Nothing here";
|
28 |
+
return;
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The Action that starts the import of products from IngramMicro
|
33 |
+
*
|
34 |
+
* @return null
|
35 |
+
*
|
36 |
+
*/
|
37 |
+
public function startImportAction()
|
38 |
+
{
|
39 |
+
return Mage::getModel('osf_ingrammicro/import')->processData();
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Retry to send purchase ordersCreate Shipment
|
44 |
+
*
|
45 |
+
* @return null
|
46 |
+
*
|
47 |
+
*/
|
48 |
+
public function retryCronAction()
|
49 |
+
{
|
50 |
+
return Mage::getModel('osf_ingrammicro/order')->retry();
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Check for ship notices to finalize the purchase order
|
55 |
+
*
|
56 |
+
* @return null
|
57 |
+
*
|
58 |
+
*/
|
59 |
+
public function shipNoticeCronAction()
|
60 |
+
{
|
61 |
+
return Mage::getModel('osf_ingrammicro/shipping_notice')->processNotices();
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/* Filename: IndexController.php */
|
66 |
+
/* Location: ../app/code/community/Osf/IngramMicro/controllers/IndexController.php */
|
app/code/community/Osf/IngramMicro/etc/config.xml
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<!--
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
-->
|
11 |
+
<config>
|
12 |
+
<modules>
|
13 |
+
<Osf_IngramMicro>
|
14 |
+
<version>1.0.0</version>
|
15 |
+
</Osf_IngramMicro>
|
16 |
+
</modules>
|
17 |
+
<global>
|
18 |
+
<blocks>
|
19 |
+
<osf_ingrammicro>
|
20 |
+
<class>Osf_IngramMicro_Block</class>
|
21 |
+
</osf_ingrammicro>
|
22 |
+
<adminhtml>
|
23 |
+
<rewrite>
|
24 |
+
<sales_order_view_tab_shipments>Osf_IngramMicro_Block_Adminhtml_Shipments</sales_order_view_tab_shipments>
|
25 |
+
<sales_shipment_grid>Osf_IngramMicro_Block_Adminhtml_Shipments_Grid</sales_shipment_grid>
|
26 |
+
</rewrite>
|
27 |
+
</adminhtml>
|
28 |
+
</blocks>
|
29 |
+
<models>
|
30 |
+
<osf_ingrammicro>
|
31 |
+
<class>Osf_IngramMicro_Model</class>
|
32 |
+
<resourceModel>osf_ingrammicro_resource</resourceModel>syn
|
33 |
+
</osf_ingrammicro>
|
34 |
+
<osf_ingrammicro_resource>
|
35 |
+
<class>Osf_IngramMicro_Model_Resource</class>
|
36 |
+
<entities>
|
37 |
+
<queue>
|
38 |
+
<table>osf_ingrammicro_queue</table>
|
39 |
+
</queue>
|
40 |
+
<catmap>
|
41 |
+
<table>osf_ingrammicro_catmap</table>
|
42 |
+
</catmap>
|
43 |
+
</entities>
|
44 |
+
</osf_ingrammicro_resource>
|
45 |
+
</models>
|
46 |
+
<resources>
|
47 |
+
<osf_ingrammicro_setup>
|
48 |
+
<setup>
|
49 |
+
<module>Osf_IngramMicro</module>
|
50 |
+
<!-- default, optional -->
|
51 |
+
<class>Mage_Core_Model_Resource_Setup</class>
|
52 |
+
</setup>
|
53 |
+
</osf_ingrammicro_setup>
|
54 |
+
</resources>
|
55 |
+
<helpers>
|
56 |
+
<osf_ingrammicro>
|
57 |
+
<class>Osf_IngramMicro_Helper</class>
|
58 |
+
</osf_ingrammicro>
|
59 |
+
</helpers>
|
60 |
+
<events>
|
61 |
+
<sales_order_save_after>
|
62 |
+
<observers>
|
63 |
+
<osf_sales_order_save_after>
|
64 |
+
<type>singleton</type>
|
65 |
+
<class>Osf_IngramMicro_Model_Observer</class>
|
66 |
+
<method>processOrder</method>
|
67 |
+
</osf_sales_order_save_after>
|
68 |
+
</observers>
|
69 |
+
</sales_order_save_after>
|
70 |
+
</events>
|
71 |
+
</global>
|
72 |
+
<frontend>
|
73 |
+
<routers>
|
74 |
+
<osf_ingrammicro>
|
75 |
+
<use>standard</use>
|
76 |
+
<args>
|
77 |
+
<module>Osf_IngramMicro</module>
|
78 |
+
<frontName>ingrammicro</frontName>
|
79 |
+
</args>
|
80 |
+
</osf_ingrammicro>
|
81 |
+
</routers>
|
82 |
+
</frontend>
|
83 |
+
<adminhtml>
|
84 |
+
<acl>
|
85 |
+
<resources>
|
86 |
+
<all>
|
87 |
+
<title>Allow Everything</title>
|
88 |
+
</all>
|
89 |
+
<admin>
|
90 |
+
<children>
|
91 |
+
<osf_ingrammicro module="osf_ingrammicro">
|
92 |
+
<title>Ingram Micro Configuration</title>
|
93 |
+
<sort_order>11</sort_order>
|
94 |
+
</osf_ingrammicro>
|
95 |
+
<system>
|
96 |
+
<children>
|
97 |
+
<config>
|
98 |
+
<children>
|
99 |
+
<osf_ingrammicro translate="title">
|
100 |
+
<title>Ingram Micro Configuration</title>
|
101 |
+
<sort_order>80</sort_order>
|
102 |
+
</osf_ingrammicro>
|
103 |
+
</children>
|
104 |
+
</config>
|
105 |
+
</children>
|
106 |
+
</system>
|
107 |
+
</children>
|
108 |
+
</admin>
|
109 |
+
</resources>
|
110 |
+
</acl>
|
111 |
+
</adminhtml>
|
112 |
+
<crontab>
|
113 |
+
<jobs>
|
114 |
+
<osf_ingrammicro_process>
|
115 |
+
<schedule>
|
116 |
+
<cron_expr>0 1 * * *</cron_expr>
|
117 |
+
</schedule>
|
118 |
+
<run>
|
119 |
+
<model>osf_ingrammicro/import::processData</model>
|
120 |
+
</run>
|
121 |
+
</osf_ingrammicro_process>
|
122 |
+
<osf_ingrammicro_retry>
|
123 |
+
<schedule>
|
124 |
+
<cron_expr>0 * * * *</cron_expr>
|
125 |
+
</schedule>
|
126 |
+
<run>
|
127 |
+
<model>osf_ingrammicro/order::retry</model>
|
128 |
+
</run>
|
129 |
+
</osf_ingrammicro_retry>
|
130 |
+
</jobs>
|
131 |
+
</crontab>
|
132 |
+
</config>
|
app/code/community/Osf/IngramMicro/etc/system.xml
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<!--
|
3 |
+
* Osf Global Services
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the EULA
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
*
|
10 |
+
-->
|
11 |
+
<config>
|
12 |
+
<tabs>
|
13 |
+
<osftab translate="label" module="osf_ingrammicro">
|
14 |
+
<label>Osf</label>
|
15 |
+
<sort_order>100</sort_order>
|
16 |
+
</osftab>
|
17 |
+
</tabs>
|
18 |
+
<sections>
|
19 |
+
<osf_ingrammicro module="osf_ingrammicro">
|
20 |
+
<label>Ingram Micro Configuration</label>
|
21 |
+
<tab>osftab</tab>
|
22 |
+
<frontend_type>text</frontend_type>
|
23 |
+
<sort_order>351</sort_order>
|
24 |
+
<show_in_default>1</show_in_default>
|
25 |
+
<show_in_website>1</show_in_website>
|
26 |
+
<show_in_store>1</show_in_store>
|
27 |
+
<groups>
|
28 |
+
<general translate="label">
|
29 |
+
<label>Ingram Micro General Configuration</label>
|
30 |
+
<frontend_type>text</frontend_type>
|
31 |
+
<sort_order>11</sort_order>
|
32 |
+
<show_in_default>1</show_in_default>
|
33 |
+
<show_in_website>1</show_in_website>
|
34 |
+
<show_in_store>1</show_in_store>
|
35 |
+
<fields>
|
36 |
+
<account_number translate="label">
|
37 |
+
<label>Ingram Micro Account Number</label>
|
38 |
+
<frontend_type>text</frontend_type>
|
39 |
+
<sort_order>11</sort_order>
|
40 |
+
<show_in_default>1</show_in_default>
|
41 |
+
<show_in_website>1</show_in_website>
|
42 |
+
<show_in_store>1</show_in_store>
|
43 |
+
<comment><![CDATA[ The account number received from Ingram Micro ]]></comment>
|
44 |
+
</account_number>
|
45 |
+
<test_mode translate="label comment">
|
46 |
+
<label>Test mode</label>
|
47 |
+
<frontend_type>select</frontend_type>
|
48 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
49 |
+
<sort_order>14</sort_order>
|
50 |
+
<show_in_default>1</show_in_default>
|
51 |
+
<show_in_website>1</show_in_website>
|
52 |
+
<show_in_store>1</show_in_store>
|
53 |
+
<comment><![CDATA[Turning this one will set H (HOLD) as Autorelease value, "TEST PO ONLY - DO NOT SHIP as CustomerPO]]></comment>
|
54 |
+
</test_mode>
|
55 |
+
<category_mapping_import translate="label">
|
56 |
+
<label>Category Mapping Import</label>
|
57 |
+
<frontend_type>import</frontend_type>
|
58 |
+
<backend_model>osf_ingrammicro/adminhtml_system_config_backend_catmap</backend_model>
|
59 |
+
<sort_order>40</sort_order>
|
60 |
+
<show_in_default>1</show_in_default>
|
61 |
+
<show_in_website>1</show_in_website>
|
62 |
+
<show_in_store>0</show_in_store>
|
63 |
+
<comment><![CDATA[Upload the file with the category map. For more infomation about this configuration go to user guide section "Configuration"]]></comment>
|
64 |
+
</category_mapping_import>
|
65 |
+
</fields>
|
66 |
+
</general>
|
67 |
+
<ftplogin translate="label">
|
68 |
+
<label>Ftp Configuration</label>
|
69 |
+
<frontend_type>text</frontend_type>
|
70 |
+
<sort_order>11</sort_order>
|
71 |
+
<show_in_default>1</show_in_default>
|
72 |
+
<show_in_website>1</show_in_website>
|
73 |
+
<show_in_store>1</show_in_store>
|
74 |
+
<fields>
|
75 |
+
<ftp_host translate="label">
|
76 |
+
<label>Ftp Server</label>
|
77 |
+
<frontend_type>text</frontend_type>
|
78 |
+
<sort_order>11</sort_order>
|
79 |
+
<show_in_default>1</show_in_default>
|
80 |
+
<show_in_website>1</show_in_website>
|
81 |
+
<show_in_store>1</show_in_store>
|
82 |
+
<comment><![CDATA[<b>Ex: </b> example.com OR ftp.example.com ]]></comment>
|
83 |
+
</ftp_host>
|
84 |
+
<ftp_user translate="label">
|
85 |
+
<label>Ftp Username</label>
|
86 |
+
<frontend_type>text</frontend_type>
|
87 |
+
<sort_order>12</sort_order>
|
88 |
+
<show_in_default>1</show_in_default>
|
89 |
+
<show_in_website>1</show_in_website>
|
90 |
+
<show_in_store>1</show_in_store>
|
91 |
+
<comment><![CDATA[The FTP username used to connect to ingram micro ftp]]></comment>
|
92 |
+
</ftp_user>
|
93 |
+
<ftp_password translate="label">
|
94 |
+
<label>Ftp Password</label>
|
95 |
+
<frontend_type>password</frontend_type>
|
96 |
+
<backend_model>adminhtml/system_config_backend_encrypted</backend_model>
|
97 |
+
<sort_order>13</sort_order>
|
98 |
+
<show_in_default>1</show_in_default>
|
99 |
+
<show_in_website>1</show_in_website>
|
100 |
+
<show_in_store>1</show_in_store>
|
101 |
+
<comment><![CDATA[The FTP password used to connect to ingram micro ftp]]></comment>
|
102 |
+
</ftp_password>
|
103 |
+
<ftp_remote_dir translate="label">
|
104 |
+
<label>Ftp Remote Directory</label>
|
105 |
+
<frontend_type>text</frontend_type>
|
106 |
+
<sort_order>14</sort_order>
|
107 |
+
<show_in_default>1</show_in_default>
|
108 |
+
<show_in_website>1</show_in_website>
|
109 |
+
<show_in_store>1</show_in_store>
|
110 |
+
<comment><![CDATA[Remote directory]]></comment>
|
111 |
+
</ftp_remote_dir>
|
112 |
+
<ftp_prod_file translate="label">
|
113 |
+
<label>Ftp Products Filename</label>
|
114 |
+
<frontend_type>text</frontend_type>
|
115 |
+
<sort_order>15</sort_order>
|
116 |
+
<show_in_default>1</show_in_default>
|
117 |
+
<show_in_website>1</show_in_website>
|
118 |
+
<show_in_store>1</show_in_store>
|
119 |
+
<comment><![CDATA[The products file from the server]]></comment>
|
120 |
+
</ftp_prod_file>
|
121 |
+
<filtered_skus_file translate="label tooltip comment">
|
122 |
+
<label>Filtered SKUs File</label>
|
123 |
+
<comment>Upload the file with the selected skus</comment>
|
124 |
+
<tooltip>Upload the file with the selected skus</tooltip>
|
125 |
+
<frontend_type>file</frontend_type>
|
126 |
+
<backend_model>adminhtml/system_config_backend_file</backend_model>
|
127 |
+
<upload_dir config="system/filesystem/media" scope_info="1">admin-config-uploads</upload_dir>
|
128 |
+
<base_url type="media" scope_info="1">admin-config-uploads</base_url>
|
129 |
+
<sort_order>16</sort_order>
|
130 |
+
<show_in_default>1</show_in_default>
|
131 |
+
<show_in_website>1</show_in_website>
|
132 |
+
<show_in_store>1</show_in_store>
|
133 |
+
</filtered_skus_file>
|
134 |
+
<manual_import translate="comment">
|
135 |
+
<label></label>
|
136 |
+
<comment>Upload the file with the selected skus</comment>
|
137 |
+
<frontend_type>button</frontend_type>
|
138 |
+
<frontend_model>osf_ingrammicro/adminhtml_system_config_frontend_button</frontend_model>
|
139 |
+
<sort_order>17</sort_order>
|
140 |
+
<show_in_default>1</show_in_default>
|
141 |
+
<show_in_website>1</show_in_website>
|
142 |
+
<show_in_store>1</show_in_store>
|
143 |
+
</manual_import>
|
144 |
+
</fields>
|
145 |
+
</ftplogin>
|
146 |
+
<xmllogin translate="label">
|
147 |
+
<label>XML Configuration</label>
|
148 |
+
<frontend_type>text</frontend_type>
|
149 |
+
<sort_order>12</sort_order>
|
150 |
+
<show_in_default>1</show_in_default>
|
151 |
+
<show_in_website>1</show_in_website>
|
152 |
+
<show_in_store>1</show_in_store>
|
153 |
+
<fields>
|
154 |
+
<xml_endpoint translate="label">
|
155 |
+
<label>XML Endpoint</label>
|
156 |
+
<frontend_type>text</frontend_type>
|
157 |
+
<sort_order>11</sort_order>
|
158 |
+
<show_in_default>1</show_in_default>
|
159 |
+
<show_in_website>1</show_in_website>
|
160 |
+
<show_in_store>1</show_in_store>
|
161 |
+
<comment><![CDATA[<b>Ex: </b> example.com ]]></comment>
|
162 |
+
</xml_endpoint>
|
163 |
+
<xml_username translate="label">
|
164 |
+
<label>Xml Username</label>
|
165 |
+
<frontend_type>text</frontend_type>
|
166 |
+
<sort_order>12</sort_order>
|
167 |
+
<show_in_default>1</show_in_default>
|
168 |
+
<show_in_website>1</show_in_website>
|
169 |
+
<show_in_store>1</show_in_store>
|
170 |
+
<comment><![CDATA[The username used to connect to ingram micro endpoint]]></comment>
|
171 |
+
</xml_username>
|
172 |
+
<xml_password translate="label">
|
173 |
+
<label>Xml Password</label>
|
174 |
+
<frontend_type>password</frontend_type>
|
175 |
+
<backend_model>adminhtml/system_config_backend_encrypted</backend_model>
|
176 |
+
<sort_order>13</sort_order>
|
177 |
+
<show_in_default>1</show_in_default>
|
178 |
+
<show_in_website>1</show_in_website>
|
179 |
+
<show_in_store>1</show_in_store>
|
180 |
+
<comment><![CDATA[The password used to connect to ingram micro endpoint]]></comment>
|
181 |
+
</xml_password>
|
182 |
+
|
183 |
+
</fields>
|
184 |
+
</xmllogin>
|
185 |
+
</groups>
|
186 |
+
</osf_ingrammicro>
|
187 |
+
</sections>
|
188 |
+
</config>
|
app/code/community/Osf/IngramMicro/lib/magmi/conf/Ingrammicro/CategoryImporter.conf
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[CategoryImporter]
|
2 |
+
CAT:baseroot =
|
3 |
+
CAT:lastonly = "0"
|
4 |
+
CAT:urlending = ".html"
|
5 |
+
CAT:treesep = "/"
|
app/code/community/Osf/IngramMicro/lib/magmi/conf/Ingrammicro/plugins.conf
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
[PLUGINS_ITEMPROCESSORS]
|
2 |
+
classes = "CategoryImporter"
|
app/code/community/Osf/IngramMicro/lib/magmi/engines/magmi_productimportengine.php
ADDED
@@ -0,0 +1,1924 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* MAGENTO MASS IMPORTER CLASS
|
5 |
+
*
|
6 |
+
* version : 1.7.8
|
7 |
+
* author : S.BRACQUEMONT aka dweeves
|
8 |
+
* updated : 2010-10-09
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* use external file for db helper */
|
13 |
+
require_once ("magmi_engine.php");
|
14 |
+
require_once ("magmi_valueparser.php");
|
15 |
+
|
16 |
+
/**
|
17 |
+
*
|
18 |
+
*
|
19 |
+
* Magmi Product Import engine class
|
20 |
+
* This class handle product import
|
21 |
+
*
|
22 |
+
* @author dweeves
|
23 |
+
*
|
24 |
+
*/
|
25 |
+
class Magmi_ProductImportEngine extends Magmi_Engine
|
26 |
+
{
|
27 |
+
//attribute info cache
|
28 |
+
public $attrinfo = array();
|
29 |
+
//attribute info by type
|
30 |
+
public $attrbytype = array();
|
31 |
+
//attribute set cache
|
32 |
+
public $attribute_sets = array();
|
33 |
+
//product entity type
|
34 |
+
public $prod_etype;
|
35 |
+
//default attribute set id
|
36 |
+
public $default_asid;
|
37 |
+
//store id cache
|
38 |
+
public $sidcache = array();
|
39 |
+
//default mode
|
40 |
+
public $mode = "update";
|
41 |
+
//cache for column names that are not attributes
|
42 |
+
private $_notattribs = array();
|
43 |
+
//list of attribute handlers
|
44 |
+
private $_attributehandlers;
|
45 |
+
//current import row
|
46 |
+
private $_current_row;
|
47 |
+
//option id cache for select/multiselect
|
48 |
+
private $_optidcache = null;
|
49 |
+
//current item ids
|
50 |
+
private $_curitemids = array("sku"=>null);
|
51 |
+
//default store list to impact
|
52 |
+
private $_dstore = array();
|
53 |
+
//same flag if current import line is referencing same item than the previous one
|
54 |
+
private $_same;
|
55 |
+
//current product id
|
56 |
+
private $_currentpid;
|
57 |
+
//extra attributes to create
|
58 |
+
private $_extra_attrs;
|
59 |
+
//current import profile
|
60 |
+
private $_profile;
|
61 |
+
//Store ids cache for website scoped attributes
|
62 |
+
private $_sid_wsscope = array();
|
63 |
+
//Store ids cache for store scope attributes
|
64 |
+
private $_sid_sscope = array();
|
65 |
+
//magento product table columns list
|
66 |
+
private $_prodcols = array();
|
67 |
+
//magento stock related table columns list
|
68 |
+
private $_stockcols = array();
|
69 |
+
//stats
|
70 |
+
private $_skustats = array();
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* constructor
|
75 |
+
*
|
76 |
+
* @param string $conffile
|
77 |
+
* : configuration .ini filename
|
78 |
+
*/
|
79 |
+
public function __construct()
|
80 |
+
{
|
81 |
+
parent::__construct();
|
82 |
+
$this->setBuiltinPluginClasses("itemprocessors",
|
83 |
+
dirname(dirname(__FILE__)) .
|
84 |
+
"/plugins/inc/magmi_defaultattributehandler.php::Magmi_DefaultAttributeItemProcessor");
|
85 |
+
}
|
86 |
+
|
87 |
+
public function getSkuStats()
|
88 |
+
{
|
89 |
+
return $this->_skustats;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* (non-PHPdoc)
|
94 |
+
*
|
95 |
+
* @see Magmi_Engine::getEngineInfo()
|
96 |
+
*/
|
97 |
+
public function getEngineInfo()
|
98 |
+
{
|
99 |
+
return array("name"=>"Magmi Product Import Engine","version"=>"1.8.2","author"=>"dweeves");
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* load properties
|
104 |
+
*
|
105 |
+
* @param string $conf
|
106 |
+
* : configuration .ini filename
|
107 |
+
*/
|
108 |
+
public function initProdType()
|
109 |
+
{
|
110 |
+
$tname = $this->tablename("eav_entity_type");
|
111 |
+
$this->prod_etype = $this->selectone("SELECT entity_type_id FROM $tname WHERE entity_type_code=?",
|
112 |
+
"catalog_product", "entity_type_id");
|
113 |
+
$this->default_asid = $this->getAttributeSetId('Default');
|
114 |
+
}
|
115 |
+
|
116 |
+
public function getPluginFamilies()
|
117 |
+
{
|
118 |
+
return array("datasources","general","itemprocessors");
|
119 |
+
}
|
120 |
+
|
121 |
+
public function registerAttributeHandler($ahinst, $attdeflist)
|
122 |
+
{
|
123 |
+
foreach ($attdeflist as $attdef)
|
124 |
+
{
|
125 |
+
$ad = explode(":", $attdef);
|
126 |
+
if (count($ad) != 2)
|
127 |
+
{
|
128 |
+
$this->log("Invalid registration string ($attdef) :" . get_class($ahinst), "warning");
|
129 |
+
}
|
130 |
+
else
|
131 |
+
{
|
132 |
+
$this->_attributehandlers[$attdef] = $ahinst;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
*
|
139 |
+
* Return list of store codes that share the same website than the stores passed as parameter
|
140 |
+
*
|
141 |
+
* @param string $scodes
|
142 |
+
* comma separated list of store view codes
|
143 |
+
*/
|
144 |
+
public function getStoreIdsForWebsiteScope($scodes)
|
145 |
+
{
|
146 |
+
if (!isset($this->_sid_wsscope[$scodes]))
|
147 |
+
{
|
148 |
+
$this->_sid_wsscope[$scodes] = array();
|
149 |
+
$wscarr = csl2arr($scodes);
|
150 |
+
$qcolstr = $this->arr2values($wscarr);
|
151 |
+
$cs = $this->tablename("core_store");
|
152 |
+
$sql = "SELECT csdep.store_id FROM $cs as csmain
|
153 |
+
JOIN $cs as csdep ON csdep.website_id=csmain.website_id
|
154 |
+
WHERE csmain.code IN ($qcolstr) ";
|
155 |
+
$sidrows = $this->selectAll($sql, $wscarr);
|
156 |
+
foreach ($sidrows as $sidrow)
|
157 |
+
{
|
158 |
+
$this->_sid_wsscope[$scodes][] = $sidrow["store_id"];
|
159 |
+
}
|
160 |
+
}
|
161 |
+
return $this->_sid_wsscope[$scodes];
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Returns the list of store ids corresponding to the store view codes
|
166 |
+
* @param unknown $scodes
|
167 |
+
* @return multitype:
|
168 |
+
*/
|
169 |
+
public function getStoreIdsForStoreScope($scodes)
|
170 |
+
{
|
171 |
+
if (!isset($this->_sid_sscope[$scodes]))
|
172 |
+
{
|
173 |
+
$this->_sid_sscope[$scodes] = array();
|
174 |
+
$scarr = csl2arr($scodes);
|
175 |
+
$qcolstr = $this->arr2values($scarr);
|
176 |
+
$cs = $this->tablename("core_store");
|
177 |
+
$sql = "SELECT csmain.store_id from $cs as csmain WHERE csmain.code IN ($qcolstr)";
|
178 |
+
$sidrows = $this->selectAll($sql, $scarr);
|
179 |
+
foreach ($sidrows as $sidrow)
|
180 |
+
{
|
181 |
+
$this->_sid_sscope[$scodes][] = $sidrow["store_id"];
|
182 |
+
}
|
183 |
+
}
|
184 |
+
return $this->_sid_sscope[$scodes];
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Returns Magento current data for given item
|
189 |
+
* @param unknown $item : item to get magento data from
|
190 |
+
* @param unknown $params : item metadata
|
191 |
+
* @param string $cols : columns list to return (if not set, all items column list)
|
192 |
+
* @return Ambigous <multitype:, multitype:unknown >
|
193 |
+
*/
|
194 |
+
public function getMagentoData($item, $params, $cols = null)
|
195 |
+
{
|
196 |
+
// out data
|
197 |
+
$out = array();
|
198 |
+
// if no specific columns set, use all item keys as base
|
199 |
+
if ($cols == null)
|
200 |
+
{
|
201 |
+
$cols = array_keys($item);
|
202 |
+
}
|
203 |
+
$this->initAttrInfos($cols);
|
204 |
+
// cross with defined attributes
|
205 |
+
$attrkeys = array_intersect($cols, array_keys($this->attrinfo));
|
206 |
+
// Create several maps:
|
207 |
+
// 1 per backend type => 1 request per backend type
|
208 |
+
// 1 to retrieve attribute code from attribute id (avoid a join since we already have the map)
|
209 |
+
$bta = array();
|
210 |
+
$idcodemap = array();
|
211 |
+
|
212 |
+
// Handle atribute retrieval
|
213 |
+
|
214 |
+
foreach ($attrkeys as $k)
|
215 |
+
{
|
216 |
+
$attrdata = $this->attrinfo[$k];
|
217 |
+
$bt = "" . $attrdata["backend_type"];
|
218 |
+
if ($bt != "static")
|
219 |
+
{
|
220 |
+
$attid = $attrdata["attribute_id"];
|
221 |
+
if (!isset($bta[$bt]))
|
222 |
+
{
|
223 |
+
$bta[$bt] = array();
|
224 |
+
}
|
225 |
+
$bta[$bt][] = $attid;
|
226 |
+
$idcodemap[$attid] = $k;
|
227 |
+
}
|
228 |
+
}
|
229 |
+
|
230 |
+
// Peform SQL "by type"
|
231 |
+
foreach (array_keys($bta) as $bt)
|
232 |
+
{
|
233 |
+
$cpet = $this->tablename("catalog_product_entity_$bt");
|
234 |
+
$storeids = $this->getItemStoreIds($item);
|
235 |
+
$sid = $storeids[0];
|
236 |
+
$sql = "SELECT attribute_id,value FROM $cpet WHERE entity_id=? AND store_id=? AND attribute_id IN (" .
|
237 |
+
$this->arr2values($bta[$bt]) . ")";
|
238 |
+
$tdata = $this->selectAll($sql, array_merge(array($params["product_id"],$sid), $bta[$bt]));
|
239 |
+
foreach ($tdata as $row)
|
240 |
+
{
|
241 |
+
$out[$idcodemap[$row["attribute_id"]]] = $row["value"];
|
242 |
+
}
|
243 |
+
unset($tdata);
|
244 |
+
}
|
245 |
+
|
246 |
+
// Check for qty attributes
|
247 |
+
$scols = array_intersect($cols, $this->getStockCols());
|
248 |
+
$sql = "SELECT " . implode(",", $scols) . " FROM " . $this->tablename("cataloginventory_stock_item") .
|
249 |
+
" WHERE product_id=?";
|
250 |
+
$tdata = $this->selectAll($sql, array($params["product_id"]));
|
251 |
+
if (count($tdata) > 0)
|
252 |
+
{
|
253 |
+
$out = array_merge($out, $tdata[0]);
|
254 |
+
}
|
255 |
+
|
256 |
+
unset($idcodemap);
|
257 |
+
unset($bta);
|
258 |
+
return $out;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* returns mode
|
263 |
+
*/
|
264 |
+
public function getMode()
|
265 |
+
{
|
266 |
+
return $this->mode;
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Adds an extra attribute to process
|
271 |
+
* Useful for some plugins if generating attribute values that are not in initial scanned list
|
272 |
+
* @param unknown $attr attribute code
|
273 |
+
*/
|
274 |
+
public function addExtraAttribute($attr)
|
275 |
+
{
|
276 |
+
$attinfo = $this->attrinfo[$attr];
|
277 |
+
$this->_extra_attrs[$attinfo["backend_type"]]["data"][] = $attinfo;
|
278 |
+
}
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Returns the list of magento base product table columns
|
282 |
+
* @return multitype:
|
283 |
+
*/
|
284 |
+
public function getProdCols()
|
285 |
+
{
|
286 |
+
if (count($this->_prodcols) == 0)
|
287 |
+
{
|
288 |
+
$sql = 'DESCRIBE ' . $this->tablename('catalog_product_entity');
|
289 |
+
$rows = $this->selectAll($sql);
|
290 |
+
foreach ($rows as $row)
|
291 |
+
{
|
292 |
+
$this->_prodcols[] = $row['Field'];
|
293 |
+
}
|
294 |
+
}
|
295 |
+
return $this->_prodcols;
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Returns the list of magento product item stock info table columns
|
300 |
+
* @return multitype:
|
301 |
+
*/
|
302 |
+
public function getStockCols()
|
303 |
+
{
|
304 |
+
if (count($this->_stockcols) == 0)
|
305 |
+
{
|
306 |
+
$sql = 'DESCRIBE ' . $this->tablename('cataloginventory_stock_item');
|
307 |
+
$rows = $this->selectAll($sql);
|
308 |
+
foreach ($rows as $row)
|
309 |
+
{
|
310 |
+
$this->_stockcols[] = $row['Field'];
|
311 |
+
}
|
312 |
+
}
|
313 |
+
return $this->_stockcols;
|
314 |
+
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Initialize attribute infos to be used during import
|
318 |
+
*
|
319 |
+
* @param array $cols
|
320 |
+
* : array of attribute names
|
321 |
+
*/
|
322 |
+
public function checkRequired($cols)
|
323 |
+
{
|
324 |
+
$eav_attr = $this->tablename("eav_attribute");
|
325 |
+
$sql = "SELECT attribute_code FROM $eav_attr WHERE is_required=1
|
326 |
+
AND frontend_input!='' AND frontend_label!='' AND entity_type_id=?";
|
327 |
+
$required = $this->selectAll($sql, $this->prod_etype);
|
328 |
+
$reqcols = array();
|
329 |
+
foreach ($required as $line)
|
330 |
+
{
|
331 |
+
$reqcols[] = $line["attribute_code"];
|
332 |
+
}
|
333 |
+
$required = array_diff($reqcols, $cols);
|
334 |
+
return $required;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
*
|
339 |
+
* gets attribute metadata from DB and put it in attribute metadata caches
|
340 |
+
*
|
341 |
+
* @param array $cols
|
342 |
+
* list of attribute codes to get metadata from
|
343 |
+
* if in this list, some values are not attribute code, no metadata will be cached.
|
344 |
+
*/
|
345 |
+
public function initAttrInfos($cols)
|
346 |
+
{
|
347 |
+
if ($this->prod_etype == null)
|
348 |
+
{
|
349 |
+
// Find product entity type
|
350 |
+
$tname = $this->tablename("eav_entity_type");
|
351 |
+
$this->prod_etype = $this->selectone("SELECT entity_type_id FROM $tname WHERE entity_type_code=?",
|
352 |
+
"catalog_product", "entity_type_id");
|
353 |
+
}
|
354 |
+
|
355 |
+
// remove from candidates, those which we already know are not attributes
|
356 |
+
$candidates = array_diff($cols, $this->_notattribs);
|
357 |
+
// remove from candidates already known attributes
|
358 |
+
$candidates = array_diff($candidates, array_keys($this->attrinfo));
|
359 |
+
// now we have a count of "unknown columns" that are potential attributes
|
360 |
+
$toscan = array_values($candidates);
|
361 |
+
if (count($toscan) > 0)
|
362 |
+
{
|
363 |
+
// create statement parameter string ?,?,?.....
|
364 |
+
$qcolstr = $this->arr2values($toscan);
|
365 |
+
|
366 |
+
$tname = $this->tablename("eav_attribute");
|
367 |
+
if ($this->getMagentoVersion() != "1.3.x")
|
368 |
+
{
|
369 |
+
$extra = $this->tablename("catalog_eav_attribute");
|
370 |
+
// SQL for selecting attribute properties for all wanted attributes
|
371 |
+
$sql = "SELECT `$tname`.*,$extra.is_global,$extra.apply_to FROM `$tname`
|
372 |
+
LEFT JOIN $extra ON $tname.attribute_id=$extra.attribute_id
|
373 |
+
WHERE ($tname.attribute_code IN ($qcolstr)) AND (entity_type_id=?)";
|
374 |
+
}
|
375 |
+
else
|
376 |
+
{
|
377 |
+
$sql = "SELECT `$tname`.* FROM `$tname` WHERE ($tname.attribute_code IN ($qcolstr)) AND (entity_type_id=?)";
|
378 |
+
}
|
379 |
+
$toscan[] = $this->prod_etype;
|
380 |
+
$result = $this->selectAll($sql, $toscan);
|
381 |
+
|
382 |
+
$attrinfs = array();
|
383 |
+
// create an attribute code based array for the wanted columns
|
384 |
+
foreach ($result as $r)
|
385 |
+
{
|
386 |
+
$attrinfs[$r["attribute_code"]] = $r;
|
387 |
+
}
|
388 |
+
unset($result);
|
389 |
+
|
390 |
+
// create a backend_type based array for the wanted columns
|
391 |
+
// this will greatly help for optimizing inserts when creating attributes
|
392 |
+
// since eav_ model for attributes has one table per backend type
|
393 |
+
// skip already in attrinfo
|
394 |
+
foreach ($attrinfs as $k => $a)
|
395 |
+
{
|
396 |
+
if (!in_array($k, array_keys($this->attrinfo)))
|
397 |
+
{
|
398 |
+
$bt = $a["backend_type"];
|
399 |
+
if (!isset($this->attrbytype[$bt]))
|
400 |
+
{
|
401 |
+
$this->attrbytype[$bt] = array("data"=>array());
|
402 |
+
}
|
403 |
+
$this->attrbytype[$bt]["data"][] = $a;
|
404 |
+
$this->attrinfo[$k] = $a;
|
405 |
+
}
|
406 |
+
}
|
407 |
+
// now add a fast index in the attrbytype array to store id list in a comma separated form
|
408 |
+
foreach ($this->attrbytype as $bt => $test)
|
409 |
+
{
|
410 |
+
$idlist = array();
|
411 |
+
foreach ($test["data"] as $it)
|
412 |
+
{
|
413 |
+
$idlist[] = $it["attribute_id"];
|
414 |
+
}
|
415 |
+
$this->attrbytype[$bt]["ids"] = implode(",", $idlist);
|
416 |
+
}
|
417 |
+
// Important Bugfix, array_merge_recurvise to merge 2 dimenstional arrays.
|
418 |
+
$this->_notattribs = array_diff($cols, array_keys($this->attrinfo));
|
419 |
+
}
|
420 |
+
/*
|
421 |
+
* now we have 2 index arrays 1. $this->attrinfo which has the following structure: key : attribute_code value : attribute_properties 2. $this->attrbytype which has the following structure: key : attribute backend type value : array of : data => array of attribute_properties ,one for each attribute that match the backend type ids => list of attribute ids of the backend type
|
422 |
+
*/
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* retrieves attribute metadata
|
427 |
+
*
|
428 |
+
* @param string $attcode
|
429 |
+
* attribute code
|
430 |
+
* @param boolean $lookup
|
431 |
+
* if set, this will try to get info from DB otherwise will get from cache and may return null if not cached
|
432 |
+
* @return array attribute metadata info
|
433 |
+
*/
|
434 |
+
public function getAttrInfo($attcode, $lookup = true)
|
435 |
+
{
|
436 |
+
$attrinf = isset($this->attrinfo[$attcode]) ? $this->attrinfo[$attcode] : null;
|
437 |
+
if ($attrinf == null && $lookup)
|
438 |
+
{
|
439 |
+
$this->initAttrInfos(array($attcode));
|
440 |
+
}
|
441 |
+
if (isset($this->attrinfo[$attcode]))
|
442 |
+
{
|
443 |
+
$attrinf = $this->attrinfo[$attcode];
|
444 |
+
}
|
445 |
+
return $attrinf;
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
* retrieves attribute set id for a given attribute set name
|
450 |
+
*
|
451 |
+
* @param string $asname
|
452 |
+
* : attribute set name
|
453 |
+
*/
|
454 |
+
public function getAttributeSetId($asname)
|
455 |
+
{
|
456 |
+
if (!isset($this->attribute_sets[$asname]))
|
457 |
+
{
|
458 |
+
$tname = $this->tablename("eav_attribute_set");
|
459 |
+
$asid = $this->selectone(
|
460 |
+
"SELECT attribute_set_id FROM $tname WHERE attribute_set_name=? AND entity_type_id=?",
|
461 |
+
array($asname,$this->prod_etype), 'attribute_set_id');
|
462 |
+
$this->attribute_sets[$asname] = $asid;
|
463 |
+
}
|
464 |
+
return $this->attribute_sets[$asname];
|
465 |
+
}
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Retrieves product id for a given sku
|
469 |
+
*
|
470 |
+
* @param string $sku
|
471 |
+
* : sku of product to get id for
|
472 |
+
*/
|
473 |
+
public function getProductIds($sku)
|
474 |
+
{
|
475 |
+
$tname = $this->tablename("catalog_product_entity");
|
476 |
+
$result = $this->selectAll(
|
477 |
+
"SELECT sku,entity_id as pid,attribute_set_id as asid,type_id as type FROM $tname WHERE sku=?", $sku);
|
478 |
+
if (count($result) > 0)
|
479 |
+
{
|
480 |
+
$pids = $result[0];
|
481 |
+
$pids["__new"] = false;
|
482 |
+
return $pids;
|
483 |
+
}
|
484 |
+
else
|
485 |
+
{
|
486 |
+
return false;
|
487 |
+
}
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* creates a product in magento database
|
492 |
+
*
|
493 |
+
* @param array $item:
|
494 |
+
* product attributes as array with key:attribute name,value:attribute value
|
495 |
+
* @param int $asid
|
496 |
+
* : attribute set id for values
|
497 |
+
* @return : product id for newly created product
|
498 |
+
*/
|
499 |
+
public function createProduct($item, $asid)
|
500 |
+
{
|
501 |
+
// force item type if not exists
|
502 |
+
if (!isset($item["type"]))
|
503 |
+
{
|
504 |
+
$item["type"] = "simple";
|
505 |
+
}
|
506 |
+
$tname = $this->tablename('catalog_product_entity');
|
507 |
+
$item['type_id'] = $item['type'];
|
508 |
+
$item['attribute_set_id'] = $asid;
|
509 |
+
$item['entity_type_id'] = $this->prod_etype;
|
510 |
+
$item['created_at'] = strftime("%Y-%m-%d %H:%M:%S");
|
511 |
+
$item['updated_at'] = strftime("%Y-%m-%d %H:%M:%S");
|
512 |
+
$columns = array_intersect(array_keys($item), $this->getProdCols());
|
513 |
+
$values = $this->filterkvarr($item, $columns);
|
514 |
+
$sql = "INSERT INTO `$tname` (" . implode(",", $columns) . ") VALUES (" . $this->arr2values($columns) . ")";
|
515 |
+
$lastid = $this->insert($sql, array_values($values));
|
516 |
+
return $lastid;
|
517 |
+
}
|
518 |
+
|
519 |
+
/**
|
520 |
+
* Updateds product update time
|
521 |
+
*
|
522 |
+
* @param unknown_type $pid
|
523 |
+
* : entity_id of product
|
524 |
+
*/
|
525 |
+
public function touchProduct($pid)
|
526 |
+
{
|
527 |
+
$tname = $this->tablename('catalog_product_entity');
|
528 |
+
$this->update("UPDATE $tname SET updated_at=? WHERE entity_id=?", array(strftime("%Y-%m-%d %H:%M:%S"),$pid));
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Get Option id for select attributes based on value
|
533 |
+
*
|
534 |
+
* @param int $attid
|
535 |
+
* : attribute id to find option id from value
|
536 |
+
* @param mixed $optval
|
537 |
+
* : value to get option id for
|
538 |
+
* @return : array of lines (should be as much as values found),"opvd"=>option_id for value on store 0,"opvs" option id for value on current store
|
539 |
+
*/
|
540 |
+
public function getOptionsFromValues($attid, $store_id, $optvals)
|
541 |
+
{
|
542 |
+
$ovstr = substr(str_repeat("?,", count($optvals)), 0, -1);
|
543 |
+
$t1 = $this->tablename('eav_attribute_option');
|
544 |
+
$t2 = $this->tablename('eav_attribute_option_value');
|
545 |
+
$sql = "SELECT optvals.option_id as opvs,optvals.value FROM $t2 as optvals";
|
546 |
+
$sql .= " JOIN $t1 as opt ON opt.option_id=optvals.option_id AND opt.attribute_id=?";
|
547 |
+
$sql .= " WHERE optvals.store_id=? AND BINARY optvals.value IN ($ovstr)";
|
548 |
+
return $this->selectAll($sql, array_merge(array($attid,$store_id), $optvals));
|
549 |
+
}
|
550 |
+
|
551 |
+
/* create a new option entry for an attribute */
|
552 |
+
public function createOption($attid)
|
553 |
+
{
|
554 |
+
$t = $this->tablename('eav_attribute_option');
|
555 |
+
$optid = $this->insert("INSERT INTO $t (attribute_id) VALUES (?)", $attid);
|
556 |
+
return $optid;
|
557 |
+
}
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Creates a new option value for an option entry for a store
|
561 |
+
*
|
562 |
+
* @param int $optid
|
563 |
+
* : option entry id
|
564 |
+
* @param int $store_id
|
565 |
+
* : store id to add value for
|
566 |
+
* @param mixed $optval
|
567 |
+
* : new option value to add
|
568 |
+
* @return : option id for new created value
|
569 |
+
*/
|
570 |
+
public function createOptionValue($optid, $store_id, $optval)
|
571 |
+
{
|
572 |
+
$t = $this->tablename('eav_attribute_option_value');
|
573 |
+
$optval_id = $this->insert("INSERT INTO $t (option_id,store_id,value) VALUES (?,?,?)",
|
574 |
+
array($optid,$store_id,$optval));
|
575 |
+
return $optval_id;
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Returns option ids for a given store for a set of values (for select/multiselect attributes)
|
580 |
+
* - Create new entries if values do not exist
|
581 |
+
*
|
582 |
+
* @param unknown $attid
|
583 |
+
* attribute id
|
584 |
+
* @param unknown $storeid
|
585 |
+
* store id
|
586 |
+
* @param unknown $values
|
587 |
+
* value to create options for
|
588 |
+
* @return Ambigous <multitype:, unknown>
|
589 |
+
*/
|
590 |
+
public function getOptionIds($attid, $storeid, $values)
|
591 |
+
{
|
592 |
+
$optids = array();
|
593 |
+
$svalues = array();
|
594 |
+
$avalues = array();
|
595 |
+
|
596 |
+
// Checking if we want to "translate" values existing in admin
|
597 |
+
foreach ($values as $val)
|
598 |
+
{
|
599 |
+
// if we have a reference value in admin
|
600 |
+
if (preg_match("|^(.*)::\[(.*)\]$|", $val, $matches))
|
601 |
+
{
|
602 |
+
// add translated value in store value array
|
603 |
+
$svalues[] = $matches[2];
|
604 |
+
// add admin value in admin value array
|
605 |
+
$avalues[] = $matches[1];
|
606 |
+
}
|
607 |
+
else
|
608 |
+
{
|
609 |
+
// if no translation, add values in both admin & current store array
|
610 |
+
$svalues[] = $val;
|
611 |
+
$avalues[] = $val;
|
612 |
+
}
|
613 |
+
}
|
614 |
+
|
615 |
+
// get Existing options for admin values & current attribute (store = 0)
|
616 |
+
$existing = $this->getOptionsFromValues($attid, 0, $avalues);
|
617 |
+
$exvals = array();
|
618 |
+
foreach ($existing as $optdesc)
|
619 |
+
{
|
620 |
+
$exvals[] = $optdesc["value"];
|
621 |
+
}
|
622 |
+
// new option values are option values that are in "admin" option values array & not in existing admin option values array
|
623 |
+
$new = array_merge(array_diff($avalues, $exvals));
|
624 |
+
|
625 |
+
// if we are on admin option values
|
626 |
+
if ($storeid == 0)
|
627 |
+
{
|
628 |
+
// for each new option value to create in admin
|
629 |
+
foreach ($new as $nval)
|
630 |
+
{
|
631 |
+
// create a new option with value
|
632 |
+
$row = array("opvs"=>$this->createOption($attid),"value"=>$nval);
|
633 |
+
// add an option value for current store
|
634 |
+
$this->createOptionValue($row["opvs"], $storeid, $nval);
|
635 |
+
// add this value to existing pool
|
636 |
+
$existing[] = $row;
|
637 |
+
}
|
638 |
+
// put this value in the option id cache
|
639 |
+
$this->cacheOptIds($attid, $existing);
|
640 |
+
}
|
641 |
+
else
|
642 |
+
// we are on a specific store , not admin
|
643 |
+
{
|
644 |
+
// get cached option ids for current attribute
|
645 |
+
$brows = $this->getCachedOptIds($attid);
|
646 |
+
// if none already exist
|
647 |
+
if (count($brows) == 0)
|
648 |
+
{
|
649 |
+
// try to find options matching given values (admin)
|
650 |
+
$existing = $this->getOptionsFromValues($attid, 0, $avalues);
|
651 |
+
// find non existing ones
|
652 |
+
$new = array_merge(array_diff($avalues, $exvals));
|
653 |
+
// for each new option value to create in admin
|
654 |
+
foreach ($new as $nval)
|
655 |
+
{
|
656 |
+
// create option
|
657 |
+
$row = array("opvs"=>$this->createOption($attid),"value"=>$nval);
|
658 |
+
// create option value for current store
|
659 |
+
$this->createOptionValue($row["opvs"], $storeid, $nval);
|
660 |
+
// add to exisiting pool
|
661 |
+
$existing[] = $row;
|
662 |
+
}
|
663 |
+
// add existing pool to cache
|
664 |
+
$this->cacheOptIds($attid, $existing);
|
665 |
+
// return cached option ids
|
666 |
+
$brows = $this->getCachedOptIds($attid);
|
667 |
+
}
|
668 |
+
// for all existing
|
669 |
+
foreach ($existing as $ex)
|
670 |
+
{
|
671 |
+
// remove from processing array
|
672 |
+
array_shift($brows);
|
673 |
+
}
|
674 |
+
// for all new
|
675 |
+
$cnew = count($new);
|
676 |
+
for ($i = 0; $i < $cnew; $i++)
|
677 |
+
{
|
678 |
+
$row = $brows[$i];
|
679 |
+
// if we don't have option
|
680 |
+
if (!isset($row["opvs"]))
|
681 |
+
{
|
682 |
+
// create option
|
683 |
+
$row["opvs"] = $this->createOption($attid);
|
684 |
+
// create option
|
685 |
+
$this->createOptionValue($row["opvs"], 0, $new[$i]);
|
686 |
+
}
|
687 |
+
// create option value for store
|
688 |
+
$this->createOptionValue($row["opvs"], $storeid, $new[$i]);
|
689 |
+
// add to existing pool
|
690 |
+
$existing[] = $row;
|
691 |
+
}
|
692 |
+
}
|
693 |
+
|
694 |
+
$optids = array();
|
695 |
+
// now all options are in existing & values are created
|
696 |
+
// builf and array with all option ids
|
697 |
+
foreach ($existing as $row)
|
698 |
+
{
|
699 |
+
$optids[] = $row["opvs"];
|
700 |
+
}
|
701 |
+
// remove existing
|
702 |
+
unset($existing);
|
703 |
+
// remove existing values
|
704 |
+
unset($exvals);
|
705 |
+
// remove temp array
|
706 |
+
unset($brows);
|
707 |
+
// return option ids
|
708 |
+
return $optids;
|
709 |
+
}
|
710 |
+
|
711 |
+
/**
|
712 |
+
* Adds a new option definition row in the cache
|
713 |
+
*
|
714 |
+
* @param unknown $attid
|
715 |
+
* attribute id
|
716 |
+
* @param unknown $row
|
717 |
+
* option definition
|
718 |
+
*/
|
719 |
+
public function cacheOptIds($attid, $row)
|
720 |
+
{
|
721 |
+
$this->_optidcache[$attid] = $row;
|
722 |
+
}
|
723 |
+
|
724 |
+
/**
|
725 |
+
* return cached option definition rows for a given attribute id
|
726 |
+
*
|
727 |
+
* @param unknown $attid
|
728 |
+
* attribute id
|
729 |
+
* @return NULL or option definition rows found
|
730 |
+
*/
|
731 |
+
public function getCachedOptIds($attid)
|
732 |
+
{
|
733 |
+
if (isset($this->_optidcache[$attid]))
|
734 |
+
{
|
735 |
+
return $this->_optidcache[$attid];
|
736 |
+
}
|
737 |
+
else
|
738 |
+
{
|
739 |
+
return null;
|
740 |
+
}
|
741 |
+
}
|
742 |
+
|
743 |
+
/**
|
744 |
+
* returns tax class id for a given tax class value
|
745 |
+
*
|
746 |
+
* @param $tcvalue :
|
747 |
+
* tax class value
|
748 |
+
*/
|
749 |
+
public function getTaxClassId($tcvalue)
|
750 |
+
{
|
751 |
+
// allow for ids in tax_class_id column , extending support
|
752 |
+
if (is_numeric($tcvalue))
|
753 |
+
{
|
754 |
+
$txid = $tcvalue;
|
755 |
+
}
|
756 |
+
else
|
757 |
+
{
|
758 |
+
$t = $this->tablename('tax_class');
|
759 |
+
$txid = $this->selectone("SELECT class_id FROM $t WHERE class_name=?", array($tcvalue), "class_id");
|
760 |
+
}
|
761 |
+
// bugfix for tax class id, if not found set it to none
|
762 |
+
if (!isset($txid))
|
763 |
+
{
|
764 |
+
$txid = 0;
|
765 |
+
}
|
766 |
+
return $txid;
|
767 |
+
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* parses a calculated value with tokens like {{ }} or {}
|
771 |
+
*
|
772 |
+
* @param unknown $pvalue
|
773 |
+
* parsing value
|
774 |
+
* @param unknown $item
|
775 |
+
* item for resolving {item.xxx} tokens
|
776 |
+
* @param unknown $params
|
777 |
+
* params for resolving {meta.xxx} tokens
|
778 |
+
* @return string resolved value
|
779 |
+
*/
|
780 |
+
public function parseCalculatedValue($pvalue, $item, $params)
|
781 |
+
{
|
782 |
+
$pvalue = Magmi_ValueParser::parseValue($pvalue, array("item"=>$item,"meta"=>$params));
|
783 |
+
return $pvalue;
|
784 |
+
}
|
785 |
+
|
786 |
+
/**
|
787 |
+
* Return affected store ids for a given item given an attribute scope
|
788 |
+
*
|
789 |
+
* @param array $item
|
790 |
+
* : item to get store for scope
|
791 |
+
* @param string $scope
|
792 |
+
* : scope to get stores from.
|
793 |
+
*/
|
794 |
+
public function getItemStoreIds($item, $scope = 0)
|
795 |
+
{
|
796 |
+
if (!isset($item['store']))
|
797 |
+
{
|
798 |
+
$item['store'] = "admin";
|
799 |
+
}
|
800 |
+
switch ($scope)
|
801 |
+
{
|
802 |
+
// global scope
|
803 |
+
case 1:
|
804 |
+
$bstore_ids = $this->getStoreIdsForStoreScope("admin");
|
805 |
+
break;
|
806 |
+
// store scope
|
807 |
+
case 0:
|
808 |
+
$bstore_ids = $this->getStoreIdsForStoreScope($item["store"]);
|
809 |
+
break;
|
810 |
+
// website scope
|
811 |
+
case 2:
|
812 |
+
$bstore_ids = $this->getStoreIdsForWebsiteScope($item["store"]);
|
813 |
+
break;
|
814 |
+
}
|
815 |
+
|
816 |
+
$itemstores = array_unique(array_merge($this->_dstore, $bstore_ids));
|
817 |
+
sort($itemstores);
|
818 |
+
return $itemstores;
|
819 |
+
}
|
820 |
+
|
821 |
+
/**
|
822 |
+
* Create product attribute from values for a given product id
|
823 |
+
*
|
824 |
+
* @param $pid :
|
825 |
+
* product id to create attribute values for
|
826 |
+
* @param $item :
|
827 |
+
* attribute values in an array indexed by attribute_code
|
828 |
+
*/
|
829 |
+
public function createAttributes($pid, &$item, $attmap, $isnew, $itemids)
|
830 |
+
{
|
831 |
+
/**
|
832 |
+
* get all store ids
|
833 |
+
*/
|
834 |
+
$this->_extra_attrs = array();
|
835 |
+
/* now is the interesring part */
|
836 |
+
/* iterate on attribute backend type index */
|
837 |
+
foreach ($attmap as $tp => $a)
|
838 |
+
{
|
839 |
+
/* for static types, do not insert into attribute tables */
|
840 |
+
if ($tp == "static")
|
841 |
+
{
|
842 |
+
continue;
|
843 |
+
}
|
844 |
+
|
845 |
+
// table name for backend type data
|
846 |
+
$cpet = $this->tablename("catalog_product_entity_$tp");
|
847 |
+
// data table for inserts
|
848 |
+
$data = array();
|
849 |
+
// inserts to perform on backend type eav
|
850 |
+
$inserts = array();
|
851 |
+
// deletes to perform on backend type eav
|
852 |
+
$deletes = array();
|
853 |
+
|
854 |
+
// use reflection to find special handlers
|
855 |
+
$typehandler = "handle" . ucfirst($tp) . "Attribute";
|
856 |
+
// iterate on all attribute descriptions for the given backend type
|
857 |
+
foreach ($a["data"] as $attrdesc)
|
858 |
+
{
|
859 |
+
// check item type is compatible with attribute apply_to
|
860 |
+
if ($attrdesc["apply_to"] != null &&
|
861 |
+
strpos($attrdesc["apply_to"], strtolower($itemids["type"])) === false)
|
862 |
+
{
|
863 |
+
// do not handle attribute if it does not apply to the product type
|
864 |
+
continue;
|
865 |
+
}
|
866 |
+
// get attribute id
|
867 |
+
$attid = $attrdesc["attribute_id"];
|
868 |
+
// get attribute value in the item to insert based on code
|
869 |
+
$atthandler = "handle" . ucfirst($attrdesc["attribute_code"]) . "Attribute";
|
870 |
+
$attrcode = $attrdesc["attribute_code"];
|
871 |
+
// if the attribute code is no more in item (plugins may have come into the way), continue
|
872 |
+
if (!in_array($attrcode, array_keys($item)))
|
873 |
+
{
|
874 |
+
continue;
|
875 |
+
}
|
876 |
+
// get the item value
|
877 |
+
$ivalue = $item[$attrcode];
|
878 |
+
// get item store id for the current attribute
|
879 |
+
$store_ids = $this->getItemStoreIds($item, $attrdesc["is_global"]);
|
880 |
+
|
881 |
+
// do not handle empty generic int values in create mode
|
882 |
+
if ($ivalue == "" && $this->mode != "update" && $tp == "int")
|
883 |
+
{
|
884 |
+
continue;
|
885 |
+
}
|
886 |
+
// for all store ids
|
887 |
+
foreach ($store_ids as $store_id)
|
888 |
+
{
|
889 |
+
|
890 |
+
// base output value to be inserted = base source value
|
891 |
+
$ovalue = $ivalue;
|
892 |
+
// check for attribute handlers for current attribute
|
893 |
+
foreach ($this->_attributehandlers as $match => $ah)
|
894 |
+
{
|
895 |
+
$matchinfo = explode(":", $match);
|
896 |
+
$mtype = $matchinfo[0];
|
897 |
+
$mtest = $matchinfo[1];
|
898 |
+
unset($matchinfo);
|
899 |
+
unset($hvalue);
|
900 |
+
if (preg_match("/$mtest/", $attrdesc[$mtype]))
|
901 |
+
{
|
902 |
+
// if there is a specific handler for attribute, use it
|
903 |
+
if (method_exists($ah, $atthandler))
|
904 |
+
{
|
905 |
+
$hvalue = $ah->$atthandler($pid, $item, $store_id, $attrcode, $attrdesc, $ivalue);
|
906 |
+
}
|
907 |
+
else
|
908 |
+
// use generic type attribute
|
909 |
+
if (method_exists($ah, $typehandler))
|
910 |
+
{
|
911 |
+
$hvalue = $ah->$typehandler($pid, $item, $store_id, $attrcode, $attrdesc, $ivalue);
|
912 |
+
}
|
913 |
+
// if handlers returned a value that is not "__MAGMI_UNHANDLED__" , we have our output value
|
914 |
+
if (isset($hvalue) && $hvalue != "__MAGMI_UNHANDLED__")
|
915 |
+
{
|
916 |
+
$ovalue = $hvalue;
|
917 |
+
break;
|
918 |
+
}
|
919 |
+
}
|
920 |
+
}
|
921 |
+
// if __MAGMI_UNHANDLED__ ,don't insert anything
|
922 |
+
if ($ovalue == "__MAGMI_UNHANDLED__")
|
923 |
+
{
|
924 |
+
$ovalue = false;
|
925 |
+
}
|
926 |
+
|
927 |
+
// force null value => to delete
|
928 |
+
if ($ovalue == "__NULL__")
|
929 |
+
{
|
930 |
+
$ovalue = "__MAGMI_DELETE__";
|
931 |
+
}
|
932 |
+
|
933 |
+
// if handled value is a "DELETE"
|
934 |
+
if ($ovalue == "__MAGMI_DELETE__")
|
935 |
+
{
|
936 |
+
$deletes[] = $attid;
|
937 |
+
// do not handle value in insert
|
938 |
+
$ovalue = null;
|
939 |
+
}
|
940 |
+
// if we have something to do with this value
|
941 |
+
if ($ovalue !== false && $ovalue != null)
|
942 |
+
{
|
943 |
+
|
944 |
+
$data[] = $this->prod_etype;
|
945 |
+
$data[] = $attid;
|
946 |
+
$data[] = $store_id;
|
947 |
+
$data[] = $pid;
|
948 |
+
$data[] = $ovalue;
|
949 |
+
$insstr = "(?,?,?,?,?)";
|
950 |
+
$inserts[] = $insstr;
|
951 |
+
}
|
952 |
+
|
953 |
+
// if one of the store in the list is admin
|
954 |
+
if ($store_id == 0)
|
955 |
+
{
|
956 |
+
$sids = $store_ids;
|
957 |
+
// remove all values bound to the other stores for this attribute,so that they default to "use admin value"
|
958 |
+
array_shift($sids);
|
959 |
+
if (count($sids) > 0)
|
960 |
+
{
|
961 |
+
$sidlist = implode(",", $sids);
|
962 |
+
$ddata = array($this->prod_etype,$attid,$pid);
|
963 |
+
$sql = "DELETE FROM $cpet WHERE entity_type_id=? AND attribute_id=? AND store_id IN ($sidlist) AND entity_id=?";
|
964 |
+
$this->delete($sql, $ddata);
|
965 |
+
unset($ddata);
|
966 |
+
}
|
967 |
+
unset($sids);
|
968 |
+
break;
|
969 |
+
}
|
970 |
+
}
|
971 |
+
}
|
972 |
+
//if we have values to insert or update
|
973 |
+
if (!empty($inserts))
|
974 |
+
{
|
975 |
+
// now perform insert for all values of the the current backend type in one
|
976 |
+
// single insert
|
977 |
+
$sql = "INSERT INTO $cpet
|
978 |
+
(`entity_type_id`, `attribute_id`, `store_id`, `entity_id`, `value`)
|
979 |
+
VALUES ";
|
980 |
+
$sql .= implode(",", $inserts);
|
981 |
+
// this one taken from mysql log analysis of magento import
|
982 |
+
// smart one :)
|
983 |
+
$sql .= " ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)";
|
984 |
+
$this->insert($sql, $data);
|
985 |
+
}
|
986 |
+
|
987 |
+
//if we have values to delete
|
988 |
+
if (!empty($deletes))
|
989 |
+
{
|
990 |
+
$sidlist = implode(",", $store_ids);
|
991 |
+
$attidlist = implode(",", $deletes);
|
992 |
+
$sql = "DELETE FROM $cpet WHERE entity_type_id=? AND attribute_id IN ($attidlist) AND store_id IN ($sidlist) AND entity_id=?";
|
993 |
+
$this->delete($sql, array($this->prod_etype,$pid));
|
994 |
+
}
|
995 |
+
//if no values inserted or deleted on a new item, we have a problem
|
996 |
+
if (empty($deletes) && empty($inserts) && $isnew)
|
997 |
+
{
|
998 |
+
//in fact we have a problem if we have a really new item
|
999 |
+
if (!$this->_same)
|
1000 |
+
{
|
1001 |
+
$this->log("No $tp Attributes created for sku " . $item["sku"], "warning");
|
1002 |
+
}
|
1003 |
+
}
|
1004 |
+
//memory release
|
1005 |
+
unset($store_ids);
|
1006 |
+
unset($data);
|
1007 |
+
unset($inserts);
|
1008 |
+
unset($deletes);
|
1009 |
+
}
|
1010 |
+
//if new attributes are to be processed, return them
|
1011 |
+
return $this->_extra_attrs;
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
/**
|
1015 |
+
* update product stock
|
1016 |
+
*
|
1017 |
+
* @param int $pid
|
1018 |
+
* : product id
|
1019 |
+
* @param array $item
|
1020 |
+
* : attribute values for product indexed by attribute_code
|
1021 |
+
*/
|
1022 |
+
public function updateStock($pid, $item, $isnew)
|
1023 |
+
{
|
1024 |
+
$scols = $this->getStockCols();
|
1025 |
+
// ake only stock columns that are in item
|
1026 |
+
$itstockcols = array_intersect(array_keys($item), $scols);
|
1027 |
+
// o stock columns set, item exists, no stock update needed.
|
1028 |
+
if (count($itstockcols) == 0 && !$isnew)
|
1029 |
+
{
|
1030 |
+
return;
|
1031 |
+
}
|
1032 |
+
$csit = $this->tablename("cataloginventory_stock_item");
|
1033 |
+
$css = $this->tablename("cataloginventory_stock_status");
|
1034 |
+
// alculate is_in_stock flag
|
1035 |
+
if (isset($item["qty"]))
|
1036 |
+
{
|
1037 |
+
if (!isset($item["manage_stock"]))
|
1038 |
+
{
|
1039 |
+
$item["manage_stock"] = 1;
|
1040 |
+
$item["use_config_manage_stock"] = 0;
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
$mqty = (isset($item["min_qty"]) ? $item["min_qty"] : 0);
|
1044 |
+
$is_in_stock = isset($item["is_in_stock"]) ? $item["is_in_stock"] : ($item["qty"] > $mqty ? 1 : 0);
|
1045 |
+
$item["is_in_stock"] = $is_in_stock;
|
1046 |
+
}
|
1047 |
+
// ake only stock columns that are in item after item update
|
1048 |
+
$common = array_intersect(array_keys($item), $scols);
|
1049 |
+
|
1050 |
+
// reate stock item line if needed
|
1051 |
+
$stock_id = (isset($item["stock_id"]) ? $item["stock_id"] : 1);
|
1052 |
+
$sql = "INSERT IGNORE INTO `$csit` (product_id,stock_id) VALUES (?,?)";
|
1053 |
+
$this->insert($sql, array($pid,$stock_id));
|
1054 |
+
|
1055 |
+
if (count($common) > 0)
|
1056 |
+
{
|
1057 |
+
$cols = $this->arr2columns($common);
|
1058 |
+
$stockvals = $this->filterkvarr($item, $common);
|
1059 |
+
|
1060 |
+
// ill with values
|
1061 |
+
$svstr = $this->arr2update($stockvals);
|
1062 |
+
if (isset($item["qty"]) && $item["qty"] != "")
|
1063 |
+
{
|
1064 |
+
$relqty = NULL;
|
1065 |
+
|
1066 |
+
// if magmi_qty_absolute flag is not set, then use standard "relative" qty parsing.
|
1067 |
+
if (!isset($item["magmi_qty_absolute"]) || $item["magmi_qty_absolute"] == 0)
|
1068 |
+
{
|
1069 |
+
// test for relative qty
|
1070 |
+
if ($item["qty"][0] == "+" || $item["qty"][0] == "-")
|
1071 |
+
{
|
1072 |
+
$relqty = getRelative($item["qty"]);
|
1073 |
+
}
|
1074 |
+
}
|
1075 |
+
// if relative qty
|
1076 |
+
if ($relqty != NULL)
|
1077 |
+
{
|
1078 |
+
// update UPDATE statement value affectation
|
1079 |
+
$svstr = preg_replace("/(^|,)qty=\?/", "$1qty=qty$relqty?", $svstr);
|
1080 |
+
$stockvals["qty"] = $item["qty"];
|
1081 |
+
$svstr = str_replace("is_in_stock=?", "is_in_stock=(qty>min_qty)", $svstr);
|
1082 |
+
unset($stockvals["is_in_stock"]);
|
1083 |
+
}
|
1084 |
+
}
|
1085 |
+
$sql = "UPDATE `$csit` SET $svstr WHERE product_id=? AND stock_id=?";
|
1086 |
+
$this->update($sql, array_merge(array_values($stockvals), array($pid,$stock_id)));
|
1087 |
+
}
|
1088 |
+
|
1089 |
+
$data = array();
|
1090 |
+
$wsids = $this->getItemWebsites($item);
|
1091 |
+
$csscols = array("website_id","product_id","stock_id","qty","stock_status");
|
1092 |
+
$cssvals = $this->filterkvarr($item, $csscols);
|
1093 |
+
$stock_id = (isset($cssvals["stock_id"]) ? $cssvals["stock_id"] : 1);
|
1094 |
+
$stock_status = (isset($cssvals["stock_status"]) ? $cssvals["stock_status"] : 1);
|
1095 |
+
// new auto synchro on lat inserted stock item values for stock status.
|
1096 |
+
// also works for multiple stock ids.
|
1097 |
+
|
1098 |
+
// [start] exanto.de - this does not work inside a DB transaction bc cataloginventory_stock_item is not written yet on fresh imports
|
1099 |
+
/*
|
1100 |
+
* :ORG: $sql="INSERT INTO `$css` SELECT csit.product_id,ws.website_id,cis.stock_id,csit.qty,? as stock_status FROM `$csit` as csit JOIN ".$this->tablename("core_website")." as ws ON ws.website_id IN (".$this->arr2values($wsids).") JOIN ".$this->tablename("cataloginventory_stock")." as cis ON cis.stock_id=? WHERE product_id=? ON DUPLICATE KEY UPDATE stock_status=VALUES(`stock_status`),qty=VALUES(`qty`)";
|
1101 |
+
*/
|
1102 |
+
// Fixed version
|
1103 |
+
$cpe = $this->tablename("catalog_product_entity");
|
1104 |
+
// Fix , $stockvals is already a mix between item keys & stock table keys.
|
1105 |
+
$qty = isset($stockvals['qty']) ? $stockvals['qty'] : 0;
|
1106 |
+
if (!$qty)
|
1107 |
+
{
|
1108 |
+
$qty = 0;
|
1109 |
+
}
|
1110 |
+
$sql = "INSERT INTO `$css` SELECT '$pid' as product_id,ws.website_id,cis.stock_id,'$qty' as qty,? as stock_status
|
1111 |
+
FROM `$cpe` as cpe
|
1112 |
+
JOIN " .
|
1113 |
+
$this->tablename("core_website") . " as ws ON ws.website_id IN (" . $this->arr2values($wsids) . ")
|
1114 |
+
JOIN " .
|
1115 |
+
$this->tablename("cataloginventory_stock") . " as cis ON cis.stock_id=?
|
1116 |
+
WHERE cpe.entity_id=?
|
1117 |
+
ON DUPLICATE KEY UPDATE stock_status=VALUES(`stock_status`),qty=VALUES(`qty`)";
|
1118 |
+
// [ end ] exanto.de - this does not work inside a DB transaction bc cataloginventory_stock_item is not written yet on fresh imports
|
1119 |
+
|
1120 |
+
$data[] = $stock_status;
|
1121 |
+
$data = array_merge($data, $wsids);
|
1122 |
+
$data[] = $stock_id;
|
1123 |
+
$data[] = $pid;
|
1124 |
+
$this->insert($sql, $data);
|
1125 |
+
unset($data);
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
/**
|
1129 |
+
* assign categories for a given product id from values
|
1130 |
+
* categories should already be created & csv values should be as the ones
|
1131 |
+
* given in the magento export (ie: comma separated ids, minus 1,2)
|
1132 |
+
*
|
1133 |
+
* @param int $pid
|
1134 |
+
* : product id
|
1135 |
+
* @param array $item
|
1136 |
+
* : attribute values for product indexed by attribute_code
|
1137 |
+
*/
|
1138 |
+
public function assignCategories($pid, $item)
|
1139 |
+
{
|
1140 |
+
$cce = $this->tablename("catalog_category_entity");
|
1141 |
+
$ccpt = $this->tablename("catalog_category_product");
|
1142 |
+
// andle assignment reset
|
1143 |
+
if (!isset($item["category_reset"]) || $item["category_reset"] == 1)
|
1144 |
+
{
|
1145 |
+
$sql = "DELETE $ccpt.*
|
1146 |
+
FROM $ccpt
|
1147 |
+
JOIN $cce ON $cce.entity_id=$ccpt.category_id
|
1148 |
+
WHERE product_id=?";
|
1149 |
+
$this->delete($sql, $pid);
|
1150 |
+
}
|
1151 |
+
|
1152 |
+
$inserts = array();
|
1153 |
+
$data = array();
|
1154 |
+
$cdata = array();
|
1155 |
+
$ddata = array();
|
1156 |
+
$cpos = array();
|
1157 |
+
$catids = csl2arr($item["category_ids"]);
|
1158 |
+
|
1159 |
+
// find positive category assignments
|
1160 |
+
|
1161 |
+
foreach ($catids as $catdef)
|
1162 |
+
{
|
1163 |
+
$a = explode("::", $catdef);
|
1164 |
+
$catid = $a[0];
|
1165 |
+
$catpos = (count($a) > 1 ? $a[1] : "0");
|
1166 |
+
$rel = getRelative($catid);
|
1167 |
+
if ($rel == "-")
|
1168 |
+
{
|
1169 |
+
$ddata[] = $catid;
|
1170 |
+
}
|
1171 |
+
else
|
1172 |
+
{
|
1173 |
+
$cdata[$catid] = $catpos;
|
1174 |
+
}
|
1175 |
+
}
|
1176 |
+
|
1177 |
+
// get all "real ids"
|
1178 |
+
if (count($cdata) > 0)
|
1179 |
+
{
|
1180 |
+
$scatids = array_keys($cdata);
|
1181 |
+
$rcatids = $this->selectAll(
|
1182 |
+
"SELECT cce.entity_id as id FROM $cce as cce WHERE cce.entity_id IN (" . $this->arr2values($scatids) .
|
1183 |
+
")", $scatids);
|
1184 |
+
$vcatids = array();
|
1185 |
+
foreach ($rcatids as $rcatrow)
|
1186 |
+
{
|
1187 |
+
$vcatids[] = $rcatrow['id'];
|
1188 |
+
}
|
1189 |
+
// now get the diff
|
1190 |
+
$diff = array_diff(array_keys($cdata), $vcatids);
|
1191 |
+
$cdiff = count($diff);
|
1192 |
+
// if there are some, warning
|
1193 |
+
if ($cdiff > 0)
|
1194 |
+
{
|
1195 |
+
$this->log('Invalid category ids found for sku ' . $item['sku'] . ":" . implode(",", $diff), "warning");
|
1196 |
+
// remove invalid category entries
|
1197 |
+
for ($i = 0; $i < $cdiff; $i++)
|
1198 |
+
{
|
1199 |
+
unset($cdata[$diff[$i]]);
|
1200 |
+
}
|
1201 |
+
}
|
1202 |
+
|
1203 |
+
// ow we have verified ids
|
1204 |
+
foreach ($cdata as $catid => $catpos)
|
1205 |
+
{
|
1206 |
+
$inserts[] = "(?,?,?)";
|
1207 |
+
$data[] = $catid;
|
1208 |
+
$data[] = $pid;
|
1209 |
+
$data[] = $catpos;
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
|
1213 |
+
// eform deletion of removed category affectation
|
1214 |
+
if (count($ddata) > 0)
|
1215 |
+
{
|
1216 |
+
$sql = "DELETE FROM $ccpt WHERE category_id IN (" . $this->arr2values($ddata) . ") AND product_id=?";
|
1217 |
+
$ddata[] = $pid;
|
1218 |
+
$this->delete($sql, $ddata);
|
1219 |
+
unset($ddata);
|
1220 |
+
}
|
1221 |
+
|
1222 |
+
// reate new category assignment for products, if multi store with repeated ids
|
1223 |
+
// gnore duplicates
|
1224 |
+
if (count($inserts) > 0)
|
1225 |
+
{
|
1226 |
+
$sql = "INSERT INTO $ccpt (`category_id`,`product_id`,`position`)
|
1227 |
+
VALUES ";
|
1228 |
+
$sql .= implode(",", $inserts);
|
1229 |
+
$sql .= " ON DUPLICATE KEY UPDATE position=VALUES(`position`)";
|
1230 |
+
$this->insert($sql, $data);
|
1231 |
+
unset($data);
|
1232 |
+
}
|
1233 |
+
unset($deletes);
|
1234 |
+
unset($inserts);
|
1235 |
+
}
|
1236 |
+
|
1237 |
+
public function getItemWebsites($item, $default = false)
|
1238 |
+
{
|
1239 |
+
// support for websites column if set
|
1240 |
+
if (!empty($item["websites"]))
|
1241 |
+
{
|
1242 |
+
if (!isset($this->_wsids[$item["websites"]]))
|
1243 |
+
{
|
1244 |
+
$this->_wsids[$item["websites"]] = array();
|
1245 |
+
|
1246 |
+
$cws = $this->tablename("core_website");
|
1247 |
+
$wscodes = csl2arr($item["websites"]);
|
1248 |
+
$qcolstr = $this->arr2values($wscodes);
|
1249 |
+
$rows = $this->selectAll("SELECT website_id FROM $cws WHERE code IN ($qcolstr)", $wscodes);
|
1250 |
+
foreach ($rows as $row)
|
1251 |
+
{
|
1252 |
+
$this->_wsids[$item["websites"]][] = $row['website_id'];
|
1253 |
+
}
|
1254 |
+
}
|
1255 |
+
return $this->_wsids[$item["websites"]];
|
1256 |
+
}
|
1257 |
+
|
1258 |
+
if (!isset($item['store']))
|
1259 |
+
{
|
1260 |
+
$item['store'] = "admin";
|
1261 |
+
}
|
1262 |
+
$k = $item["store"];
|
1263 |
+
|
1264 |
+
if (!isset($this->_wsids[$k]))
|
1265 |
+
{
|
1266 |
+
$this->_wsids[$k] = array();
|
1267 |
+
$cs = $this->tablename("core_store");
|
1268 |
+
if (trim($k) != "admin")
|
1269 |
+
{
|
1270 |
+
$scodes = csl2arr($k);
|
1271 |
+
$qcolstr = $this->arr2values($scodes);
|
1272 |
+
$rows = $this->selectAll(
|
1273 |
+
"SELECT website_id FROM $cs WHERE code IN ($qcolstr) AND store_id!=0 GROUP BY website_id", $scodes);
|
1274 |
+
}
|
1275 |
+
else
|
1276 |
+
{
|
1277 |
+
$rows = $this->selectAll("SELECT website_id FROM $cs WHERE store_id!=0 GROUP BY website_id ");
|
1278 |
+
}
|
1279 |
+
foreach ($rows as $row)
|
1280 |
+
{
|
1281 |
+
$this->_wsids[$k][] = $row['website_id'];
|
1282 |
+
}
|
1283 |
+
}
|
1284 |
+
return $this->_wsids[$k];
|
1285 |
+
}
|
1286 |
+
|
1287 |
+
/**
|
1288 |
+
* set website of product if not exists
|
1289 |
+
*
|
1290 |
+
* @param int $pid
|
1291 |
+
* : product id
|
1292 |
+
* @param array $item
|
1293 |
+
* : attribute values for product indexed by attribute_code
|
1294 |
+
*/
|
1295 |
+
public function updateWebSites($pid, $item)
|
1296 |
+
{
|
1297 |
+
$wsids = $this->getItemWebsites($item);
|
1298 |
+
$qcolstr = $this->arr2values($wsids);
|
1299 |
+
$cpst = $this->tablename("catalog_product_website");
|
1300 |
+
$cws = $this->tablename("core_website");
|
1301 |
+
// associate product with all websites in a single multi insert (use ignore to avoid duplicates)
|
1302 |
+
$ddata = array($pid);
|
1303 |
+
$sql = "DELETE FROM `$cpst` WHERE product_id=?";
|
1304 |
+
$this->delete($sql, $ddata);
|
1305 |
+
$sql = "INSERT INTO `$cpst` (`product_id`, `website_id`) SELECT ?,website_id FROM $cws WHERE website_id IN ($qcolstr)";
|
1306 |
+
$this->insert($sql, array_merge(array($pid), $wsids));
|
1307 |
+
}
|
1308 |
+
|
1309 |
+
public function clearOptCache()
|
1310 |
+
{
|
1311 |
+
unset($this->_optidcache);
|
1312 |
+
$this->_optidcache = array();
|
1313 |
+
}
|
1314 |
+
|
1315 |
+
public function onNewSku($sku, $existing)
|
1316 |
+
{
|
1317 |
+
$this->clearOptCache();
|
1318 |
+
// only assign values to store 0 by default in create mode for new sku
|
1319 |
+
// for store related options
|
1320 |
+
if (!$existing)
|
1321 |
+
{
|
1322 |
+
$this->_dstore = array(0);
|
1323 |
+
}
|
1324 |
+
else
|
1325 |
+
{
|
1326 |
+
$this->_dstore = array();
|
1327 |
+
}
|
1328 |
+
$this->_same = false;
|
1329 |
+
}
|
1330 |
+
|
1331 |
+
public function onSameSku($sku)
|
1332 |
+
{
|
1333 |
+
unset($this->_dstore);
|
1334 |
+
$this->_dstore = array();
|
1335 |
+
$this->_same = true;
|
1336 |
+
}
|
1337 |
+
|
1338 |
+
public function currentItemExists()
|
1339 |
+
{
|
1340 |
+
return $this->_curitemids["__new"] == false;
|
1341 |
+
}
|
1342 |
+
|
1343 |
+
public function getItemIds($item)
|
1344 |
+
{
|
1345 |
+
$sku = $item["sku"];
|
1346 |
+
if (strcmp($sku, $this->_curitemids["sku"]) != 0)
|
1347 |
+
{
|
1348 |
+
// try to find item ids in db
|
1349 |
+
$cids = $this->getProductIds($sku);
|
1350 |
+
if ($cids !== false)
|
1351 |
+
{
|
1352 |
+
// if found use it
|
1353 |
+
$this->_curitemids = $cids;
|
1354 |
+
}
|
1355 |
+
else
|
1356 |
+
{
|
1357 |
+
// only sku & attribute set id from datasource otherwise.
|
1358 |
+
$this->_curitemids = array("pid"=>null,"sku"=>$sku,
|
1359 |
+
"asid"=>isset($item["attribute_set"]) ? $this->getAttributeSetId($item["attribute_set"]) : $this->default_asid,
|
1360 |
+
"type"=>isset($item["type"]) ? $item["type"] : "simple","__new"=>true);
|
1361 |
+
}
|
1362 |
+
// do not reset values for existing if non admin
|
1363 |
+
$this->onNewSku($sku, ($cids !== false));
|
1364 |
+
unset($cids);
|
1365 |
+
}
|
1366 |
+
else
|
1367 |
+
{
|
1368 |
+
$this->onSameSku($sku);
|
1369 |
+
}
|
1370 |
+
return $this->_curitemids;
|
1371 |
+
}
|
1372 |
+
|
1373 |
+
public function handleIgnore(&$item)
|
1374 |
+
{
|
1375 |
+
// filter __MAGMI_IGNORE__ COLUMNS
|
1376 |
+
foreach ($item as $k => $v)
|
1377 |
+
{
|
1378 |
+
if ($v === "__MAGMI_IGNORE__")
|
1379 |
+
{
|
1380 |
+
unset($item[$k]);
|
1381 |
+
}
|
1382 |
+
}
|
1383 |
+
}
|
1384 |
+
|
1385 |
+
public function findItemStores($pid)
|
1386 |
+
{
|
1387 |
+
$sql = "SELECT cs.code FROM " . $this->tablename("catalog_product_website") . " AS cpw" . " JOIN " .
|
1388 |
+
$this->tablename("core_store") . " as cs ON cs.website_id=cpw.website_id" . " WHERE cpw.product_id=?";
|
1389 |
+
$result = $this->selectAll($sql, array($pid));
|
1390 |
+
$scodes = array();
|
1391 |
+
foreach ($result as $row)
|
1392 |
+
{
|
1393 |
+
$scodes[] = $row["code"];
|
1394 |
+
}
|
1395 |
+
return implode(",", $scodes);
|
1396 |
+
}
|
1397 |
+
|
1398 |
+
public function checkItemStores($scodes)
|
1399 |
+
{
|
1400 |
+
if ($scodes == "admin")
|
1401 |
+
{
|
1402 |
+
return $scodes;
|
1403 |
+
}
|
1404 |
+
|
1405 |
+
$scarr = explode(",", $scodes);
|
1406 |
+
trimarray($scarr);
|
1407 |
+
$rscode = array();
|
1408 |
+
$sql = "SELECT code FROM " . $this->tablename("core_store") . " WHERE code IN (" . $this->arr2values($scarr) .
|
1409 |
+
")";
|
1410 |
+
$result = $this->selectAll($sql, $scarr);
|
1411 |
+
$rscodes = array();
|
1412 |
+
foreach ($result as $row)
|
1413 |
+
{
|
1414 |
+
$rscodes[] = $row["code"];
|
1415 |
+
}
|
1416 |
+
$diff = array_diff($scarr, $rscodes);
|
1417 |
+
$out = "";
|
1418 |
+
if (count($diff) > 0)
|
1419 |
+
{
|
1420 |
+
$out = "Invalid store code(s) found:" . implode(",", $diff);
|
1421 |
+
}
|
1422 |
+
if ($out != "")
|
1423 |
+
{
|
1424 |
+
if (count($rscodes) == 0)
|
1425 |
+
{
|
1426 |
+
$out .= ", NO VALID STORE FOUND";
|
1427 |
+
}
|
1428 |
+
$this->log($out, "warning");
|
1429 |
+
}
|
1430 |
+
|
1431 |
+
return implode(",", $rscodes);
|
1432 |
+
}
|
1433 |
+
|
1434 |
+
public function checkstore(&$item, $pid, $isnew)
|
1435 |
+
{
|
1436 |
+
// we have store column set , just check
|
1437 |
+
if (isset($item["store"]) && trim($item["store"]) != "")
|
1438 |
+
{
|
1439 |
+
$scodes = $this->checkItemStores($item["store"]);
|
1440 |
+
}
|
1441 |
+
else
|
1442 |
+
{
|
1443 |
+
$scodes = "admin";
|
1444 |
+
}
|
1445 |
+
if ($scodes == "")
|
1446 |
+
{
|
1447 |
+
return false;
|
1448 |
+
}
|
1449 |
+
$item["store"] = $scodes;
|
1450 |
+
return true;
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
/**
|
1454 |
+
* full import workflow for item
|
1455 |
+
*
|
1456 |
+
* @param array $item
|
1457 |
+
* : attribute values for product indexed by attribute_code
|
1458 |
+
*/
|
1459 |
+
public function importItem($item)
|
1460 |
+
{
|
1461 |
+
$this->handleIgnore($item);
|
1462 |
+
if (Magmi_StateManager::getState() == "canceled")
|
1463 |
+
{
|
1464 |
+
throw new Exception("MAGMI_RUN_CANCELED");
|
1465 |
+
}
|
1466 |
+
// first step
|
1467 |
+
|
1468 |
+
if (!$this->callPlugins("itemprocessors", "processItemBeforeId", $item))
|
1469 |
+
{
|
1470 |
+
return false;
|
1471 |
+
}
|
1472 |
+
|
1473 |
+
// check if sku has been reset
|
1474 |
+
if (!isset($item["sku"]) || trim($item["sku"]) == '')
|
1475 |
+
{
|
1476 |
+
$this->log('No sku info found for record #' . $this->_current_row, "error");
|
1477 |
+
return false;
|
1478 |
+
}
|
1479 |
+
// handle "computed" ignored columns
|
1480 |
+
$this->handleIgnore($item);
|
1481 |
+
// get Item identifiers in magento
|
1482 |
+
$itemids = $this->getItemIds($item);
|
1483 |
+
|
1484 |
+
// extract product id & attribute set id
|
1485 |
+
$pid = $itemids["pid"];
|
1486 |
+
$asid = $itemids["asid"];
|
1487 |
+
|
1488 |
+
$isnew = false;
|
1489 |
+
if (isset($pid) && $this->mode == "xcreate")
|
1490 |
+
{
|
1491 |
+
$this->log("skipping existing sku:{$item["sku"]} - xcreate mode set", "skip");
|
1492 |
+
return false;
|
1493 |
+
}
|
1494 |
+
|
1495 |
+
if (!isset($pid))
|
1496 |
+
{
|
1497 |
+
|
1498 |
+
if ($this->mode !== 'update')
|
1499 |
+
{
|
1500 |
+
if (!isset($asid))
|
1501 |
+
{
|
1502 |
+
$this->log("cannot create product sku:{$item["sku"]}, no attribute_set defined", "error");
|
1503 |
+
return false;
|
1504 |
+
}
|
1505 |
+
$pid = $this->createProduct($item, $asid);
|
1506 |
+
$this->_curitemids["pid"] = $pid;
|
1507 |
+
$isnew = true;
|
1508 |
+
}
|
1509 |
+
else
|
1510 |
+
{
|
1511 |
+
// mode is update, do nothing
|
1512 |
+
$this->log("skipping unknown sku:{$item["sku"]} - update mode set", "skip");
|
1513 |
+
return false;
|
1514 |
+
}
|
1515 |
+
}
|
1516 |
+
else
|
1517 |
+
{
|
1518 |
+
$this->updateProduct($item, $pid);
|
1519 |
+
}
|
1520 |
+
|
1521 |
+
try
|
1522 |
+
{
|
1523 |
+
$basemeta = array("product_id"=>$pid,"new"=>$isnew,"same"=>$this->_same,"asid"=>$asid);
|
1524 |
+
$fullmeta = array_merge($basemeta, $itemids);
|
1525 |
+
if (!$this->callPlugins("itemprocessors", "processItemAfterId", $item, $fullmeta))
|
1526 |
+
{
|
1527 |
+
return false;
|
1528 |
+
}
|
1529 |
+
|
1530 |
+
if (count($item) == 0)
|
1531 |
+
{
|
1532 |
+
return true;
|
1533 |
+
}
|
1534 |
+
// handle "computed" ignored columns from afterImport
|
1535 |
+
$this->handleIgnore($item);
|
1536 |
+
|
1537 |
+
if (!$this->checkstore($item, $pid, $isnew))
|
1538 |
+
{
|
1539 |
+
$this->log("invalid store value, skipping item sku:" . $item["sku"]);
|
1540 |
+
return false;
|
1541 |
+
}
|
1542 |
+
// if column list has been modified by callback, update attribute info cache.
|
1543 |
+
$this->initAttrInfos(array_keys($item));
|
1544 |
+
// create new ones
|
1545 |
+
$attrmap = $this->attrbytype;
|
1546 |
+
do
|
1547 |
+
{
|
1548 |
+
$attrmap = $this->createAttributes($pid, $item, $attrmap, $isnew, $itemids);
|
1549 |
+
}
|
1550 |
+
while (count($attrmap) > 0);
|
1551 |
+
|
1552 |
+
if (!testempty($item, "category_ids") || (isset($item["category_reset"]) && $item["category_reset"] == 1))
|
1553 |
+
{
|
1554 |
+
// assign categories
|
1555 |
+
$this->assignCategories($pid, $item);
|
1556 |
+
}
|
1557 |
+
|
1558 |
+
// update websites if column is set
|
1559 |
+
if (isset($item["websites"]) || $isnew)
|
1560 |
+
{
|
1561 |
+
$this->updateWebSites($pid, $item);
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
if (!$this->_same)
|
1565 |
+
{
|
1566 |
+
// update stock
|
1567 |
+
$this->updateStock($pid, $item, $isnew);
|
1568 |
+
}
|
1569 |
+
|
1570 |
+
$this->touchProduct($pid);
|
1571 |
+
// ok,we're done
|
1572 |
+
if (!$this->callPlugins("itemprocessors", "processItemAfterImport", $item, $fullmeta))
|
1573 |
+
{
|
1574 |
+
return false;
|
1575 |
+
}
|
1576 |
+
}
|
1577 |
+
catch (Exception $e)
|
1578 |
+
{
|
1579 |
+
$this->callPlugins(array("itemprocessors"), "processItemException", $item, array("exception"=>$e));
|
1580 |
+
$this->logException($e);
|
1581 |
+
throw $e;
|
1582 |
+
}
|
1583 |
+
// return true;
|
1584 |
+
return $pid;
|
1585 |
+
}
|
1586 |
+
|
1587 |
+
public function getProperties()
|
1588 |
+
{
|
1589 |
+
return $this->_props;
|
1590 |
+
}
|
1591 |
+
|
1592 |
+
/**
|
1593 |
+
* count lines of csv file
|
1594 |
+
*
|
1595 |
+
* @param string $csvfile
|
1596 |
+
* filename
|
1597 |
+
*/
|
1598 |
+
public function lookup()
|
1599 |
+
{
|
1600 |
+
$t0 = microtime(true);
|
1601 |
+
$this->log("Performing Datasouce Lookup...", "startup");
|
1602 |
+
|
1603 |
+
$count = $this->datasource->getRecordsCount();
|
1604 |
+
$t1 = microtime(true);
|
1605 |
+
$time = $t1 - $t0;
|
1606 |
+
$this->log("$count:$time", "lookup");
|
1607 |
+
$this->log("Found $count records, took $time sec", "startup");
|
1608 |
+
|
1609 |
+
return $count;
|
1610 |
+
}
|
1611 |
+
|
1612 |
+
public function updateProduct($item, $pid)
|
1613 |
+
{
|
1614 |
+
$tname = $this->tablename('catalog_product_entity');
|
1615 |
+
if (isset($item['type']))
|
1616 |
+
{
|
1617 |
+
$item['type_id'] = $item['type'];
|
1618 |
+
}
|
1619 |
+
$item['entity_type_id'] = $this->prod_etype;
|
1620 |
+
$item['updated_at'] = strftime("%Y-%m-%d %H:%M:%S");
|
1621 |
+
$columns = array_intersect(array_keys($item), $this->getProdCols());
|
1622 |
+
$values = $this->filterkvarr($item, $columns);
|
1623 |
+
|
1624 |
+
$sql = "UPDATE `$tname` SET " . $this->arr2update($values) . " WHERE entity_id=?";
|
1625 |
+
|
1626 |
+
$this->update($sql, array_merge(array_values($values), array($pid)));
|
1627 |
+
}
|
1628 |
+
|
1629 |
+
public function getProductEntityType()
|
1630 |
+
{
|
1631 |
+
return $this->prod_etype;
|
1632 |
+
}
|
1633 |
+
|
1634 |
+
public function getCurrentRow()
|
1635 |
+
{
|
1636 |
+
return $this->_current_row;
|
1637 |
+
}
|
1638 |
+
|
1639 |
+
public function setCurrentRow($cnum)
|
1640 |
+
{
|
1641 |
+
$this->_current_row = $cnum;
|
1642 |
+
}
|
1643 |
+
|
1644 |
+
public function isLastItem($item)
|
1645 |
+
{
|
1646 |
+
return isset($item["__MAGMI_LAST__"]);
|
1647 |
+
}
|
1648 |
+
|
1649 |
+
public function setLastItem(&$item)
|
1650 |
+
{
|
1651 |
+
$item["__MAGMI_LAST__"] = 1;
|
1652 |
+
}
|
1653 |
+
|
1654 |
+
public function engineInit($params)
|
1655 |
+
{
|
1656 |
+
$this->_profile = $this->getParam($params, "profile", "default");
|
1657 |
+
// create an instance of local magento directory handler
|
1658 |
+
// this instance will autoregister in factory
|
1659 |
+
$mdh = new LocalMagentoDirHandler(Magmi_Config::getInstance()->getMagentoDir());
|
1660 |
+
$this->_timecounter->initTimingCats(array("global","line"));
|
1661 |
+
$this->initPlugins($this->_profile);
|
1662 |
+
$this->mode = $this->getParam($params, "mode", "update");
|
1663 |
+
}
|
1664 |
+
|
1665 |
+
public function reportStats($nrow, &$tstart, &$tdiff, &$lastdbtime, &$lastrec)
|
1666 |
+
{
|
1667 |
+
$tend = microtime(true);
|
1668 |
+
$this->log($nrow . " - " . ($tend - $tstart) . " - " . ($tend - $tdiff), "itime");
|
1669 |
+
$this->log(
|
1670 |
+
$this->_nreq . " - " . ($this->_indbtime) . " - " . ($this->_indbtime - $lastdbtime) . " - " .
|
1671 |
+
($this->_nreq - $lastrec), "dbtime");
|
1672 |
+
$lastrec = $this->_nreq;
|
1673 |
+
$lastdbtime = $this->_indbtime;
|
1674 |
+
$tdiff = microtime(true);
|
1675 |
+
}
|
1676 |
+
|
1677 |
+
public function initImport($params)
|
1678 |
+
{
|
1679 |
+
$this->log("MAGMI by dweeves - version:" . Magmi_Version::$version, "title");
|
1680 |
+
$this->log("Import Profile:$this->_profile", "startup");
|
1681 |
+
$this->log("Import Mode:$this->mode", "startup");
|
1682 |
+
$this->log("step:" . $this->getProp("GLOBAL", "step", 0.5) . "%", "step");
|
1683 |
+
// intialize store id cache
|
1684 |
+
$this->connectToMagento();
|
1685 |
+
try
|
1686 |
+
{
|
1687 |
+
$this->initProdType();
|
1688 |
+
$this->createPlugins($this->_profile, $params);
|
1689 |
+
$this->_registerPluginLoopCallback("processItemAfterId", "onPluginProcessedItemAfterId");
|
1690 |
+
$this->callPlugins("datasources,itemprocessors", "startImport");
|
1691 |
+
$this->resetSkuStats();
|
1692 |
+
}
|
1693 |
+
catch (Exception $e)
|
1694 |
+
{
|
1695 |
+
$this->disconnectFromMagento();
|
1696 |
+
}
|
1697 |
+
}
|
1698 |
+
|
1699 |
+
public function onPluginProcessedItemAfterId($plinst, &$item, $plresult)
|
1700 |
+
{
|
1701 |
+
$this->handleIgnore($item);
|
1702 |
+
}
|
1703 |
+
|
1704 |
+
/**
|
1705 |
+
* Breaks item processing , but validates partial import
|
1706 |
+
* This is useful for complex plugins that would assur
|
1707 |
+
*
|
1708 |
+
* @param array $item
|
1709 |
+
* , item to break process on
|
1710 |
+
* @param array $params
|
1711 |
+
* , processing parameters (item metadata)
|
1712 |
+
* @param
|
1713 |
+
* bool touch , sets product update time if true (default)
|
1714 |
+
*/
|
1715 |
+
public function breakItemProcessing(&$item, $params, $touch = true)
|
1716 |
+
{
|
1717 |
+
// setting empty item to break standard processing
|
1718 |
+
$item = array();
|
1719 |
+
if ($touch && isset($params["product_id"]))
|
1720 |
+
{
|
1721 |
+
$this->touchProduct($params["product_id"]);
|
1722 |
+
}
|
1723 |
+
}
|
1724 |
+
|
1725 |
+
public function exitImport()
|
1726 |
+
{
|
1727 |
+
$this->callPlugins("datasources,general,itemprocessors", "endImport");
|
1728 |
+
$this->callPlugins("datasources,general,itemprocessors", "afterImport");
|
1729 |
+
$this->disconnectFromMagento();
|
1730 |
+
}
|
1731 |
+
|
1732 |
+
public function updateSkuStats($res)
|
1733 |
+
{
|
1734 |
+
if (!$this->_same)
|
1735 |
+
{
|
1736 |
+
$this->_skustats["nsku"]++;
|
1737 |
+
if ($res["ok"])
|
1738 |
+
{
|
1739 |
+
$this->_skustats["ok"]++;
|
1740 |
+
}
|
1741 |
+
else
|
1742 |
+
{
|
1743 |
+
$this->_skustats["ko"]++;
|
1744 |
+
}
|
1745 |
+
}
|
1746 |
+
}
|
1747 |
+
|
1748 |
+
public function getDataSource()
|
1749 |
+
{
|
1750 |
+
return $this->getPluginInstance("datasources");
|
1751 |
+
}
|
1752 |
+
|
1753 |
+
public function processDataSourceLine($item, $rstep, &$tstart, &$tdiff, &$lastdbtime, &$lastrec)
|
1754 |
+
{
|
1755 |
+
// counter
|
1756 |
+
$res = array("ok"=>0,"last"=>0);
|
1757 |
+
$canceled = false;
|
1758 |
+
$this->_current_row++;
|
1759 |
+
if ($this->_current_row % $rstep == 0)
|
1760 |
+
{
|
1761 |
+
$this->reportStats($this->_current_row, $tstart, $tdiff, $lastdbtime, $lastrec);
|
1762 |
+
}
|
1763 |
+
try
|
1764 |
+
{
|
1765 |
+
if (is_array($item) && count($item) > 0)
|
1766 |
+
{
|
1767 |
+
// import item
|
1768 |
+
$this->beginTransaction();
|
1769 |
+
$importedok = $this->importItem($item);
|
1770 |
+
if ($importedok)
|
1771 |
+
{
|
1772 |
+
$res["_product_id"] = $importedok;
|
1773 |
+
$res["ok"] = true;
|
1774 |
+
$this->commitTransaction();
|
1775 |
+
}
|
1776 |
+
else
|
1777 |
+
{
|
1778 |
+
$res["ok"] = false;
|
1779 |
+
$res["_exception_message"] = $item[ 'sku' ] . ': ' . $e->getMessage();
|
1780 |
+
$this->rollbackTransaction();
|
1781 |
+
}
|
1782 |
+
}
|
1783 |
+
else
|
1784 |
+
{
|
1785 |
+
$this->log("ERROR - RECORD #$this->_current_row - INVALID RECORD", "error");
|
1786 |
+
}
|
1787 |
+
// intermediary measurement
|
1788 |
+
}
|
1789 |
+
catch (Exception $e)
|
1790 |
+
{
|
1791 |
+
$this->rollbackTransaction();
|
1792 |
+
$res["ok"] = false;
|
1793 |
+
$this->logException($e, "ERROR ON RECORD #$this->_current_row");
|
1794 |
+
if ($e->getMessage() == "MAGMI_RUN_CANCELED")
|
1795 |
+
{
|
1796 |
+
$canceled = true;
|
1797 |
+
}
|
1798 |
+
}
|
1799 |
+
if ($this->isLastItem($item) || $canceled)
|
1800 |
+
{
|
1801 |
+
unset($item);
|
1802 |
+
$res["last"] = 1;
|
1803 |
+
}
|
1804 |
+
|
1805 |
+
unset($item);
|
1806 |
+
$this->updateSkuStats($res);
|
1807 |
+
|
1808 |
+
return $res;
|
1809 |
+
}
|
1810 |
+
|
1811 |
+
public function resetSkuStats()
|
1812 |
+
{
|
1813 |
+
$this->_skustats = array("nsku"=>0,"ok"=>0,"ko"=>0);
|
1814 |
+
}
|
1815 |
+
|
1816 |
+
public function engineRun($params, $forcebuiltin = array())
|
1817 |
+
{
|
1818 |
+
$this->log("Import Profile:$this->_profile", "startup");
|
1819 |
+
$this->log("Import Mode:$this->mode", "startup");
|
1820 |
+
$this->log("step:" . $this->getProp("GLOBAL", "step", 0.5) . "%", "step");
|
1821 |
+
$this->createPlugins($this->_profile, $params);
|
1822 |
+
$this->datasource = $this->getDataSource();
|
1823 |
+
$this->callPlugins("datasources,general", "beforeImport");
|
1824 |
+
$nitems = $this->lookup();
|
1825 |
+
Magmi_StateManager::setState("running");
|
1826 |
+
// if some rows found
|
1827 |
+
if ($nitems > 0)
|
1828 |
+
{
|
1829 |
+
// initializing product type early (in case of db update on startImport)
|
1830 |
+
$this->initProdType();
|
1831 |
+
$this->resetSkuStats();
|
1832 |
+
// intialize store id cache
|
1833 |
+
$this->callPlugins("datasources,itemprocessors", "startImport");
|
1834 |
+
// initializing item processors
|
1835 |
+
$cols = $this->datasource->getColumnNames();
|
1836 |
+
$this->log(count($cols), "columns");
|
1837 |
+
$this->callPlugins("itemprocessors", "processColumnList", $cols);
|
1838 |
+
if (count($cols) < 2)
|
1839 |
+
{
|
1840 |
+
$this->log("Invalid input data , not enough columns found,check datasource parameters", "error");
|
1841 |
+
$this->log("Import Ended", "end");
|
1842 |
+
Magmi_StateManager::setState("idle");
|
1843 |
+
return;
|
1844 |
+
}
|
1845 |
+
$this->log("Ajusted processed columns:" . count($cols), "startup");
|
1846 |
+
// initialize attribute infos & indexes from column names
|
1847 |
+
if ($this->mode != "update")
|
1848 |
+
{
|
1849 |
+
$this->checkRequired($cols);
|
1850 |
+
}
|
1851 |
+
$this->initAttrInfos(array_values($cols));
|
1852 |
+
// counter
|
1853 |
+
$this->_current_row = 0;
|
1854 |
+
// start time
|
1855 |
+
$tstart = microtime(true);
|
1856 |
+
// differential
|
1857 |
+
$tdiff = $tstart;
|
1858 |
+
// intermediary report step
|
1859 |
+
$this->initDbqStats();
|
1860 |
+
$pstep = $this->getProp("GLOBAL", "step", 0.5);
|
1861 |
+
$rstep = ceil(($nitems * $pstep) / 100);
|
1862 |
+
// read each line
|
1863 |
+
$lastrec = 0;
|
1864 |
+
$lastdbtime = 0;
|
1865 |
+
while (($item = $this->datasource->getNextRecord()) !== false)
|
1866 |
+
{
|
1867 |
+
$this->_timecounter->initTimingCats(array("line"));
|
1868 |
+
$res = $this->processDataSourceLine($item, $rstep, $tstart, $tdiff, $lastdbtime, $lastrec);
|
1869 |
+
// break on "forced" last
|
1870 |
+
if ($res["last"] == 1)
|
1871 |
+
{
|
1872 |
+
$this->log("last item encountered", "info");
|
1873 |
+
break;
|
1874 |
+
}
|
1875 |
+
}
|
1876 |
+
$this->callPlugins("datasources,general,itemprocessors", "endImport");
|
1877 |
+
$this->reportStats($this->_current_row, $tstart, $tdiff, $lastdbtime, $lastrec);
|
1878 |
+
$this->log("Skus imported OK:" . $this->_skustats["ok"] . "/" . $this->_skustats["nsku"], "info");
|
1879 |
+
if ($this->_skustats["ko"] > 0)
|
1880 |
+
{
|
1881 |
+
$this->log("Skus imported KO:" . $this->_skustats["ko"] . "/" . $this->_skustats["nsku"], "warning");
|
1882 |
+
}
|
1883 |
+
}
|
1884 |
+
else
|
1885 |
+
{
|
1886 |
+
$this->log("No Records returned by datasource", "warning");
|
1887 |
+
}
|
1888 |
+
$this->callPlugins("datasources,general,itemprocessors", "afterImport");
|
1889 |
+
$this->log("Import Ended", "end");
|
1890 |
+
Magmi_StateManager::setState("idle");
|
1891 |
+
|
1892 |
+
$timers = $this->_timecounter->getTimers();
|
1893 |
+
$f = fopen(Magmi_StateManager::getStateDir() . "/timings.txt", "w");
|
1894 |
+
foreach ($timers as $cat => $info)
|
1895 |
+
{
|
1896 |
+
$rep = "\nTIMING CATEGORY:$cat\n--------------------------------";
|
1897 |
+
foreach ($info as $phase => $pinfo)
|
1898 |
+
{
|
1899 |
+
$rep .= "\nPhase:$phase\n";
|
1900 |
+
foreach ($pinfo as $plugin => $data)
|
1901 |
+
{
|
1902 |
+
$rdur = round($data["dur"], 4);
|
1903 |
+
if ($rdur > 0)
|
1904 |
+
{
|
1905 |
+
$rep .= "- Class:$plugin :$rdur ";
|
1906 |
+
}
|
1907 |
+
}
|
1908 |
+
}
|
1909 |
+
fwrite($f, $rep);
|
1910 |
+
}
|
1911 |
+
fclose($f);
|
1912 |
+
}
|
1913 |
+
|
1914 |
+
public function onEngineException($e)
|
1915 |
+
{
|
1916 |
+
if (isset($this->datasource))
|
1917 |
+
{
|
1918 |
+
$this->datasource->onException($e);
|
1919 |
+
}
|
1920 |
+
$this->log("Import Ended", "end");
|
1921 |
+
|
1922 |
+
Magmi_StateManager::setState("idle");
|
1923 |
+
}
|
1924 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/engines/magmi_utilityengine.php
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* MAGENTO MASS IMPORTER CLASS
|
5 |
+
*
|
6 |
+
* version : 0.6
|
7 |
+
* author : S.BRACQUEMONT aka dweeves
|
8 |
+
* updated : 2010-10-09
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* use external file for db helper */
|
13 |
+
require_once ("magmi_engine.php");
|
14 |
+
require_once ("magmi_pluginhelper.php");
|
15 |
+
|
16 |
+
/* Magmi ProductImporter is now a Magmi_Engine instance */
|
17 |
+
class Magmi_UtilityEngine extends Magmi_Engine
|
18 |
+
{
|
19 |
+
|
20 |
+
/**
|
21 |
+
* constructor
|
22 |
+
*
|
23 |
+
* @param string $conffile
|
24 |
+
* : configuration .ini filename
|
25 |
+
*/
|
26 |
+
public function __construct()
|
27 |
+
{
|
28 |
+
parent::__construct();
|
29 |
+
}
|
30 |
+
|
31 |
+
public function getEnabledPluginClasses($profile)
|
32 |
+
{
|
33 |
+
$clist = Magmi_PluginHelper::getInstance("main")->getPluginsInfo("utilities", "class");
|
34 |
+
return $clist;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getEngineInfo()
|
38 |
+
{
|
39 |
+
return array("name"=>"Magmi Utilities Engine","version"=>"1.0.1","author"=>"dweeves");
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* load properties
|
44 |
+
*
|
45 |
+
* @param string $conf
|
46 |
+
* : configuration .ini filename
|
47 |
+
*/
|
48 |
+
public function getPluginFamilies()
|
49 |
+
{
|
50 |
+
return array("utilities");
|
51 |
+
}
|
52 |
+
|
53 |
+
public function engineInit($params)
|
54 |
+
{
|
55 |
+
$this->initPlugins(null);
|
56 |
+
}
|
57 |
+
|
58 |
+
public function engineRun($params)
|
59 |
+
{
|
60 |
+
$this->log("Magento Mass Importer by dweeves - version:" . Magmi_Version::$version, "title");
|
61 |
+
// initialize db connectivity
|
62 |
+
Magmi_StateManager::setState("running");
|
63 |
+
// force only one class to run
|
64 |
+
$this->_pluginclasses = array("utilities"=>array($params["pluginclass"]));
|
65 |
+
|
66 |
+
$this->createPlugins("__utilities__", $params);
|
67 |
+
foreach ($this->_activeplugins["utilities"] as $pinst)
|
68 |
+
{
|
69 |
+
try
|
70 |
+
{
|
71 |
+
$pinst->runUtility();
|
72 |
+
}
|
73 |
+
catch (Exception $e)
|
74 |
+
{
|
75 |
+
$this->logException($e);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
Magmi_StateManager::setState("idle");
|
80 |
+
}
|
81 |
+
|
82 |
+
public function onEngineException($e)
|
83 |
+
{
|
84 |
+
Magmi_StateManager::setState("idle");
|
85 |
+
}
|
86 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/dbhelper.class.php
ADDED
@@ -0,0 +1,661 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* This class is a Database Operation Helper based on PDO library
|
5 |
+
* It provides shortcuts for common DB CRUD operations and some advanced templated requests operations
|
6 |
+
* @author dweeves
|
7 |
+
*
|
8 |
+
*/
|
9 |
+
include_once ("timecounter.php");
|
10 |
+
|
11 |
+
class DBHelper
|
12 |
+
{
|
13 |
+
protected $_db;
|
14 |
+
protected $_debug;
|
15 |
+
protected $_laststmt;
|
16 |
+
protected $_use_stmt_cache = true;
|
17 |
+
protected $_nreq;
|
18 |
+
protected $_indbtime;
|
19 |
+
protected $_intrans = false;
|
20 |
+
protected $prepared = array();
|
21 |
+
protected $_timecounter = null;
|
22 |
+
protected $_tcats;
|
23 |
+
|
24 |
+
public function __construct()
|
25 |
+
{
|
26 |
+
$this->_timecounter = new TimeCounter(get_class($this));
|
27 |
+
$this->_tcats = "db";
|
28 |
+
$this->_timecounter->initTimingCats(array($this->_tcats));
|
29 |
+
$this->_timecounter->addCounter("requests");
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Intializes database connection
|
34 |
+
*
|
35 |
+
* @param string $host
|
36 |
+
* : hostname
|
37 |
+
* @param string $dbname
|
38 |
+
* : database name
|
39 |
+
* @param string $user
|
40 |
+
* : username
|
41 |
+
* @param string $pass
|
42 |
+
* : password
|
43 |
+
* @param bool $debug
|
44 |
+
* : debug mode
|
45 |
+
*/
|
46 |
+
public function initDb($host, $dbname, $user, $pass, $port = 3306, $socket = "/tmp/mysql.sock", $conntype = "net", $debug = false)
|
47 |
+
{
|
48 |
+
// intialize connection with PDO
|
49 |
+
// fix by Mr Lei for UTF8 special chars
|
50 |
+
if ($conntype == "net")
|
51 |
+
{
|
52 |
+
$pdostr = "mysql:host=$host;port=$port;dbname=$dbname;charset=utf8";
|
53 |
+
}
|
54 |
+
else
|
55 |
+
{
|
56 |
+
$pdostr = "mysql:unix_socket=$socket;dbname=$dbname;charset=utf8";
|
57 |
+
}
|
58 |
+
|
59 |
+
$this->_db = new PDO($pdostr, $user, $pass, array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET NAMES utf8"));
|
60 |
+
// use exception error mode
|
61 |
+
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
62 |
+
$this->_db->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);
|
63 |
+
$this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
64 |
+
|
65 |
+
// set database debug mode to trace if necessary
|
66 |
+
$this->_debug = $debug;
|
67 |
+
$this->prepared = array();
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* store output in some debug file
|
72 |
+
*
|
73 |
+
* @param unknown_type $data
|
74 |
+
*/
|
75 |
+
public function logdebug($data)
|
76 |
+
{
|
77 |
+
if ($this->_debug)
|
78 |
+
{
|
79 |
+
$f = fopen($this->_debugfile, "a");
|
80 |
+
fwrite($f, microtime());
|
81 |
+
fwrite($f, $data);
|
82 |
+
fwrite($f, "\n");
|
83 |
+
fclose($f);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Sets or unsets the usage of internal prepared statement cache for reuse
|
89 |
+
*
|
90 |
+
* @param boolean $uc
|
91 |
+
* true:use cache,false:do not use cache
|
92 |
+
*/
|
93 |
+
public function usestmtcache($uc)
|
94 |
+
{
|
95 |
+
$this->_use_stmt_cache = $uc;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* releases database connection
|
100 |
+
*/
|
101 |
+
public function exitDb()
|
102 |
+
{
|
103 |
+
// clear PDO resource
|
104 |
+
$this->_db = NULL;
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Helper method to try to guess mysql socket based on some tricky phpinfo analysis
|
109 |
+
*
|
110 |
+
* @throws Exception if something got wrong during detection
|
111 |
+
*/
|
112 |
+
public static function getMysqlSocket()
|
113 |
+
{
|
114 |
+
$mysqlsock = "";
|
115 |
+
$old_track = ini_set('track_errors', '1');
|
116 |
+
try
|
117 |
+
{
|
118 |
+
$mysqlsock = ini_get("mysql.default_socket");
|
119 |
+
|
120 |
+
if (isset($mysqlsock) && !@file_exists($mysqlsock))
|
121 |
+
{
|
122 |
+
if (error_get_last() !== null)
|
123 |
+
{
|
124 |
+
throw new Exception();
|
125 |
+
}
|
126 |
+
ob_start();
|
127 |
+
phpinfo();
|
128 |
+
$data = ob_get_contents();
|
129 |
+
ob_end_clean();
|
130 |
+
$cap = preg_match("/MYSQL_SOCKET.*?<td .*?>(.*?)<\/td>/msi", $data, $matches);
|
131 |
+
if ($cap)
|
132 |
+
{
|
133 |
+
$mysqlsock = $matches[1];
|
134 |
+
}
|
135 |
+
}
|
136 |
+
if (isset($mysqlsock) && !@file_exists($mysqlsock))
|
137 |
+
{
|
138 |
+
$mysqlsock = "";
|
139 |
+
}
|
140 |
+
}
|
141 |
+
catch (Exception $e)
|
142 |
+
{}
|
143 |
+
if (error_get_last() !== null)
|
144 |
+
{
|
145 |
+
$mysqlsock = false;
|
146 |
+
}
|
147 |
+
ini_set('track_errors', $old_track);
|
148 |
+
return $mysqlsock;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Initializes database requests stats counters
|
153 |
+
*/
|
154 |
+
public function initDbqStats()
|
155 |
+
{
|
156 |
+
$this->_nreq = 0;
|
157 |
+
$this->_indbtime = 0;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Returns database statistics
|
162 |
+
*
|
163 |
+
* @param unknown_type $nbreq
|
164 |
+
*/
|
165 |
+
public function collectDbqStats(&$nbreq)
|
166 |
+
{
|
167 |
+
return $this->_nreq;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* cache sorting comparison method
|
172 |
+
*
|
173 |
+
* @param unknown_type $a
|
174 |
+
* @param unknown_type $b
|
175 |
+
*/
|
176 |
+
public function cachesort($a, $b)
|
177 |
+
{
|
178 |
+
return $b[1] - $a[1];
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Garbages statement cache if above 500 , removes less used statements
|
183 |
+
*/
|
184 |
+
public function garbageStmtCache()
|
185 |
+
{
|
186 |
+
if (count($this->prepared) >= 500)
|
187 |
+
{
|
188 |
+
uasort($this->prepared, array($this,"cachesort"));
|
189 |
+
array_splice($this->prepared, 350, count($this->prepared));
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* executes an sql statement
|
195 |
+
*
|
196 |
+
* @param string $sql
|
197 |
+
* : sql statement (may include ? placeholders or named variables)
|
198 |
+
* @param array $params
|
199 |
+
* : parameters to replace placeholders (can be null)
|
200 |
+
* @param boolean $close
|
201 |
+
* : auto close cursor after statement execution (defaults to true)
|
202 |
+
* @return PDOStatement : statement for further processing if needed
|
203 |
+
*/
|
204 |
+
public function exec_stmt($sql, $params = null, $close = true)
|
205 |
+
{
|
206 |
+
$this->_nreq++;
|
207 |
+
$this->_timecounter->initTime("indb", null, $this->_tcats);
|
208 |
+
$this->_timecounter->incCounter("requests");
|
209 |
+
$t0 = microtime(true);
|
210 |
+
if ($this->_use_stmt_cache && strpos($sql, "'") == false)
|
211 |
+
{
|
212 |
+
// if sql not in statement cache
|
213 |
+
if (!isset($this->prepared[$sql]))
|
214 |
+
{
|
215 |
+
$this->garbageStmtCache();
|
216 |
+
// create new prepared statement
|
217 |
+
$stmt = $this->_db->prepare($sql);
|
218 |
+
// cache prepare statement
|
219 |
+
$this->prepared[$sql] = array($stmt,1);
|
220 |
+
}
|
221 |
+
else
|
222 |
+
{
|
223 |
+
// get from statement cache
|
224 |
+
$this->prepared[$sql][1]++;
|
225 |
+
$stmt = $this->prepared[$sql][0];
|
226 |
+
}
|
227 |
+
}
|
228 |
+
else
|
229 |
+
{
|
230 |
+
// create new prepared statement
|
231 |
+
$stmt = $this->_db->prepare($sql);
|
232 |
+
}
|
233 |
+
$this->_laststmt = $stmt;
|
234 |
+
if ($params != null)
|
235 |
+
{
|
236 |
+
if (!$this->is_assoc($params))
|
237 |
+
{
|
238 |
+
$params = is_array($params) ? $params : array($params);
|
239 |
+
$stmt->execute($params);
|
240 |
+
}
|
241 |
+
else
|
242 |
+
{
|
243 |
+
foreach ($params as $pname => $pval)
|
244 |
+
{
|
245 |
+
if (count(explode(":", $pname)) == 1)
|
246 |
+
{
|
247 |
+
$val = strval($pval);
|
248 |
+
$stmt->bindValue(":$pname", $val);
|
249 |
+
}
|
250 |
+
}
|
251 |
+
$stmt->execute();
|
252 |
+
}
|
253 |
+
}
|
254 |
+
else
|
255 |
+
{
|
256 |
+
|
257 |
+
$stmt->execute();
|
258 |
+
}
|
259 |
+
if ($close)
|
260 |
+
{
|
261 |
+
$stmt->closeCursor();
|
262 |
+
}
|
263 |
+
$this->_timecounter->exitTime("indb", null, $this->_tcats);
|
264 |
+
$t1 = microtime(true);
|
265 |
+
$this->_indbtime += $t1 - $t0;
|
266 |
+
$this->logdebug("$sql\n" . print_r($params, true));
|
267 |
+
unset($params);
|
268 |
+
return $stmt;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Perform a delete statement, sql should be "DELETE"
|
273 |
+
*
|
274 |
+
* @param string $sql
|
275 |
+
* : DELETE statement sql (placeholders allowed)
|
276 |
+
* @param array $params
|
277 |
+
* : placeholder replacements (can be null)
|
278 |
+
*/
|
279 |
+
public function delete($sql, $params = null)
|
280 |
+
{
|
281 |
+
$this->exec_stmt($sql, $params);
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* Performs an update statement
|
286 |
+
*
|
287 |
+
* @param string $sql
|
288 |
+
* UPDATE statement sql (placeholder allowed)
|
289 |
+
* @param array $params
|
290 |
+
* parameter values if placeholders in SQL
|
291 |
+
*/
|
292 |
+
public function update($sql, $params = null)
|
293 |
+
{
|
294 |
+
$this->exec_stmt($sql, $params);
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Perform an insert , sql should be "INSERT"
|
299 |
+
*
|
300 |
+
* @param string $sql
|
301 |
+
* :INSERT statement SQL (placeholders allowed)
|
302 |
+
* @param array $params
|
303 |
+
* : placeholder replacements (can be null)
|
304 |
+
* @return mixed : last inserted id
|
305 |
+
*/
|
306 |
+
public function insert($sql, $params = null)
|
307 |
+
{
|
308 |
+
$this->exec_stmt($sql, $params);
|
309 |
+
$liid = $this->_db->lastInsertId();
|
310 |
+
return $liid;
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Perform a select ,sql should be "SELECT"
|
315 |
+
*
|
316 |
+
* @param string $sql
|
317 |
+
* :SELECT statement SQL (placeholders allowed)
|
318 |
+
* @param array $params
|
319 |
+
* : placeholder replacements (can be null)
|
320 |
+
* @return PDOStatement : statement instance for further processing
|
321 |
+
*/
|
322 |
+
public function select($sql, $params = null)
|
323 |
+
{
|
324 |
+
return $this->exec_stmt($sql, $params, false);
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Selects one unique value from one single row
|
329 |
+
*
|
330 |
+
* @param $sql :
|
331 |
+
* SELECT statement SQL (placeholders allowed)
|
332 |
+
* @param $params :placeholder
|
333 |
+
* replacements (can be null)
|
334 |
+
* @param $col :
|
335 |
+
* column value to retrieve
|
336 |
+
* @return mixed : null if not result , wanted column value if match
|
337 |
+
*/
|
338 |
+
public function selectone($sql, $params, $col)
|
339 |
+
{
|
340 |
+
$stmt = $this->select($sql, $params);
|
341 |
+
$this->_timecounter->initTime("indb", null, $this->_tcats);
|
342 |
+
$t0 = microtime(true);
|
343 |
+
|
344 |
+
$r = $stmt->fetch(PDO::FETCH_ASSOC);
|
345 |
+
$stmt->closeCursor();
|
346 |
+
$this->_timecounter->exitTime("indb", null, $this->_tcats);
|
347 |
+
|
348 |
+
$t1 = microtime(true);
|
349 |
+
|
350 |
+
$this->_indbtime += $t1 - $t0;
|
351 |
+
$v = (is_array($r) ? $r[$col] : null);
|
352 |
+
unset($r);
|
353 |
+
return $v;
|
354 |
+
}
|
355 |
+
|
356 |
+
/**
|
357 |
+
* Selects all values from a statement into a php array
|
358 |
+
*
|
359 |
+
* @param unknown_type $sql
|
360 |
+
* sql select to execute
|
361 |
+
* @param unknown_type $params
|
362 |
+
* placeholder replacements (can be null)
|
363 |
+
*/
|
364 |
+
public function selectAll($sql, $params = null)
|
365 |
+
{
|
366 |
+
$stmt = $this->select($sql, $params);
|
367 |
+
$this->_timecounter->initTime("indb", null, $this->_tcats);
|
368 |
+
|
369 |
+
$t0 = microtime(true);
|
370 |
+
|
371 |
+
$r = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
372 |
+
$stmt->closeCursor();
|
373 |
+
$this->_timecounter->exitTime("indb", null, $this->_tcats);
|
374 |
+
|
375 |
+
$t1 = microtime(true);
|
376 |
+
$this->_indbtime += $t1 - $t0;
|
377 |
+
return $r;
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* test if value exists (test should be compatible with unique select)
|
382 |
+
*
|
383 |
+
* @param $sql :
|
384 |
+
* SELECT statement SQL (placeholders allowed)
|
385 |
+
* @param $params :placeholder
|
386 |
+
* replacements (can be null)
|
387 |
+
* @param $col :
|
388 |
+
* column value to retrieve
|
389 |
+
* @return boolean : true if value found, false otherwise
|
390 |
+
*/
|
391 |
+
public function testexists($sql, $params, $col)
|
392 |
+
{
|
393 |
+
return $this->selectone($sql, $params, $col) != null;
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Quote array values in order to be used as parameters (handy if array used directly in explode in a IN condition)
|
398 |
+
*
|
399 |
+
* @param array $arr
|
400 |
+
* array of values to be quoted
|
401 |
+
*/
|
402 |
+
public function quotearr($arr)
|
403 |
+
{
|
404 |
+
$arrout = array();
|
405 |
+
foreach ($arr as $v)
|
406 |
+
{
|
407 |
+
$arrout[] = $this->_db->quote($v);
|
408 |
+
}
|
409 |
+
return $arrout;
|
410 |
+
}
|
411 |
+
|
412 |
+
/**
|
413 |
+
* transforms an array in a comma separated list of enclosed column names for request
|
414 |
+
*
|
415 |
+
* @param array $arr
|
416 |
+
* list of names to enclose
|
417 |
+
*/
|
418 |
+
public function arr2columns($arr)
|
419 |
+
{
|
420 |
+
$arrout = array();
|
421 |
+
foreach ($arr as $cname)
|
422 |
+
{
|
423 |
+
$arrout[] = "`" . $cname . "`";
|
424 |
+
}
|
425 |
+
$colstr = implode(",", $arrout);
|
426 |
+
unset($arrout);
|
427 |
+
return $colstr;
|
428 |
+
}
|
429 |
+
|
430 |
+
/**
|
431 |
+
* transform an array of values into equivalent comma separated list of unnamed placeholders.
|
432 |
+
*
|
433 |
+
* @param array $arr
|
434 |
+
*/
|
435 |
+
public function arr2values($arr)
|
436 |
+
{
|
437 |
+
$str = substr(str_repeat("?,", count($arr)), 0, -1);
|
438 |
+
return $str;
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* transform a list of values into static select to use it as SQL static resultset
|
443 |
+
*
|
444 |
+
* @param array $arr
|
445 |
+
* list of values to use as SQL dataset
|
446 |
+
* @param string $cname
|
447 |
+
* sql column name to use to represent dataset
|
448 |
+
*/
|
449 |
+
public function arr2select($arr, $cname = "id")
|
450 |
+
{
|
451 |
+
$rpt = str_repeat("? AS $cname UNION SELECT ", count($arr));
|
452 |
+
$subsel = substr($rpt, 0, -1 * strlen(" UNION SELECT "));
|
453 |
+
return "(SELECT $subsel)";
|
454 |
+
}
|
455 |
+
|
456 |
+
/**
|
457 |
+
* transform associative array into CASE sub statement
|
458 |
+
*/
|
459 |
+
public function arr2case($arr, $casevar)
|
460 |
+
{
|
461 |
+
$sql = "(CASE ";
|
462 |
+
foreach ($arr as $k => $v)
|
463 |
+
{
|
464 |
+
$sql .= "WHEN $casevar='$k' THEN '$v'\n";
|
465 |
+
}
|
466 |
+
$sql .= "END)";
|
467 |
+
return $sql;
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* transform a associative array into a list of update prepared placeholders
|
472 |
+
*
|
473 |
+
* @param array $arr
|
474 |
+
* associative array to prepare for update , array keys used as column to update
|
475 |
+
*/
|
476 |
+
public function arr2update($arr)
|
477 |
+
{
|
478 |
+
$arrout = array();
|
479 |
+
foreach ($arr as $k => $v)
|
480 |
+
{
|
481 |
+
$arrout[] = "$k=?";
|
482 |
+
}
|
483 |
+
$updstr = implode(",", $arrout);
|
484 |
+
unset($arrout);
|
485 |
+
return $updstr;
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Filters a key value array over a list of keys , replacing __NULL__ magic value with true null
|
490 |
+
*
|
491 |
+
* @param unknown_type $kvarr
|
492 |
+
* @param unknown_type $keys
|
493 |
+
*/
|
494 |
+
public function filterkvarr($kvarr, $keys)
|
495 |
+
{
|
496 |
+
$out = array();
|
497 |
+
foreach ($keys as $k)
|
498 |
+
{
|
499 |
+
$out[$k] = (isset($kvarr[$k]) && $kvarr[$k] != '__NULL__') ? $kvarr[$k] : null;
|
500 |
+
}
|
501 |
+
return $out;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* begins a transaction
|
506 |
+
*/
|
507 |
+
public function beginTransaction()
|
508 |
+
{
|
509 |
+
$this->_db->beginTransaction();
|
510 |
+
$this->_intrans = true;
|
511 |
+
$this->logdebug("-- TRANSACTION BEGIN --");
|
512 |
+
}
|
513 |
+
|
514 |
+
/**
|
515 |
+
* commits the current transaction
|
516 |
+
*/
|
517 |
+
public function commitTransaction()
|
518 |
+
{
|
519 |
+
$this->_db->commit();
|
520 |
+
$this->_intrans = false;
|
521 |
+
$this->logdebug("-- TRANSACTION COMMIT --");
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* rollback the current transaction
|
526 |
+
*/
|
527 |
+
public function rollbackTransaction()
|
528 |
+
{
|
529 |
+
if ($this->_intrans)
|
530 |
+
{
|
531 |
+
$this->_db->rollBack();
|
532 |
+
$this->_intrans = false;
|
533 |
+
$this->logdebug("-- TRANSACTION ROLLBACK --");
|
534 |
+
}
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Sets debug management
|
539 |
+
*
|
540 |
+
* @param bool $debug
|
541 |
+
* debug flag
|
542 |
+
* @param string $debugfname
|
543 |
+
* debug file name to use
|
544 |
+
*/
|
545 |
+
public function setDebug($debug, $debugfname)
|
546 |
+
{
|
547 |
+
$this->_debug = $debug;
|
548 |
+
$this->_debugfile = $debugfname;
|
549 |
+
}
|
550 |
+
|
551 |
+
/**
|
552 |
+
* Replaces named params in a descriptive parameterized request
|
553 |
+
* Descriptive parameterized request have parameters defined as
|
554 |
+
* [namespace:name/label/default value] , this parameters may represent table names or any request parameter
|
555 |
+
* namespace is optional, as label & default value
|
556 |
+
* - NameSpaces:
|
557 |
+
* tn : tablename, this namespace ensures replacement of given name with defined DB prefix so, parameterized request can use generic names to define their ops
|
558 |
+
*
|
559 |
+
* @param unknown_type $stmt
|
560 |
+
* @param unknown_type $rparams
|
561 |
+
*/
|
562 |
+
public function replaceParams(&$stmt, &$rparams)
|
563 |
+
{
|
564 |
+
$params = array();
|
565 |
+
$hasp = preg_match_all('|\[\[(.*?)\]\]|msi', $stmt, $matches);
|
566 |
+
if ($hasp)
|
567 |
+
{
|
568 |
+
$pdefs = $matches[0];
|
569 |
+
$params = $matches[1];
|
570 |
+
}
|
571 |
+
$cparams = count($params);
|
572 |
+
for ($i = 0; $i < $cparams; $i++)
|
573 |
+
{
|
574 |
+
$param = $params[$i];
|
575 |
+
$pdef = $pdefs[$i];
|
576 |
+
$pinfo = explode("/", $param);
|
577 |
+
$pname = $pinfo[0];
|
578 |
+
$epar = explode(":", $pname);
|
579 |
+
if (count($epar) > 1)
|
580 |
+
{
|
581 |
+
$stmt = str_replace($pdef, $rparams[$pname], $stmt);
|
582 |
+
}
|
583 |
+
else
|
584 |
+
{
|
585 |
+
$stmt = str_replace($pdef, ":$pname", $stmt);
|
586 |
+
}
|
587 |
+
}
|
588 |
+
for ($i = 0; $i < $cparams; $i++)
|
589 |
+
{
|
590 |
+
$param = $params[$i];
|
591 |
+
$pinfo = explode("/", $param);
|
592 |
+
$pname = $pinfo[0];
|
593 |
+
$epar = explode(":", $pname);
|
594 |
+
if (count($epar) > 1)
|
595 |
+
{
|
596 |
+
unset($rparams[$pname]);
|
597 |
+
}
|
598 |
+
}
|
599 |
+
}
|
600 |
+
|
601 |
+
/**
|
602 |
+
* Checks wether an array is associative
|
603 |
+
*
|
604 |
+
* @param mixed $var
|
605 |
+
* array or variable to test
|
606 |
+
*/
|
607 |
+
public function is_assoc($var)
|
608 |
+
{
|
609 |
+
return is_array($var) && array_keys($var) !== range(0, sizeof($var) - 1);
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* This method handled mutiple statements in a single SQL (PDO cannot do it by itself)
|
614 |
+
* Statements have to be separed by ; & line return.
|
615 |
+
*
|
616 |
+
* @param string $sql
|
617 |
+
* multiple statements
|
618 |
+
* @param array $params
|
619 |
+
* values to use for parameter placeholder, in case of named parameters,array has to have array keys aligned with parameter names
|
620 |
+
*/
|
621 |
+
public function multipleParamRequests($sql, $params, $return = false)
|
622 |
+
{
|
623 |
+
// ensure windows/mac compatibility for user made requests
|
624 |
+
$sql = str_replace("\r\n", "\n", $sql);
|
625 |
+
$sqllines = explode("--", $sql);
|
626 |
+
foreach ($sqllines as $sqlline)
|
627 |
+
{
|
628 |
+
if ($sqlline != "")
|
629 |
+
{
|
630 |
+
$subs = explode(";\n", "--" . $sqlline);
|
631 |
+
foreach ($subs as $sub)
|
632 |
+
{
|
633 |
+
|
634 |
+
if (trim($sub) != "" && substr($sub, 0, 2) != "--")
|
635 |
+
{
|
636 |
+
$stmts[] = $sub;
|
637 |
+
}
|
638 |
+
}
|
639 |
+
}
|
640 |
+
}
|
641 |
+
$results = array();
|
642 |
+
foreach ($stmts as $stmt)
|
643 |
+
{
|
644 |
+
$zparams = $params;
|
645 |
+
$this->replaceParams($stmt, $zparams);
|
646 |
+
if ($return)
|
647 |
+
{
|
648 |
+
if (substr(trim($stmt), 0, 6) == "SELECT")
|
649 |
+
{
|
650 |
+
$results[$stmt] = $this->selectAll($stmt, $zparams);
|
651 |
+
continue;
|
652 |
+
}
|
653 |
+
}
|
654 |
+
$this->exec_stmt($stmt, $zparams);
|
655 |
+
}
|
656 |
+
if ($return)
|
657 |
+
{
|
658 |
+
return $results;
|
659 |
+
}
|
660 |
+
}
|
661 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/fshelper.php
ADDED
@@ -0,0 +1,478 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ('remotefilegetter.php');
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class FSHelper
|
6 |
+
*
|
7 |
+
* File System Helper
|
8 |
+
* Gives several utility methods for filesystem testing
|
9 |
+
*
|
10 |
+
* @author dweeves
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
class FSHelper
|
14 |
+
{
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Checks if a directory has write rights
|
18 |
+
*
|
19 |
+
* @param string $dir
|
20 |
+
* directory to test
|
21 |
+
* @return boolean wether directory is writable
|
22 |
+
*/
|
23 |
+
public static function isDirWritable($dir)
|
24 |
+
{
|
25 |
+
// try to create a new file
|
26 |
+
$test = @fopen("$dir/__testwr__", "w");
|
27 |
+
if ($test == false)
|
28 |
+
{
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
else
|
32 |
+
{
|
33 |
+
// if succeeded, remove test file
|
34 |
+
fclose($test);
|
35 |
+
unlink("$dir/__testwr__");
|
36 |
+
}
|
37 |
+
return true;
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Tries to find a suitable way to execute processes
|
42 |
+
*
|
43 |
+
* @return string NULL method to execute process
|
44 |
+
*/
|
45 |
+
public static function getExecMode()
|
46 |
+
{
|
47 |
+
$is_disabled = array();
|
48 |
+
// Check for php disabled functions
|
49 |
+
$disabled = explode(',', ini_get('disable_functions'));
|
50 |
+
foreach ($disabled as $disableFunction)
|
51 |
+
{
|
52 |
+
$is_disabled[] = trim($disableFunction);
|
53 |
+
}
|
54 |
+
// try the following if not disabled,return first non disabled
|
55 |
+
foreach (array("popen","shell_exec") as $func)
|
56 |
+
{
|
57 |
+
if (!in_array($func, $is_disabled))
|
58 |
+
{
|
59 |
+
return $func;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
return null;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Factory for magento directory handle
|
68 |
+
*
|
69 |
+
* @author dweeves
|
70 |
+
*
|
71 |
+
*/
|
72 |
+
class MagentoDirHandlerFactory
|
73 |
+
{
|
74 |
+
protected $_handlers = array();
|
75 |
+
protected static $_instance;
|
76 |
+
|
77 |
+
public function __construct()
|
78 |
+
{}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Singleton getInstance method
|
82 |
+
*
|
83 |
+
* @return MagentoDirHandlerFactory
|
84 |
+
*/
|
85 |
+
public static function getInstance()
|
86 |
+
{
|
87 |
+
if (!isset(self::$_instance))
|
88 |
+
{
|
89 |
+
self::$_instance = new MagentoDirHandlerFactory();
|
90 |
+
}
|
91 |
+
return self::$_instance;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Registers a new object to handle magento directory
|
96 |
+
*
|
97 |
+
* @param unknown $obj
|
98 |
+
*/
|
99 |
+
public function registerHandler($obj)
|
100 |
+
{
|
101 |
+
$cls = get_class($obj);
|
102 |
+
if (!isset($this->_handlers[$cls]))
|
103 |
+
{
|
104 |
+
$this->_handlers[$cls] = $obj;
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Return a handler for a given url
|
110 |
+
*
|
111 |
+
* @param unknown $url
|
112 |
+
* @return unknown
|
113 |
+
*/
|
114 |
+
public function getHandler($url)
|
115 |
+
{
|
116 |
+
// Iterates on declared handlers , return first matching url
|
117 |
+
foreach ($this->_handlers as $cls => $handler)
|
118 |
+
{
|
119 |
+
if ($handler->canHandle($url))
|
120 |
+
{
|
121 |
+
return $handler;
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Magento Directory Handler
|
129 |
+
*
|
130 |
+
* Provides methods for filesystem operations & command execution
|
131 |
+
* Mother abstract class to be derived either for local operation or remote (for performing operations on remote systems)
|
132 |
+
*
|
133 |
+
* @author dweeves
|
134 |
+
*
|
135 |
+
*/
|
136 |
+
abstract class MagentoDirHandler
|
137 |
+
{
|
138 |
+
protected $_magdir;
|
139 |
+
protected $_lasterror;
|
140 |
+
protected $_exec_mode;
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Constructor from a magento directory url
|
144 |
+
*
|
145 |
+
* @param unknown $magurl
|
146 |
+
* magento base directory url
|
147 |
+
*/
|
148 |
+
public function __construct($magurl)
|
149 |
+
{
|
150 |
+
$this->_magdir = $magurl;
|
151 |
+
$this->_lasterror = array();
|
152 |
+
$this->_exec_mode = FSHelper::getExecMode();
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Returns magento directory
|
157 |
+
*
|
158 |
+
* @return string
|
159 |
+
*/
|
160 |
+
public function getMagentoDir()
|
161 |
+
{
|
162 |
+
return $this->_magdir;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Returns available execution mode
|
167 |
+
*
|
168 |
+
* @return Ambigous <string, NULL>
|
169 |
+
*/
|
170 |
+
public function getexecmode()
|
171 |
+
{
|
172 |
+
return $this->_exec_mode;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Wether current handler is compatible with given url
|
177 |
+
*
|
178 |
+
* @param unknown $url
|
179 |
+
*/
|
180 |
+
public abstract function canhandle($url);
|
181 |
+
|
182 |
+
/**
|
183 |
+
* File exists
|
184 |
+
*
|
185 |
+
* @param unknown $filepath
|
186 |
+
*/
|
187 |
+
public abstract function file_exists($filepath);
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Mkdir
|
191 |
+
*
|
192 |
+
* @param unknown $path
|
193 |
+
* @param string $mask
|
194 |
+
* @param string $rec
|
195 |
+
*/
|
196 |
+
public abstract function mkdir($path, $mask = null, $rec = false);
|
197 |
+
|
198 |
+
/**
|
199 |
+
* File Copy
|
200 |
+
*
|
201 |
+
* @param unknown $srcpath
|
202 |
+
* @param unknown $destpath
|
203 |
+
*/
|
204 |
+
public abstract function copy($srcpath, $destpath);
|
205 |
+
|
206 |
+
/**
|
207 |
+
* File Deletion
|
208 |
+
*
|
209 |
+
* @param unknown $path
|
210 |
+
*/
|
211 |
+
public abstract function unlink($path);
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Chmod
|
215 |
+
*
|
216 |
+
* @param unknown $path
|
217 |
+
* @param unknown $mask
|
218 |
+
*/
|
219 |
+
public abstract function chmod($path, $mask);
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Check if we can execute processes
|
223 |
+
*
|
224 |
+
* @return boolean
|
225 |
+
*/
|
226 |
+
public function isExecEnabled()
|
227 |
+
{
|
228 |
+
return $this->_exec_mode != null;
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Executes a process
|
233 |
+
*
|
234 |
+
* @param unknown $cmd
|
235 |
+
* @param unknown $params
|
236 |
+
* @param string $workingdir
|
237 |
+
*/
|
238 |
+
public abstract function exec_cmd($cmd, $params, $workingdir = null);
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Local Magento Dir Handler.
|
243 |
+
*
|
244 |
+
* Handle Magento related filesystem operations for a given local directory
|
245 |
+
*
|
246 |
+
* @author dweeves
|
247 |
+
*
|
248 |
+
*/
|
249 |
+
class LocalMagentoDirHandler extends MagentoDirHandler
|
250 |
+
{
|
251 |
+
protected $_rfgid;
|
252 |
+
|
253 |
+
/**
|
254 |
+
* Constructor
|
255 |
+
*
|
256 |
+
* @param unknown $magdir
|
257 |
+
*/
|
258 |
+
public function __construct($magdir)
|
259 |
+
{
|
260 |
+
parent::__construct($magdir);
|
261 |
+
// Registers itself in the factory
|
262 |
+
MagentoDirHandlerFactory::getInstance()->registerHandler($this);
|
263 |
+
$this->_rfgid = "default";
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* Can Handle any non remote urls
|
268 |
+
*
|
269 |
+
* @param unknown $url
|
270 |
+
* @return boolean
|
271 |
+
*/
|
272 |
+
public function canHandle($url)
|
273 |
+
{
|
274 |
+
return (preg_match("|^.*?://.*$|", $url) == false);
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Cleans a bit input filename, ensures filename will be located under magento directory if not already
|
279 |
+
*
|
280 |
+
* @see MagentoDirHandler::file_exists()
|
281 |
+
*/
|
282 |
+
public function file_exists($filename)
|
283 |
+
{
|
284 |
+
$mp = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $filename));
|
285 |
+
|
286 |
+
return file_exists($mp);
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Specific, set remote operation credentials for local file download
|
291 |
+
*/
|
292 |
+
public function setRemoteCredentials($user, $passwd)
|
293 |
+
{
|
294 |
+
$fginst = RemoteFileGetterFactory::getFGInstance($this->_rfgid);
|
295 |
+
$fginst->setCredentials($user, $passwd);
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Handles a remote file getter id
|
300 |
+
*
|
301 |
+
* @param unknown $rfgid
|
302 |
+
*/
|
303 |
+
public function setRemoteGetterId($rfgid)
|
304 |
+
{
|
305 |
+
$this->_rfgid = $rfgid;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* ensures dirname will be located under magento directory if not already
|
310 |
+
*
|
311 |
+
* @see MagentoDirHandler::mkdir()
|
312 |
+
*/
|
313 |
+
public function mkdir($path, $mask = null, $rec = false)
|
314 |
+
{
|
315 |
+
$mp = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $path));
|
316 |
+
|
317 |
+
if ($mask == null)
|
318 |
+
{
|
319 |
+
$mask = octdec('755');
|
320 |
+
}
|
321 |
+
$ok = @mkdir($mp, $mask, $rec);
|
322 |
+
if (!$ok)
|
323 |
+
{
|
324 |
+
$this->_lasterror = error_get_last();
|
325 |
+
}
|
326 |
+
return $ok;
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* ensures path will be located under magento directory if not already
|
331 |
+
*
|
332 |
+
* @see MagentoDirHandler::chmod()
|
333 |
+
*/
|
334 |
+
public function chmod($path, $mask)
|
335 |
+
{
|
336 |
+
$mp = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $path));
|
337 |
+
|
338 |
+
if ($mask == null)
|
339 |
+
{
|
340 |
+
$mask = octdec('755');
|
341 |
+
}
|
342 |
+
$ok = @chmod($mp, $mask);
|
343 |
+
if (!$ok)
|
344 |
+
{
|
345 |
+
$this->_lasterror = error_get_last();
|
346 |
+
}
|
347 |
+
return $ok;
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* Returns last error
|
352 |
+
*
|
353 |
+
* @return Ambigous <multitype:, multitype:string multitype: >
|
354 |
+
*/
|
355 |
+
public function getLastError()
|
356 |
+
{
|
357 |
+
return $this->_lasterror;
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* ensures filename will be located under magento directory if not already
|
362 |
+
*
|
363 |
+
* @see MagentoDirHandler::unlink()
|
364 |
+
*/
|
365 |
+
public function unlink($path)
|
366 |
+
{
|
367 |
+
$mp = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $path));
|
368 |
+
return @unlink($mp);
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* Download a file into local filesystem
|
373 |
+
* ensures local filename will be located under magento directory if not already
|
374 |
+
*
|
375 |
+
* @param unknown $remoteurl
|
376 |
+
* @param unknown $destpath
|
377 |
+
* @return unknown
|
378 |
+
*/
|
379 |
+
public function copyFromRemote($remoteurl, $destpath)
|
380 |
+
{
|
381 |
+
$rfg = RemoteFileGetterFactory::getFGInstance($this->_rfgid);
|
382 |
+
$mp = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $destpath));
|
383 |
+
$ok = $rfg->copyRemoteFile($remoteurl, $mp);
|
384 |
+
if (!$ok)
|
385 |
+
{
|
386 |
+
$this->_lasterror = $rfg->getErrors();
|
387 |
+
}
|
388 |
+
return $ok;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* ensures filename will be located under magento directory if not already
|
393 |
+
*
|
394 |
+
* @see MagentoDirHandler::copy()
|
395 |
+
*/
|
396 |
+
public function copy($srcpath, $destpath)
|
397 |
+
{
|
398 |
+
$result = false;
|
399 |
+
$destpath = str_replace("//", "/", $this->_magdir . "/" . str_replace($this->_magdir, '', $destpath));
|
400 |
+
if (preg_match('|^.*?://.*$|', $srcpath))
|
401 |
+
{
|
402 |
+
$result = $this->copyFromRemote($srcpath, $destpath);
|
403 |
+
}
|
404 |
+
else
|
405 |
+
{
|
406 |
+
|
407 |
+
$result = @copy($srcpath, $destpath);
|
408 |
+
if (!$result)
|
409 |
+
{
|
410 |
+
$this->_lasterror = error_get_last();
|
411 |
+
}
|
412 |
+
}
|
413 |
+
return $result;
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* execute command, performs some execution directory check
|
418 |
+
* uses available command execution method
|
419 |
+
*
|
420 |
+
* @see MagentoDirHandler::exec_cmd()
|
421 |
+
*/
|
422 |
+
public function exec_cmd($cmd, $params, $working_dir = null)
|
423 |
+
{
|
424 |
+
$full_cmd = $cmd . " " . $params;
|
425 |
+
$curdir = false;
|
426 |
+
$precmd = "";
|
427 |
+
// If a working directory has been specified, switch to it
|
428 |
+
// before running the requested command
|
429 |
+
if (!empty($working_dir))
|
430 |
+
{
|
431 |
+
$curdir = getcwd();
|
432 |
+
$wdir = realpath($working_dir);
|
433 |
+
// get current directory
|
434 |
+
if ($curdir != $wdir && $wdir !== false)
|
435 |
+
{
|
436 |
+
// trying to change using chdir
|
437 |
+
if (!@chdir($wdir))
|
438 |
+
{
|
439 |
+
// if no success, use cd from shell
|
440 |
+
$precmd = "cd $wdir && ";
|
441 |
+
}
|
442 |
+
}
|
443 |
+
}
|
444 |
+
$full_cmd = $precmd . $full_cmd;
|
445 |
+
// Handle Execution
|
446 |
+
$emode = $this->getexecmode();
|
447 |
+
switch ($emode)
|
448 |
+
{
|
449 |
+
case "popen":
|
450 |
+
$x = popen($full_cmd, "r");
|
451 |
+
$out = "";
|
452 |
+
while (!feof($x))
|
453 |
+
{
|
454 |
+
$data = fread($x, 1024);
|
455 |
+
$out .= $data;
|
456 |
+
usleep(100000);
|
457 |
+
}
|
458 |
+
fclose($x);
|
459 |
+
break;
|
460 |
+
case "shell_exec":
|
461 |
+
$out = shell_exec($full_cmd);
|
462 |
+
break;
|
463 |
+
}
|
464 |
+
|
465 |
+
// restore old directory if changed
|
466 |
+
if ($curdir)
|
467 |
+
{
|
468 |
+
@chdir($curdir);
|
469 |
+
}
|
470 |
+
|
471 |
+
if ($out == null)
|
472 |
+
{
|
473 |
+
$this->_lasterror = array("type"=>" execution error","message"=>error_get_last());
|
474 |
+
return false;
|
475 |
+
}
|
476 |
+
return $out;
|
477 |
+
}
|
478 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/license.txt
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright (C) 2012 by Dweeves (S.BRACQUEMONT)
|
2 |
+
|
3 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4 |
+
of this software and associated documentation files (the "Software"), to deal
|
5 |
+
in the Software without restriction, including without limitation the rights
|
6 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7 |
+
copies of the Software, and to permit persons to whom the Software is
|
8 |
+
furnished to do so, subject to the following conditions:
|
9 |
+
|
10 |
+
The above copyright notice and this permission notice shall be included in
|
11 |
+
all copies or substantial portions of the Software.
|
12 |
+
|
13 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19 |
+
THE SOFTWARE.
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_config.php
ADDED
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("properties.php");
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Directory based configuration object
|
6 |
+
* Uses a property file
|
7 |
+
*
|
8 |
+
* @author dweeves
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
class DirbasedConfig extends Properties
|
12 |
+
{
|
13 |
+
protected $_basedir = null;
|
14 |
+
protected $_confname = null;
|
15 |
+
|
16 |
+
public function __construct($basedir, $confname)
|
17 |
+
{
|
18 |
+
$this->_basedir = $basedir;
|
19 |
+
$this->_confname = $basedir . DIRSEP . $confname;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function get($secname, $pname, $default = null)
|
23 |
+
{
|
24 |
+
if (!isset($this->_props))
|
25 |
+
{
|
26 |
+
$this->load();
|
27 |
+
}
|
28 |
+
return parent::get($secname, $pname, $default);
|
29 |
+
}
|
30 |
+
|
31 |
+
public function getConfFile()
|
32 |
+
{
|
33 |
+
return $this->_confname;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function getLastSaved($fmt)
|
37 |
+
{
|
38 |
+
return strftime($fmt, filemtime($this->_confname));
|
39 |
+
}
|
40 |
+
|
41 |
+
public function load($name = null)
|
42 |
+
{
|
43 |
+
if ($name == null)
|
44 |
+
{
|
45 |
+
$name = $this->_confname;
|
46 |
+
}
|
47 |
+
|
48 |
+
if (!file_exists($name))
|
49 |
+
{
|
50 |
+
$this->save();
|
51 |
+
}
|
52 |
+
parent::load($name);
|
53 |
+
}
|
54 |
+
|
55 |
+
public function save($arr = null)
|
56 |
+
{
|
57 |
+
if ($arr != null)
|
58 |
+
{
|
59 |
+
$this->setPropsFromFlatArray($arr);
|
60 |
+
}
|
61 |
+
return parent::save($this->_confname);
|
62 |
+
}
|
63 |
+
|
64 |
+
public function saveTo($arr, $newdir)
|
65 |
+
{
|
66 |
+
if (!file_exists($newdir))
|
67 |
+
{
|
68 |
+
mkdir($newdir, Magmi_Config::getInstance()->getDirMask());
|
69 |
+
}
|
70 |
+
$val = parent::save($newdir . DIRSEP . basename($this->_confname));
|
71 |
+
$this->_basedir = $newdir;
|
72 |
+
$this->_confname = $newdir . DIRSEP . basename($this->_confname);
|
73 |
+
return $val;
|
74 |
+
}
|
75 |
+
|
76 |
+
public function getConfDir()
|
77 |
+
{
|
78 |
+
return $this->_basedir;
|
79 |
+
}
|
80 |
+
}
|
81 |
+
|
82 |
+
class ProfileBasedConfig extends DirbasedConfig
|
83 |
+
{
|
84 |
+
private static $_script = __FILE__;
|
85 |
+
protected $_profile = null;
|
86 |
+
|
87 |
+
public function getProfileDir()
|
88 |
+
{
|
89 |
+
$subdir = ($this->_profile == "default" ? "" : DIRSEP . $this->_profile);
|
90 |
+
$confdir = dirname(dirname(__FILE__)) . DIRSEP . "conf$subdir";
|
91 |
+
if (!file_exists($confdir))
|
92 |
+
{
|
93 |
+
@mkdir($confdir, Magmi_Config::getInstance()->getDirMask());
|
94 |
+
}
|
95 |
+
return realpath($confdir);
|
96 |
+
}
|
97 |
+
|
98 |
+
public function __construct($fname, $profile = null)
|
99 |
+
{
|
100 |
+
$this->_profile = $profile;
|
101 |
+
parent::__construct($this->getProfileDir(), $fname);
|
102 |
+
}
|
103 |
+
|
104 |
+
public function getProfile()
|
105 |
+
{
|
106 |
+
return $this->_profile;
|
107 |
+
}
|
108 |
+
}
|
109 |
+
|
110 |
+
class Magmi_Config extends DirbasedConfig
|
111 |
+
{
|
112 |
+
private static $_instance = null;
|
113 |
+
private $_defaultconfigname = null;
|
114 |
+
public static $conffile = null;
|
115 |
+
|
116 |
+
public function getConfDir()
|
117 |
+
{
|
118 |
+
$confdir = realpath(dirname(dirname(__FILE__)) . DIRSEP . "conf");
|
119 |
+
return $confdir;
|
120 |
+
}
|
121 |
+
|
122 |
+
public function __construct()
|
123 |
+
{
|
124 |
+
parent::__construct($this->getConfDir(), "magmi.ini");
|
125 |
+
}
|
126 |
+
|
127 |
+
public function getDirMask()
|
128 |
+
{
|
129 |
+
return octdec($this->get("GLOBAL", "dirmask", "755"));
|
130 |
+
}
|
131 |
+
|
132 |
+
public function getFileMask()
|
133 |
+
{
|
134 |
+
return octdec($this->get("GLOBAL", "filemask", "644"));
|
135 |
+
}
|
136 |
+
|
137 |
+
public function getMagentoDir()
|
138 |
+
{
|
139 |
+
$bd = $this->get("MAGENTO", "basedir");
|
140 |
+
$dp = $bd[0] == "." ? dirname(__FILE__) . "/" . $bd : $bd;
|
141 |
+
return realpath($dp);
|
142 |
+
}
|
143 |
+
|
144 |
+
public static function getInstance()
|
145 |
+
{
|
146 |
+
if (self::$_instance == null)
|
147 |
+
{
|
148 |
+
self::$_instance = new Magmi_Config();
|
149 |
+
}
|
150 |
+
return self::$_instance;
|
151 |
+
}
|
152 |
+
|
153 |
+
public function isDefault()
|
154 |
+
{
|
155 |
+
return !file_exists($this->_confname);
|
156 |
+
}
|
157 |
+
|
158 |
+
public function load($name = null)
|
159 |
+
{
|
160 |
+
$conf = (!$this->isDefault()) ? $this->_confname : $this->_confname . ".default";
|
161 |
+
parent::load($conf);
|
162 |
+
$alt = false;
|
163 |
+
if ($this->hasSection('USE_ALTERNATE'))
|
164 |
+
{
|
165 |
+
$this->_confname = $this->get("USE_ALTERNATE", "file");
|
166 |
+
$alt = true;
|
167 |
+
}
|
168 |
+
parent::load($this->_confname);
|
169 |
+
if ($alt)
|
170 |
+
{
|
171 |
+
$this->set("USE_ALTERNATE", "file", $this->_confname);
|
172 |
+
}
|
173 |
+
// Migration from 0.6.17
|
174 |
+
if ($this->hasSection("PLUGINS_DATASOURCES"))
|
175 |
+
{
|
176 |
+
$pluginsconf = new DirbasedConfig($this->getConfDir(), "plugins.conf");
|
177 |
+
$arr = array("PLUGINS_DATASOURCES"=>$this->getSection("PLUGINS_DATASOURCES"),
|
178 |
+
"PLUGINS_GENERAL"=>$this->getSection("PLUGINS_GENERAL"),
|
179 |
+
"PLUGINS_ITEMPROCESSORS"=>$this->getSection("PLUGINS_ITEMPROCESSORS"));
|
180 |
+
$pluginsconf->setProps($arr);
|
181 |
+
$pluginsconf->save();
|
182 |
+
$this->removeSection("PLUGINS_DATASOURCES");
|
183 |
+
$this->removeSection("PLUGINS_GENERAL");
|
184 |
+
$this->removeSection("PLUGINS_ITEMPROCESSORS");
|
185 |
+
$this->save();
|
186 |
+
}
|
187 |
+
// Migration step (to percent) , 0.7beta4
|
188 |
+
if ($this->get("GLOBAL", "step", 0) == 0 || floatval($this->get("GLOBAL", "step", 0.5)) > 20)
|
189 |
+
{
|
190 |
+
$this->set("GLOBAL", "step", 0.5);
|
191 |
+
$this->save();
|
192 |
+
}
|
193 |
+
return $this;
|
194 |
+
}
|
195 |
+
|
196 |
+
public function save($arr = null)
|
197 |
+
{
|
198 |
+
if (isset($arr["USE_ALTERNATE:file"]))
|
199 |
+
{
|
200 |
+
$this->_confname = $arr["USE_ALTERNATE:file"];
|
201 |
+
unset($arr["USE_ALTERNATE:file"]);
|
202 |
+
}
|
203 |
+
if ($arr !== null)
|
204 |
+
{
|
205 |
+
foreach ($arr as $k => $v)
|
206 |
+
{
|
207 |
+
if (!preg_match("/\w+:\w+/", $k))
|
208 |
+
{
|
209 |
+
unset($arr[$k]);
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
return parent::save($arr);
|
214 |
+
}
|
215 |
+
|
216 |
+
public function getProfileList()
|
217 |
+
{
|
218 |
+
$proflist = array();
|
219 |
+
$candidates = scandir($this->getConfDir());
|
220 |
+
foreach ($candidates as $candidate)
|
221 |
+
{
|
222 |
+
if (is_dir($this->getConfDir() . DIRSEP . $candidate) && $candidate[0] != "." &&
|
223 |
+
substr($candidate, 0, 2) != "__")
|
224 |
+
{
|
225 |
+
$proflist[] = $candidate;
|
226 |
+
}
|
227 |
+
}
|
228 |
+
return $proflist;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
class EnabledPlugins_Config extends ProfileBasedConfig
|
233 |
+
{
|
234 |
+
|
235 |
+
public function __construct($profile = "default")
|
236 |
+
{
|
237 |
+
parent::__construct("plugins.conf", $profile);
|
238 |
+
}
|
239 |
+
|
240 |
+
public function getEnabledPluginFamilies($typelist)
|
241 |
+
{
|
242 |
+
$btlist = array();
|
243 |
+
if (!is_array($typelist))
|
244 |
+
{
|
245 |
+
$typelist = explode(",", $typelist);
|
246 |
+
}
|
247 |
+
foreach ($typelist as $pfamily)
|
248 |
+
{
|
249 |
+
$btlist[$pfamily] = $this->getEnabledPluginClasses($pfamily);
|
250 |
+
}
|
251 |
+
return $btlist;
|
252 |
+
}
|
253 |
+
|
254 |
+
public function getEnabledPluginClasses($type)
|
255 |
+
{
|
256 |
+
$type = strtoupper($type);
|
257 |
+
$cslist = $this->get("PLUGINS_$type", "classes");
|
258 |
+
if ($cslist == null)
|
259 |
+
{
|
260 |
+
$cslist = $this->get("PLUGINS_$type", "class");
|
261 |
+
$epc = ($cslist == null ? array() : array($cslist));
|
262 |
+
}
|
263 |
+
else
|
264 |
+
{
|
265 |
+
$epc = ($cslist == "" ? array() : explode(",", $cslist));
|
266 |
+
}
|
267 |
+
return $epc;
|
268 |
+
}
|
269 |
+
|
270 |
+
public function isPluginEnabled($type, $pclass)
|
271 |
+
{
|
272 |
+
return in_array($pclass, $this->getEnabledPluginClasses($type));
|
273 |
+
}
|
274 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_defs.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
define("MAGMI_BASEDIR", dirname(dirname(__FILE__)));
|
3 |
+
define("MAGMI_INCDIR", MAGMI_BASEDIR . "/inc");
|
4 |
+
define("MAGMI_INTEGRATION_INCDIR", MAGMI_BASEDIR . "/integration/inc");
|
5 |
+
define("MAGMI_ENGINE_DIR", MAGMI_BASEDIR . "/engines");
|
6 |
+
set_include_path(
|
7 |
+
ini_get("include_path") . PATH_SEPARATOR . MAGMI_INCDIR . PATH_SEPARATOR . MAGMI_INTEGRATION_INCDIR . PATH_SEPARATOR .
|
8 |
+
MAGMI_ENGINE_DIR);
|
9 |
+
$dtz = date_default_timezone_get();
|
10 |
+
if ($dtz == "")
|
11 |
+
{
|
12 |
+
date_default_timezone_set("UTC");
|
13 |
+
}
|
14 |
+
require_once ('magmi_loggers.php');
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_engine.php
ADDED
@@ -0,0 +1,559 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("dbhelper.class.php");
|
3 |
+
require_once ("magmi_config.php");
|
4 |
+
require_once ("magmi_version.php");
|
5 |
+
require_once ("magmi_utils.php");
|
6 |
+
require_once ("magmi_statemanager.php");
|
7 |
+
require_once ("magmi_pluginhelper.php");
|
8 |
+
|
9 |
+
/**
|
10 |
+
* This class is the mother class for magmi engines
|
11 |
+
* A magmi engine is a class that performs operations on DB
|
12 |
+
*
|
13 |
+
* @author dweeves
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
abstract class Magmi_Engine extends DbHelper
|
17 |
+
{
|
18 |
+
protected $_conf;
|
19 |
+
protected $_initialized = false;
|
20 |
+
protected $_exceptions = array();
|
21 |
+
public $tprefix;
|
22 |
+
protected $_connected;
|
23 |
+
protected $_activeplugins;
|
24 |
+
protected $_pluginclasses;
|
25 |
+
protected $_builtinplugins = array();
|
26 |
+
protected $_ploop_callbacks = array();
|
27 |
+
private $_excid = 0;
|
28 |
+
public $logger = null;
|
29 |
+
protected $_timingcats = array();
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Engine Metadata Table access
|
33 |
+
*/
|
34 |
+
public function getEngineInfo()
|
35 |
+
{
|
36 |
+
return array("name"=>"Generic Magmi Engine","version"=>"1.1","author"=>"dweeves");
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor
|
41 |
+
*/
|
42 |
+
public function __construct()
|
43 |
+
{
|
44 |
+
parent::__construct();
|
45 |
+
// force PHP internal encoding as UTF 8
|
46 |
+
mb_internal_encoding("UTF-8");
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Engine initialization @param params : key/value array of initialization parameters
|
51 |
+
*/
|
52 |
+
public final function initialize($params = array())
|
53 |
+
{
|
54 |
+
try
|
55 |
+
{
|
56 |
+
// Retrieving master config file
|
57 |
+
$this->_conf = Magmi_Config::getInstance();
|
58 |
+
$this->_conf->load();
|
59 |
+
// Intializing members
|
60 |
+
$this->tprefix = $this->_conf->get("DATABASE", "table_prefix");
|
61 |
+
$this->_excid = 0;
|
62 |
+
$this->_initialized = true;
|
63 |
+
$this->_exceptions = array();
|
64 |
+
}
|
65 |
+
catch (Exception $e)
|
66 |
+
{
|
67 |
+
die("Error initializing Engine:{$this->_conf->getConfigFilename()} \n" . $e->getMessage());
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Returns magento directory
|
73 |
+
*/
|
74 |
+
public function getMagentoDir()
|
75 |
+
{
|
76 |
+
return $this->_conf->getMagentoDir();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* returns magento version
|
81 |
+
*/
|
82 |
+
public function getMagentoVersion()
|
83 |
+
{
|
84 |
+
return $this->_conf->get("MAGENTO", "version");
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Plugin loop callback registration
|
89 |
+
*/
|
90 |
+
protected function _registerPluginLoopCallback($cbtype, $cb)
|
91 |
+
{
|
92 |
+
$this->_ploop_callbacks[$cbtype] = $cb;
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Plugin loop callback deregistration
|
97 |
+
*/
|
98 |
+
protected function _unregisterPluginLoopCallback($cbtype)
|
99 |
+
{
|
100 |
+
unset($this->_ploop_callbacks[$cbtype]);
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Generic implementation of plugin families, empty for this mother class
|
105 |
+
*/
|
106 |
+
public function getPluginFamilies()
|
107 |
+
{
|
108 |
+
return array();
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* return the list of enabled plugin classes for a given profile @param $profile : profile name to check
|
113 |
+
*/
|
114 |
+
public function getEnabledPluginClasses($profile)
|
115 |
+
{
|
116 |
+
$enabledplugins = new EnabledPlugins_Config($profile);
|
117 |
+
$enabledplugins->load();
|
118 |
+
return $enabledplugins->getEnabledPluginFamilies($this->getPluginFamilies());
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* initializes Plugin instances for a given profile @param $profile : profile to initialize plugins for , defaults to null (Default Profile)
|
123 |
+
*/
|
124 |
+
public function initPlugins($profile = null)
|
125 |
+
{
|
126 |
+
// reset _active plugins in case of Engine reuse
|
127 |
+
$this->_activeplugins = array();
|
128 |
+
$this->_pluginclasses = $this->getEnabledPluginClasses($profile);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Returns a list of class names for "Builtin" plugins
|
133 |
+
*/
|
134 |
+
public function getBuiltinPluginClasses()
|
135 |
+
{
|
136 |
+
$bplarr = array();
|
137 |
+
|
138 |
+
foreach ($this->_builtinplugins as $pfamily => $pdef)
|
139 |
+
{
|
140 |
+
$plinfo = explode("::", $pdef);
|
141 |
+
$pfile = $plinfo[0];
|
142 |
+
$pclass = $plinfo[1];
|
143 |
+
require_once ($pfile);
|
144 |
+
if (!isset($bplarr[$pfamily]))
|
145 |
+
{
|
146 |
+
$bplarr[$pfamily] = array();
|
147 |
+
}
|
148 |
+
$bplarr[$pfamily][] = $pclass;
|
149 |
+
}
|
150 |
+
return $bplarr;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* Return the list of enabled plugin classes
|
155 |
+
*/
|
156 |
+
public function getPluginClasses()
|
157 |
+
{
|
158 |
+
return $this->_pluginclasses;
|
159 |
+
}
|
160 |
+
|
161 |
+
/*
|
162 |
+
* Return the list of active plugin instances for a given plugin family @param $family : plugin family to get instances from, defaults to null (all plugins)
|
163 |
+
*/
|
164 |
+
public function getPluginInstances($family = null)
|
165 |
+
{
|
166 |
+
$pil = null;
|
167 |
+
// if no family set, return all active plugins
|
168 |
+
if ($family == null)
|
169 |
+
{
|
170 |
+
$pil = $this->_activeplugins();
|
171 |
+
}
|
172 |
+
else
|
173 |
+
// filter active plugins by family
|
174 |
+
{
|
175 |
+
$pil = (isset($this->_activeplugins[$family]) ? $this->_activeplugins[$family] : array());
|
176 |
+
}
|
177 |
+
return $pil;
|
178 |
+
}
|
179 |
+
|
180 |
+
/*
|
181 |
+
* Force Builtin plugin classes list with a list of classes for a given plugin family @param $family : family of builtin plugins to set @param $pclasses : array of plugin class names to set as buitin for this engine
|
182 |
+
*/
|
183 |
+
public function setBuiltinPluginClasses($pfamily, $pclasses)
|
184 |
+
{
|
185 |
+
$this->_builtinplugins[$pfamily] = $pclasses;
|
186 |
+
}
|
187 |
+
|
188 |
+
/*
|
189 |
+
* Plugin sorting callback for call order in the same execution step. Sorts by filename
|
190 |
+
*/
|
191 |
+
public function sortPlugins($p1, $p2)
|
192 |
+
{
|
193 |
+
$m1 = $p1->getPluginMeta();
|
194 |
+
if ($m1 == null)
|
195 |
+
{
|
196 |
+
return 1;
|
197 |
+
}
|
198 |
+
$m2 = $p2->getPluginMeta();
|
199 |
+
if ($m2 == null)
|
200 |
+
{
|
201 |
+
return -1;
|
202 |
+
}
|
203 |
+
return strcmp($m1["file"], $m2["file"]);
|
204 |
+
}
|
205 |
+
|
206 |
+
/*
|
207 |
+
* Create plugin instances for a given profile @param $profile : profile name to create plugins for @param $params : configuration parameters for the profile (all plugins)
|
208 |
+
*/
|
209 |
+
public function createPlugins($profile, $params)
|
210 |
+
{
|
211 |
+
// Get Plugin Helper instance
|
212 |
+
$plhelper = Magmi_PluginHelper::getInstance($profile);
|
213 |
+
// Merge Builtin Plugin classes with current plugin classes
|
214 |
+
$this->_pluginclasses = array_merge_recursive($this->_pluginclasses, $this->getBuiltinPluginClasses());
|
215 |
+
// Iterate on plugin classes by family
|
216 |
+
foreach ($this->_pluginclasses as $pfamily => $pclasses)
|
217 |
+
{
|
218 |
+
// If family name starts with *
|
219 |
+
if ($pfamily[0] == "*")
|
220 |
+
{
|
221 |
+
// use the real family name (after *)
|
222 |
+
$this->_pluginclasses[substr($pfamily, 1)] = $pclasses;
|
223 |
+
// clear the * pseudo family
|
224 |
+
unset($this->_pluginclasses[$pfamily]);
|
225 |
+
}
|
226 |
+
}
|
227 |
+
|
228 |
+
// Iterate on final plugin classes list
|
229 |
+
foreach ($this->_pluginclasses as $pfamily => $pclasses)
|
230 |
+
{
|
231 |
+
// If there is no active plugins in the current family
|
232 |
+
if (!isset($this->_activeplugins[$pfamily]))
|
233 |
+
{
|
234 |
+
// initialize active plugins for plugin family
|
235 |
+
$this->_activeplugins[$pfamily] = array();
|
236 |
+
}
|
237 |
+
// For all plugin classes in current family
|
238 |
+
foreach ($pclasses as $pclass)
|
239 |
+
{
|
240 |
+
// Create a new instance of plugin with parameters
|
241 |
+
// Add it to the list of active plugins in the current family
|
242 |
+
$this->_activeplugins[$pfamily][] = $plhelper->createInstance($pfamily, $pclass, $params, $this);
|
243 |
+
}
|
244 |
+
// Sort family plugins with plugin sorting callback
|
245 |
+
usort($this->_activeplugins[$pfamily], array(&$this,"sortPlugins"));
|
246 |
+
}
|
247 |
+
}
|
248 |
+
|
249 |
+
/*
|
250 |
+
* Retrieve all active plugins instances for a give plugin class name
|
251 |
+
*/
|
252 |
+
public function getPluginInstanceByClassName($pfamily, $pclassname)
|
253 |
+
{
|
254 |
+
$inst = null;
|
255 |
+
if (isset($this->_activeplugins[$pfamily]))
|
256 |
+
{
|
257 |
+
foreach ($this->_activeplugins[$pfamily] as $pinstance)
|
258 |
+
{
|
259 |
+
if (get_class($pinstance) == $pclassname)
|
260 |
+
{
|
261 |
+
$inst = $pinstance;
|
262 |
+
break;
|
263 |
+
}
|
264 |
+
}
|
265 |
+
}
|
266 |
+
return $inst;
|
267 |
+
}
|
268 |
+
|
269 |
+
/*
|
270 |
+
* Get a plugin instance in a family based on it's execution order
|
271 |
+
*/
|
272 |
+
public function getPluginInstance($family, $order = -1)
|
273 |
+
{
|
274 |
+
if ($order < 0)
|
275 |
+
{
|
276 |
+
$order += count($this->_activeplugins[$family]);
|
277 |
+
}
|
278 |
+
return $this->_activeplugins[$family][$order];
|
279 |
+
}
|
280 |
+
|
281 |
+
/*
|
282 |
+
* Plugin call generic callback for engine @param $types : plugin types to call @param $callback : processing step to call @param $data : (reference) , data to pass to plugin processing @param $params : extra parameters for processing step @param $break : flag to stop calling chain at first plugin returning false (defaults to true)
|
283 |
+
*/
|
284 |
+
public function callPlugins($types, $callback, &$data = null, $params = null, $break = true)
|
285 |
+
{
|
286 |
+
$result = true;
|
287 |
+
|
288 |
+
// If plugin type list is not an array , process it as string
|
289 |
+
if (!is_array($types))
|
290 |
+
{
|
291 |
+
// If plugin is not wildcard , build array of types based on comma separated string
|
292 |
+
if ($types != "*")
|
293 |
+
{
|
294 |
+
$types = explode(",", $types);
|
295 |
+
}
|
296 |
+
else
|
297 |
+
{
|
298 |
+
$types = array_keys($this->_activeplugins);
|
299 |
+
}
|
300 |
+
}
|
301 |
+
|
302 |
+
// Timing initialization (global processing step)
|
303 |
+
$this->_timecounter->initTime($callback, get_class($this));
|
304 |
+
|
305 |
+
// Iterate on plugin types (families)
|
306 |
+
foreach ($types as $ptype)
|
307 |
+
{
|
308 |
+
// If there is at least one active plugin in this family
|
309 |
+
if (isset($this->_activeplugins[$ptype]))
|
310 |
+
{
|
311 |
+
// For all instances in the family
|
312 |
+
foreach ($this->_activeplugins[$ptype] as $pinst)
|
313 |
+
{
|
314 |
+
// If the plugin has a hook for the defined processing step
|
315 |
+
if (method_exists($pinst, $callback))
|
316 |
+
{
|
317 |
+
// Timing initialization for current plugin in processing step
|
318 |
+
$this->_timecounter->initTime($callback, get_class($pinst));
|
319 |
+
// Perform plugin call
|
320 |
+
// either with or without parameters,or parameters & data
|
321 |
+
// store execution result
|
322 |
+
$callres = ($data == null ? ($params == null ? $pinst->$callback() : $pinst->$callback($params)) : $pinst->$callback(
|
323 |
+
$data, $params));
|
324 |
+
// End Timing for current plugin in current step
|
325 |
+
$this->_timecounter->exitTime($callback, get_class($pinst));
|
326 |
+
// if plugin call result is false with data set
|
327 |
+
if ($callres === false && $data != null)
|
328 |
+
{
|
329 |
+
// final result is false
|
330 |
+
$result = false;
|
331 |
+
}
|
332 |
+
// If there is a register callback for the plugin processing loop
|
333 |
+
if (isset($this->_ploop_callbacks[$callback]))
|
334 |
+
{
|
335 |
+
$cb = $this->_ploop_callbacks[$callback];
|
336 |
+
// Call the plugin processing loop callback , time it
|
337 |
+
$this->_timecounter->initTime($callback, get_class($pinst));
|
338 |
+
$this->$cb($pinst, $data, $result);
|
339 |
+
$this->_timecounter->exitTime($callback, get_class($pinst));
|
340 |
+
}
|
341 |
+
// if last result plugin is false & break flag
|
342 |
+
if ($result === false && $break)
|
343 |
+
{
|
344 |
+
// End timing
|
345 |
+
$this->_timecounter->exitTime($callback, get_class($this));
|
346 |
+
// return false
|
347 |
+
return $result;
|
348 |
+
}
|
349 |
+
}
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
// Nothing broke, end timing
|
354 |
+
$this->_timecounter->exitTime($callback, get_class($this));
|
355 |
+
// Return plugin call result
|
356 |
+
return $result;
|
357 |
+
}
|
358 |
+
|
359 |
+
public function getParam($params, $pname, $default = null)
|
360 |
+
{
|
361 |
+
return isset($params[$pname]) ? $params[$pname] : $default;
|
362 |
+
}
|
363 |
+
|
364 |
+
public function setLogger($logger)
|
365 |
+
{
|
366 |
+
$this->logger = $logger;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* logging function
|
371 |
+
*
|
372 |
+
* @param string $data
|
373 |
+
* : string to log
|
374 |
+
* @param string $type
|
375 |
+
* : log type
|
376 |
+
*/
|
377 |
+
public function microDateTime()
|
378 |
+
{
|
379 |
+
list($microSec,$timeStamp) = explode(" ", microtime());
|
380 |
+
return date('Y-m-d h:i:', $timeStamp) . (date('s', $timeStamp) + $microSec);
|
381 |
+
}
|
382 |
+
|
383 |
+
public function log($data, $type = "default", $logger = null)
|
384 |
+
{
|
385 |
+
$usedlogger = ($logger == null ? $this->logger : $logger);
|
386 |
+
if (isset($usedlogger))
|
387 |
+
{
|
388 |
+
$usedlogger->log($data, $type);
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
public function logException($e, $data = "", $logger = null)
|
393 |
+
{
|
394 |
+
$this->trace($e, $data);
|
395 |
+
$this->log($this->_excid . ":" . $e->getMessage() . " - " . $data, "error", $logger);
|
396 |
+
}
|
397 |
+
|
398 |
+
public function getExceptionTrace($tk, &$traces)
|
399 |
+
{
|
400 |
+
$this->_excid++;
|
401 |
+
$trstr = "";
|
402 |
+
foreach ($traces as $trace)
|
403 |
+
{
|
404 |
+
if (isset($trace["file"]))
|
405 |
+
{
|
406 |
+
$fname = str_replace(dirname(dirname(__FILE__)), "", $trace["file"]);
|
407 |
+
$trstr .= $fname . ":" . (isset($trace["line"]) ? $trace["line"] : "?") . " - ";
|
408 |
+
if (isset($trace["class"]))
|
409 |
+
{
|
410 |
+
$trstr .= $trace["class"] . "->";
|
411 |
+
if (isset($trace["function"]))
|
412 |
+
{
|
413 |
+
$trstr .= $trace["function"];
|
414 |
+
}
|
415 |
+
$trstr .= "\n----------------------------------------\n";
|
416 |
+
if (isset($trace["args"]))
|
417 |
+
{
|
418 |
+
$trstr .= print_r($trace["args"], true);
|
419 |
+
}
|
420 |
+
$trstr .= "\n";
|
421 |
+
}
|
422 |
+
}
|
423 |
+
}
|
424 |
+
if (!isset($this->_exceptions[$tk]))
|
425 |
+
{
|
426 |
+
$this->_exceptions[$tk] = array(0,$this->_excid);
|
427 |
+
}
|
428 |
+
$this->_exceptions[$tk][0]++;
|
429 |
+
$trstr = "************************************\n$tk\n*************************************\n$trstr";
|
430 |
+
return array($trstr,$this->_exceptions[$tk][0] == 1,$this->_exceptions[$tk][1]);
|
431 |
+
}
|
432 |
+
|
433 |
+
public function trace($e, $data = "")
|
434 |
+
{
|
435 |
+
$traces = $e->getTrace();
|
436 |
+
$tk = $e->getMessage();
|
437 |
+
$traceinfo = $this->getExceptionTrace($tk, $traces);
|
438 |
+
$f = fopen(Magmi_StateManager::getTraceFile(), "a");
|
439 |
+
fwrite($f, "---- TRACE : $this->_excid -----\n");
|
440 |
+
fwrite($f, "---- DATE : " . date('Y-m-d H:i:s') . " ------\n");
|
441 |
+
try
|
442 |
+
{
|
443 |
+
if ($traceinfo[1] == true)
|
444 |
+
{
|
445 |
+
fwrite($f, $traceinfo[0]);
|
446 |
+
fwrite($f, "+++++++++++++++++++++++++++++\nCONTEXT DUMP\n+++++++++++++++++++++++++++++\n");
|
447 |
+
fwrite($f, print_r($this, true));
|
448 |
+
fwrite($f, "\n+++++++++++++++++++++++++++++\nEND CONTEXT DUMP\n+++++++++++++++++++++++++++++\n");
|
449 |
+
}
|
450 |
+
else
|
451 |
+
{
|
452 |
+
$tnum = $traceinfo[2];
|
453 |
+
fwrite($f, "Duplicated exception - same trace as TRACE : $tnum\n");
|
454 |
+
}
|
455 |
+
}
|
456 |
+
catch (Exception $te)
|
457 |
+
{
|
458 |
+
fwrite($f, "Exception occured during trace:" . $te->getMessage());
|
459 |
+
}
|
460 |
+
fwrite($f, "---- ENDTRACE : $this->_excid -----\n");
|
461 |
+
fclose($f);
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* Engine run method
|
466 |
+
*
|
467 |
+
* @param array $params
|
468 |
+
* - run parameters
|
469 |
+
*/
|
470 |
+
public final function run($params = array())
|
471 |
+
{
|
472 |
+
try
|
473 |
+
{
|
474 |
+
$f = fopen(Magmi_StateManager::getTraceFile(), "w");
|
475 |
+
fclose($f);
|
476 |
+
$enginf = $this->getEngineInfo();
|
477 |
+
$this->log("MAGMI by dweeves - version:" . Magmi_Version::$version, "title");
|
478 |
+
$this->log("Running {$enginf["name"]} v${enginf["version"]} by ${enginf["author"]}", "startup");
|
479 |
+
if (!$this->_initialized)
|
480 |
+
{
|
481 |
+
$this->initialize($params);
|
482 |
+
}
|
483 |
+
$this->connectToMagento();
|
484 |
+
$this->engineInit($params);
|
485 |
+
$this->engineRun($params);
|
486 |
+
$this->disconnectFromMagento();
|
487 |
+
}
|
488 |
+
catch (Exception $e)
|
489 |
+
{
|
490 |
+
$this->disconnectFromMagento();
|
491 |
+
|
492 |
+
$this->handleException($e);
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
public function handleException($e)
|
497 |
+
{
|
498 |
+
$this->logException($e);
|
499 |
+
if (method_exists($this, "onEngineException"))
|
500 |
+
{
|
501 |
+
$this->onEngineException($e);
|
502 |
+
}
|
503 |
+
}
|
504 |
+
|
505 |
+
/**
|
506 |
+
* shortcut method for configuration properties get
|
507 |
+
*/
|
508 |
+
public function getProp($sec, $val, $default = null)
|
509 |
+
{
|
510 |
+
return $this->_conf->get($sec, $val, $default);
|
511 |
+
}
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Initialize Connection with Magento Database
|
515 |
+
*/
|
516 |
+
public function connectToMagento()
|
517 |
+
{
|
518 |
+
// et database infos from properties
|
519 |
+
if (!$this->_connected)
|
520 |
+
{
|
521 |
+
$host = $this->getProp("DATABASE", "host", "localhost");
|
522 |
+
$dbname = $this->getProp("DATABASE", "dbname", "magento");
|
523 |
+
$user = $this->getProp("DATABASE", "user");
|
524 |
+
$pass = $this->getProp("DATABASE", "password");
|
525 |
+
$debug = $this->getProp("DATABASE", "debug");
|
526 |
+
$conn = $this->getProp("DATABASE", "connectivity", "net");
|
527 |
+
$port = $this->getProp("DATABASE", "port", "3306");
|
528 |
+
$socket = $this->getProp("DATABASE", "unix_socket");
|
529 |
+
$this->initDb($host, $dbname, $user, $pass, $port, $socket, $conn, $debug);
|
530 |
+
// suggested by pastanislas
|
531 |
+
$this->_db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
|
532 |
+
}
|
533 |
+
}
|
534 |
+
/*
|
535 |
+
* Disconnect Magento db
|
536 |
+
*/
|
537 |
+
public function disconnectFromMagento()
|
538 |
+
{
|
539 |
+
if ($this->_connected)
|
540 |
+
{
|
541 |
+
$this->exitDb();
|
542 |
+
}
|
543 |
+
}
|
544 |
+
|
545 |
+
/**
|
546 |
+
* returns prefixed table name
|
547 |
+
*
|
548 |
+
* @param string $magname
|
549 |
+
* : magento base table name
|
550 |
+
*/
|
551 |
+
public function tablename($magname)
|
552 |
+
{
|
553 |
+
return $this->tprefix != "" ? $this->tprefix . "$magname" : $magname;
|
554 |
+
}
|
555 |
+
|
556 |
+
public abstract function engineInit($params);
|
557 |
+
|
558 |
+
public abstract function engineRun($params);
|
559 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_loggers.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class Magmi_Logger
|
4 |
+
{
|
5 |
+
|
6 |
+
public abstract function log($data, $type = null);
|
7 |
+
}
|
8 |
+
|
9 |
+
class FileLogger extends Magmi_Logger
|
10 |
+
{
|
11 |
+
protected $_fname;
|
12 |
+
|
13 |
+
public function __construct($fname = null)
|
14 |
+
{
|
15 |
+
if ($fname == null)
|
16 |
+
{
|
17 |
+
$fname = Magmi_StateManager::getProgressFile(true);
|
18 |
+
}
|
19 |
+
$this->_fname = $fname;
|
20 |
+
$f = fopen($this->_fname, "w");
|
21 |
+
if ($f == false)
|
22 |
+
{
|
23 |
+
throw new Exception("CANNOT WRITE PROGRESS FILE ");
|
24 |
+
}
|
25 |
+
fclose($f);
|
26 |
+
}
|
27 |
+
|
28 |
+
public function log($data, $type = null)
|
29 |
+
{
|
30 |
+
$f = fopen($this->_fname, "a");
|
31 |
+
if ($f == false)
|
32 |
+
{
|
33 |
+
throw new Exception("CANNOT WRITE PROGRESS FILE ");
|
34 |
+
}
|
35 |
+
$data = preg_replace("/(\r|\n|\r\n)/", "<br>", $data);
|
36 |
+
if ($type == null)
|
37 |
+
{
|
38 |
+
$type = "default";
|
39 |
+
}
|
40 |
+
fwrite($f, "$type:$data\n");
|
41 |
+
fclose($f);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
class EchoLogger extends Magmi_Logger
|
46 |
+
{
|
47 |
+
|
48 |
+
public function log($data, $type = null)
|
49 |
+
{
|
50 |
+
if ($type != null)
|
51 |
+
{
|
52 |
+
$info = explode(";", $type);
|
53 |
+
$type = $info[0];
|
54 |
+
}
|
55 |
+
else
|
56 |
+
{
|
57 |
+
$type = "default";
|
58 |
+
}
|
59 |
+
echo ('<p class="logentry log_' . $type . '">' . $data . "</p>");
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
class CLILogger extends Magmi_Logger
|
64 |
+
{
|
65 |
+
|
66 |
+
public function log($data, $type = null)
|
67 |
+
{
|
68 |
+
echo ("$type:$data\n");
|
69 |
+
}
|
70 |
+
}
|
71 |
+
?>
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_mixin.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_Mixin
|
4 |
+
{
|
5 |
+
protected $_callers;
|
6 |
+
|
7 |
+
public function bind($caller)
|
8 |
+
{
|
9 |
+
$this->_callers[] = $caller;
|
10 |
+
$this->_callers = array_unique($this->_callers);
|
11 |
+
}
|
12 |
+
|
13 |
+
public function unbind($caller)
|
14 |
+
{
|
15 |
+
$ks = array_keys($this->_callers, $caller);
|
16 |
+
if (count($ks) > 0)
|
17 |
+
{
|
18 |
+
foreach ($ks as $k)
|
19 |
+
{
|
20 |
+
unset($this->_callers[$k]);
|
21 |
+
}
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
public function __call($data, $arg)
|
26 |
+
{
|
27 |
+
if (substr($data, 0, 8) == "_caller_")
|
28 |
+
{
|
29 |
+
$data = substr($data, 8);
|
30 |
+
}
|
31 |
+
$ccallers = count($this->_callers);
|
32 |
+
for ($i = 0; $i < $ccallers; $i++)
|
33 |
+
{
|
34 |
+
if (method_exists($this->_callers[$i], $data))
|
35 |
+
{
|
36 |
+
return call_user_func_array(array($this->_callers[$i],$data), $arg);
|
37 |
+
}
|
38 |
+
else
|
39 |
+
{
|
40 |
+
die("Invalid Method Call: $data - Not found in Caller");
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_pluginhelper.php
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("magmi_config.php");
|
3 |
+
require_once ("fshelper.php");
|
4 |
+
|
5 |
+
class Magmi_PluginHelper
|
6 |
+
{
|
7 |
+
static $_plugins_cache = array();
|
8 |
+
static $_instances = array();
|
9 |
+
public $base_dir;
|
10 |
+
public $plugin_dir;
|
11 |
+
protected $_profile;
|
12 |
+
protected $_plmeta = array("datasources"=>array("Magmi_Datasource","*/*"),
|
13 |
+
"itemprocessors"=>array("Magmi_ItemProcessor","*/*"),"general"=>array("Magmi_GeneralImportPlugin","*/*"),
|
14 |
+
"utilities"=>array("Magmi_UtilityPlugin","utilities"));
|
15 |
+
|
16 |
+
public function __construct($profile = null)
|
17 |
+
{
|
18 |
+
$this->_profile = $profile;
|
19 |
+
$this->base_dir = dirname(__FILE__);
|
20 |
+
$this->plugin_dir = realpath(dirname(dirname(__FILE__)) . DIRSEP . "plugins");
|
21 |
+
// set include path to inclue plugins inc & base dir
|
22 |
+
set_include_path(
|
23 |
+
ini_get("include_path") . PATH_SEPARATOR . "$this->plugin_dir/inc" . PATH_SEPARATOR . "$this->base_dir");
|
24 |
+
// add base classes in context
|
25 |
+
require_once ("magmi_item_processor.php");
|
26 |
+
require_once ("magmi_datasource.php");
|
27 |
+
require_once ("magmi_generalimport_plugin.php");
|
28 |
+
require_once ("magmi_utility_plugin.php");
|
29 |
+
}
|
30 |
+
|
31 |
+
public static function getInstance($profile = null)
|
32 |
+
{
|
33 |
+
$key = ($profile == null ? "default" : $profile);
|
34 |
+
if (!isset(self::$_instances[$key]))
|
35 |
+
{
|
36 |
+
self::$_instances[$key] = new Magmi_PluginHelper($profile);
|
37 |
+
}
|
38 |
+
return self::$_instances[$key];
|
39 |
+
}
|
40 |
+
|
41 |
+
public static function fnsort($f1, $f2)
|
42 |
+
{
|
43 |
+
return strcmp(basename($f1), basename($f2));
|
44 |
+
}
|
45 |
+
|
46 |
+
public function initPluginInfos($baseclass, $basedir = "*/*")
|
47 |
+
{
|
48 |
+
$candidates = glob("$this->plugin_dir/$basedir/*/*.php");
|
49 |
+
usort($candidates, array("Magmi_PluginHelper","fnsort"));
|
50 |
+
$pluginclasses = array();
|
51 |
+
foreach ($candidates as $pcfile)
|
52 |
+
{
|
53 |
+
$dirname = dirname(substr($pcfile, strlen($this->plugin_dir)));
|
54 |
+
if (substr(basename($dirname), 0, 2) != '__')
|
55 |
+
{
|
56 |
+
$content = file_get_contents($pcfile);
|
57 |
+
if (preg_match_all("/class\s+(.*?)\s+extends\s+$baseclass/mi", $content, $matches, PREG_SET_ORDER))
|
58 |
+
{
|
59 |
+
require_once ($pcfile);
|
60 |
+
foreach ($matches as $match)
|
61 |
+
{
|
62 |
+
$pluginclasses[] = array("class"=>$match[1],"dir"=>$dirname,"file"=>basename($pcfile));
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
return $pluginclasses;
|
68 |
+
}
|
69 |
+
|
70 |
+
public function getPluginClasses($pltypes)
|
71 |
+
{
|
72 |
+
return self::getPluginsInfo($pltypes, "class");
|
73 |
+
}
|
74 |
+
|
75 |
+
public function getPluginsInfo($pltypes, $filter = null)
|
76 |
+
{
|
77 |
+
if (self::$_plugins_cache == null)
|
78 |
+
{
|
79 |
+
self::scanPlugins($pltypes);
|
80 |
+
}
|
81 |
+
|
82 |
+
if (isset($filter))
|
83 |
+
{
|
84 |
+
$out = array();
|
85 |
+
foreach (self::$_plugins_cache as $k => $arr)
|
86 |
+
{
|
87 |
+
if (!isset($out[$k]))
|
88 |
+
{
|
89 |
+
$out[$k] = array();
|
90 |
+
}
|
91 |
+
foreach ($arr as $desc)
|
92 |
+
{
|
93 |
+
$out[$k][] = $desc[$filter];
|
94 |
+
}
|
95 |
+
}
|
96 |
+
$plugins = $out;
|
97 |
+
}
|
98 |
+
else
|
99 |
+
{
|
100 |
+
$plugins = self::$_plugins_cache;
|
101 |
+
}
|
102 |
+
return $plugins;
|
103 |
+
}
|
104 |
+
|
105 |
+
public function scanPlugins($pltypes)
|
106 |
+
{
|
107 |
+
if (!is_array($pltypes))
|
108 |
+
{
|
109 |
+
$pltypes = array($pltypes);
|
110 |
+
}
|
111 |
+
foreach ($pltypes as $pltype)
|
112 |
+
{
|
113 |
+
if (!isset(self::$_plugins_cache[$pltype]))
|
114 |
+
{
|
115 |
+
self::$_plugins_cache[$pltype] = self::initPluginInfos($this->_plmeta[$pltype][0],
|
116 |
+
$this->_plmeta[$pltype][1]);
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
public function createInstance($ptype, $pclass, $params = null, $mmi = null)
|
122 |
+
{
|
123 |
+
if (!isset(self::$_plugins_cache[$ptype]))
|
124 |
+
{
|
125 |
+
self::scanPlugins($ptype);
|
126 |
+
}
|
127 |
+
$plinst = new $pclass();
|
128 |
+
|
129 |
+
$plinst->pluginInit($mmi, $this->getPluginMeta($plinst), $params, ($mmi != null), $this->_profile);
|
130 |
+
return $plinst;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function getPluginDir($pinst)
|
134 |
+
{
|
135 |
+
$mt = $this->getPluginMeta($pinst);
|
136 |
+
return $mt["dir"];
|
137 |
+
}
|
138 |
+
|
139 |
+
public function getPluginMeta($pinst)
|
140 |
+
{
|
141 |
+
if (self::$_plugins_cache == null)
|
142 |
+
{
|
143 |
+
self::scanPlugins();
|
144 |
+
}
|
145 |
+
|
146 |
+
foreach (self::$_plugins_cache as $t => $l)
|
147 |
+
{
|
148 |
+
foreach ($l as $pdesc)
|
149 |
+
{
|
150 |
+
if ($pdesc["class"] == get_class($pinst))
|
151 |
+
{
|
152 |
+
$out = $pdesc;
|
153 |
+
$out["dir"] = $this->plugin_dir . $pdesc["dir"];
|
154 |
+
return $out;
|
155 |
+
}
|
156 |
+
}
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
public function installPluginPackage($pkgname)
|
161 |
+
{
|
162 |
+
$zip = new ZipArchive();
|
163 |
+
$res = $zip->open($pkgname);
|
164 |
+
if ($res === TRUE)
|
165 |
+
{
|
166 |
+
$zip->extractTo($this->plugin_dir);
|
167 |
+
$zip->close();
|
168 |
+
return array("plugin_install"=>"OK");
|
169 |
+
}
|
170 |
+
else
|
171 |
+
{
|
172 |
+
return array("plugin_install"=>"ERROR","ERROR"=>"Invalid Plugin Package Archive");
|
173 |
+
}
|
174 |
+
$packages = glob("$this->plugin_dir/*");
|
175 |
+
foreach ($packages as $pdir)
|
176 |
+
{
|
177 |
+
if (file_exists($pdir . DIRSEP . "obsolete.txt"))
|
178 |
+
{
|
179 |
+
$content = file_get_contents($pdir . DIRSEP . "obsolete.txt");
|
180 |
+
$obsolete = explode("\n", $content);
|
181 |
+
foreach ($obsolete as $todelete)
|
182 |
+
{
|
183 |
+
if ($todelete != "")
|
184 |
+
{
|
185 |
+
@unlink($pdir . DIRSEP . $todelete);
|
186 |
+
}
|
187 |
+
}
|
188 |
+
unlink($pdir . DIRSEP . "obsolete.txt");
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
public function removePlugin($pgpath)
|
194 |
+
{
|
195 |
+
unlink($pgpath);
|
196 |
+
}
|
197 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_statemanager.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if (!defined("DIRSEP"))
|
3 |
+
{
|
4 |
+
define("DIRSEP", DIRECTORY_SEPARATOR);
|
5 |
+
}
|
6 |
+
|
7 |
+
class Magmi_StateManager
|
8 |
+
{
|
9 |
+
private static $_statefile = null;
|
10 |
+
private static $_script = __FILE__;
|
11 |
+
private static $_state = "idle";
|
12 |
+
|
13 |
+
public static function getStateFile()
|
14 |
+
{
|
15 |
+
return self::getStateDir() . DIRSEP . "magmistate";
|
16 |
+
}
|
17 |
+
|
18 |
+
public static function getTraceFile()
|
19 |
+
{
|
20 |
+
return self::getStateDir() . DIRSEP . "trace.txt";
|
21 |
+
}
|
22 |
+
|
23 |
+
public static function getStateDir()
|
24 |
+
{
|
25 |
+
return dirname(dirname(self::$_script)) . DIRSEP . "state";
|
26 |
+
}
|
27 |
+
|
28 |
+
public static function getProgressFile($full = false)
|
29 |
+
{
|
30 |
+
$fullname = self::getStateDir() . DIRSEP . "progress.txt";
|
31 |
+
$pfname = ($full ? $fullname : "progress.txt");
|
32 |
+
return $pfname;
|
33 |
+
}
|
34 |
+
|
35 |
+
public static function setState($state, $force = false)
|
36 |
+
{
|
37 |
+
if (self::$_state == $state && !$force)
|
38 |
+
{
|
39 |
+
return;
|
40 |
+
}
|
41 |
+
|
42 |
+
self::$_state = $state;
|
43 |
+
$f = fopen(self::getStateFile(), "w");
|
44 |
+
fwrite($f, self::$_state);
|
45 |
+
fclose($f);
|
46 |
+
@chmod(self::getStateFile(), 0664);
|
47 |
+
if ($state == "running")
|
48 |
+
{
|
49 |
+
$f = fopen(self::getTraceFile(), "w");
|
50 |
+
fclose($f);
|
51 |
+
@chmod(self::getTraceFile(), 0664);
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
public static function getState($cached = false)
|
56 |
+
{
|
57 |
+
if (!$cached)
|
58 |
+
{
|
59 |
+
if (!file_exists(self::getStateFile()))
|
60 |
+
{
|
61 |
+
self::setState("idle", true);
|
62 |
+
}
|
63 |
+
$state = file_get_contents(self::getStateFile());
|
64 |
+
}
|
65 |
+
else
|
66 |
+
{
|
67 |
+
$state = self::$_state;
|
68 |
+
}
|
69 |
+
return $state;
|
70 |
+
}
|
71 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_utils.php
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
// utilities function
|
3 |
+
|
4 |
+
// return null for empty string
|
5 |
+
function nullifempty($val)
|
6 |
+
{
|
7 |
+
return (isset($val) ? (trim($val) == "" ? null : $val) : null);
|
8 |
+
}
|
9 |
+
// return false for empty string
|
10 |
+
function falseifempty($val)
|
11 |
+
{
|
12 |
+
return (isset($val) ? (strlen($val) == 0 ? false : $val) : false);
|
13 |
+
}
|
14 |
+
// test for empty string
|
15 |
+
function testempty($arr, $val)
|
16 |
+
{
|
17 |
+
return !isset($arr[$val]) || strlen(trim($arr[$val])) == 0;
|
18 |
+
}
|
19 |
+
|
20 |
+
// place a DELETE maker for empty values
|
21 |
+
function deleteifempty($val)
|
22 |
+
{
|
23 |
+
return (isset($val) ? (trim($val) == "" ? "__MAGMI_DELETE__" : $val) : "__MAGMI_DELETE__");
|
24 |
+
}
|
25 |
+
|
26 |
+
// convert to array & trims a comma separated list
|
27 |
+
function csl2arr($cslarr, $sep = ",")
|
28 |
+
{
|
29 |
+
$arr = explode($sep, $cslarr);
|
30 |
+
$carr = count($arr);
|
31 |
+
for ($i = 0; $i < $carr; $i++)
|
32 |
+
{
|
33 |
+
$arr[$i] = trim($arr[$i]);
|
34 |
+
}
|
35 |
+
return $arr;
|
36 |
+
}
|
37 |
+
|
38 |
+
// trim a list of array values
|
39 |
+
function trimarray(&$arr)
|
40 |
+
{
|
41 |
+
$carr = count($arr);
|
42 |
+
for ($i = 0; $i < $carr; $i++)
|
43 |
+
{
|
44 |
+
$arr[$i] = trim($arr[$i]);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
// Relative value detection (prepend of + or -)
|
49 |
+
function getRelative(&$val)
|
50 |
+
{
|
51 |
+
$dir = "+";
|
52 |
+
if ($val[0] == "-")
|
53 |
+
{
|
54 |
+
$val = substr($val, 1);
|
55 |
+
$dir = "-";
|
56 |
+
}
|
57 |
+
else
|
58 |
+
if ($val[0] == "+")
|
59 |
+
{
|
60 |
+
$val = substr($val, 1);
|
61 |
+
}
|
62 |
+
return $dir;
|
63 |
+
}
|
64 |
+
|
65 |
+
// Check if we have a remote path
|
66 |
+
function is_remote_path($path)
|
67 |
+
{
|
68 |
+
$parsed = parse_url($path);
|
69 |
+
return isset($parsed['host']);
|
70 |
+
}
|
71 |
+
|
72 |
+
// Returns absolute path for a file with a base path
|
73 |
+
// if $resolve is set to true,return associated realpath
|
74 |
+
function abspath($path, $basepath = "", $resolve = true)
|
75 |
+
{
|
76 |
+
if ($basepath == "")
|
77 |
+
{
|
78 |
+
$basepath = dirname(dirname(__FILE__));
|
79 |
+
}
|
80 |
+
$cpath = str_replace('//', '/', $basepath . "/" . $path);
|
81 |
+
if ($resolve && !is_remote_path($cpath))
|
82 |
+
{
|
83 |
+
$abs = realpath($cpath);
|
84 |
+
}
|
85 |
+
else
|
86 |
+
{
|
87 |
+
$inparts = explode("/", $cpath);
|
88 |
+
$outparts = array();
|
89 |
+
$cinparts = count($inparts);
|
90 |
+
for ($i = 0; $i < $cinparts; $i++)
|
91 |
+
{
|
92 |
+
if ($inparts[$i] == '..')
|
93 |
+
{
|
94 |
+
array_pop($outparts);
|
95 |
+
}
|
96 |
+
else
|
97 |
+
if ($inparts[$i] != '.')
|
98 |
+
{
|
99 |
+
$outparts[] = $inparts[$i];
|
100 |
+
}
|
101 |
+
}
|
102 |
+
$abs = implode("/", $outparts);
|
103 |
+
}
|
104 |
+
return $abs;
|
105 |
+
}
|
106 |
+
|
107 |
+
function truepath($path)
|
108 |
+
{
|
109 |
+
$opath = $path;
|
110 |
+
// whether $path is unix or not
|
111 |
+
$unipath = strlen($path) == 0 || $path{0} != '/';
|
112 |
+
// attempts to detect if path is relative in which case, add cwd
|
113 |
+
if (strpos($path, ':') === false && $unipath)
|
114 |
+
$path = getcwd() . DIRECTORY_SEPARATOR . $path;
|
115 |
+
// resolve path parts (single dot, double dot and double delimiters)
|
116 |
+
$path = str_replace(array('/','\\'), DIRECTORY_SEPARATOR, $path);
|
117 |
+
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
|
118 |
+
$absolutes = array();
|
119 |
+
foreach ($parts as $part)
|
120 |
+
{
|
121 |
+
if ('.' == $part)
|
122 |
+
continue;
|
123 |
+
if ('..' == $part)
|
124 |
+
{
|
125 |
+
array_pop($absolutes);
|
126 |
+
}
|
127 |
+
else
|
128 |
+
{
|
129 |
+
$absolutes[] = $part;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
$path = implode(DIRECTORY_SEPARATOR, $absolutes);
|
133 |
+
// resolve any symlinks
|
134 |
+
if (file_exists($path) && linkinfo($path) > 0)
|
135 |
+
{
|
136 |
+
$path = readlink($path);
|
137 |
+
}
|
138 |
+
// put initial separator that could have been lost
|
139 |
+
$path = !$unipath ? '/' . $path : $path;
|
140 |
+
return $path;
|
141 |
+
}
|
142 |
+
|
143 |
+
// Test for absolute path using OS detection
|
144 |
+
function isabspath($path)
|
145 |
+
{
|
146 |
+
return ($path[0] == "." || (substr(PHP_OS, 0, 3) == "WIN" && strlen($path) > 1) ? $path[1] == ":" : $path[0] == "/");
|
147 |
+
}
|
148 |
+
|
149 |
+
/*
|
150 |
+
* Slugger class, for producing valid url from strings
|
151 |
+
*/
|
152 |
+
class Slugger
|
153 |
+
{
|
154 |
+
// Mapping array for intl accented chars
|
155 |
+
protected static $_translit = array('Š'=>'S','š'=>'s','Ð'=>'Dj','Ž'=>'Z','ž'=>'z','À'=>'A','Á'=>'A','Â'=>'A',
|
156 |
+
'Ã'=>'A','Ä'=>'A','Å'=>'A','Æ'=>'A','Ç'=>'C','È'=>'E','É'=>'E','Ê'=>'E','Ë'=>'E','Ì'=>'I','Í'=>'I','Î'=>'I',
|
157 |
+
'Ï'=>'I','Ñ'=>'N','Ò'=>'O','Ó'=>'O','Ô'=>'O','Õ'=>'O','Ö'=>'O','Ø'=>'O','Ù'=>'U','Ú'=>'U','Û'=>'U','Ü'=>'U',
|
158 |
+
'Ý'=>'Y','Þ'=>'B','ß'=>'Ss','à'=>'a','á'=>'a','â'=>'a','ã'=>'a','ä'=>'a','å'=>'a','æ'=>'a','ç'=>'c','è'=>'e',
|
159 |
+
'é'=>'e','ê'=>'e','ë'=>'e','ì'=>'i','í'=>'i','î'=>'i','ï'=>'i','ð'=>'o','ñ'=>'n','ò'=>'o','ó'=>'o','ô'=>'o',
|
160 |
+
'õ'=>'o','ö'=>'o','ø'=>'o','ù'=>'u','ú'=>'u','û'=>'u','ý'=>'y','ý'=>'y','þ'=>'b','ÿ'=>'y','ƒ'=>'f','Č'=>'C',
|
161 |
+
'č'=>'c','Ľ'=>'L','ľ'=>'l','Ĺ'=>'L','Ť'=>'T','ť'=>'t','Ň'=>'N','ň'=>'n','Ŕ'=>'R','ŕ'=>'r','Ř'=>'R','ř'=>'r',
|
162 |
+
'Ő'=>'O','ő'=>'o','Ű'=>'U','ű'=>'u','ü'=>'u');
|
163 |
+
|
164 |
+
// Stripping accents
|
165 |
+
public static function stripAccents($text)
|
166 |
+
{
|
167 |
+
return strtr($text, self::$_translit);
|
168 |
+
}
|
169 |
+
// Slugging function
|
170 |
+
public static function slug($str, $allowslash = false)
|
171 |
+
{
|
172 |
+
$str = strtolower(self::stripAccents(trim($str)));
|
173 |
+
$rerep = $allowslash ? '[^a-z0-9-/]' : '[^a-z0-9-]';
|
174 |
+
$str = preg_replace("|$rerep|", '-', $str);
|
175 |
+
$str = preg_replace('|-+|', "-", $str);
|
176 |
+
$str = preg_replace('|-$|', "", $str);
|
177 |
+
return $str;
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_valueparser.php
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_ValueParser
|
4 |
+
{
|
5 |
+
|
6 |
+
public static function parseValue($pvalue, $dictarray)
|
7 |
+
{
|
8 |
+
$matches = array();
|
9 |
+
$rep = "";
|
10 |
+
$renc = "<-XMagmi_Enc->";
|
11 |
+
|
12 |
+
foreach ($dictarray as $key => $vals)
|
13 |
+
{
|
14 |
+
$ik = array_keys($vals);
|
15 |
+
// replace base values
|
16 |
+
while (preg_match("|\{$key\.(.*?)\}|", $pvalue, $matches))
|
17 |
+
{
|
18 |
+
foreach ($matches as $match)
|
19 |
+
{
|
20 |
+
if ($match != $matches[0])
|
21 |
+
{
|
22 |
+
if (in_array($match, $ik))
|
23 |
+
{
|
24 |
+
$rep = $renc . $dictarray[$key][$match] . $renc;
|
25 |
+
}
|
26 |
+
else
|
27 |
+
{
|
28 |
+
$rep = "";
|
29 |
+
}
|
30 |
+
$pvalue = str_replace($matches[0], $rep, $pvalue);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
unset($matches);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
// replacing expr values
|
38 |
+
while (preg_match("|\{\{\s*(.*?)\s*\}\}|", $pvalue, $matches))
|
39 |
+
{
|
40 |
+
foreach ($matches as $match)
|
41 |
+
{
|
42 |
+
if ($match != $matches[0])
|
43 |
+
{
|
44 |
+
$code = trim($match);
|
45 |
+
$code = str_replace($renc, '"', $code);
|
46 |
+
|
47 |
+
$rep = eval("return ($code);");
|
48 |
+
// escape potential "{{xxx}}" values in interpreted target
|
49 |
+
// so that they won't be reparsed in next round
|
50 |
+
$rep = preg_replace("|\{\{\s*(.*?)\s*\}\}|", "____$1____", $rep);
|
51 |
+
$pvalue = str_replace($matches[0], $rep, $pvalue);
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
// unescape matches
|
57 |
+
$pvalue = preg_replace("|____(.*?)____|", '{{$1}}', $pvalue);
|
58 |
+
// single replaced values
|
59 |
+
$pvalue = str_replace($renc, '', $pvalue);
|
60 |
+
return "" . $pvalue;
|
61 |
+
}
|
62 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/magmi_version.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_Version
|
3 |
+
{
|
4 |
+
public static $version="0.7.19a";
|
5 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/properties.php
ADDED
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if (!defined("DIRSEP"))
|
3 |
+
{
|
4 |
+
define("DIRSEP", DIRECTORY_SEPARATOR);
|
5 |
+
}
|
6 |
+
|
7 |
+
class FileNotFoundException extends Exception
|
8 |
+
{
|
9 |
+
}
|
10 |
+
|
11 |
+
class InvalidPropertiesException extends Exception
|
12 |
+
{
|
13 |
+
}
|
14 |
+
|
15 |
+
class Properties
|
16 |
+
{
|
17 |
+
protected $_props;
|
18 |
+
public $inifile;
|
19 |
+
protected $_specialchars = array('"'=>":DQUOTE:","'"=>":SQUOTE:",'\\t'=>"TAB");
|
20 |
+
|
21 |
+
public function __construct()
|
22 |
+
{
|
23 |
+
$this->inifile = null;
|
24 |
+
$this->_props = array();
|
25 |
+
}
|
26 |
+
|
27 |
+
public function setPropsFromFlatArray($flatarr)
|
28 |
+
{
|
29 |
+
$this->_props = $this->getIniStruct($flatarr);
|
30 |
+
}
|
31 |
+
|
32 |
+
public function setProps($proparr)
|
33 |
+
{
|
34 |
+
$this->_props = $proparr;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function load($file)
|
38 |
+
{
|
39 |
+
if (!file_exists($file))
|
40 |
+
{
|
41 |
+
return;
|
42 |
+
// throw new FileNotFoundException();
|
43 |
+
}
|
44 |
+
try
|
45 |
+
{
|
46 |
+
$this->inifile = $file;
|
47 |
+
$this->_props = parse_ini_file($this->inifile, true);
|
48 |
+
foreach ($this->_props as $sec => $data)
|
49 |
+
{
|
50 |
+
foreach ($data as $k => $v)
|
51 |
+
{
|
52 |
+
foreach ($this->_specialchars as $spch => $alias)
|
53 |
+
{
|
54 |
+
$newv = str_replace($alias, $spch, $v);
|
55 |
+
if ($newv != $v)
|
56 |
+
{
|
57 |
+
break;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
$this->_props[$sec][$k] = $newv;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
catch (Exception $e)
|
65 |
+
{
|
66 |
+
throw new InvalidPropertiesException();
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
public function getIniStruct($arr)
|
71 |
+
{
|
72 |
+
$conf = array();
|
73 |
+
foreach ($arr as $k => $v)
|
74 |
+
{
|
75 |
+
list($section,$value) = explode(":", $k, 2);
|
76 |
+
if (!isset($conf[$section]))
|
77 |
+
{
|
78 |
+
$conf[$section] = array();
|
79 |
+
}
|
80 |
+
$conf[$section][$value] = $v;
|
81 |
+
}
|
82 |
+
return $conf;
|
83 |
+
}
|
84 |
+
|
85 |
+
public function save($fname = null)
|
86 |
+
{
|
87 |
+
if ($fname == null)
|
88 |
+
{
|
89 |
+
$fname == $this->inifile;
|
90 |
+
}
|
91 |
+
return $this->write_ini_file($this->_props, $fname, true);
|
92 |
+
}
|
93 |
+
|
94 |
+
public function esc($str)
|
95 |
+
{
|
96 |
+
foreach ($this->_specialchars as $spch => $alias)
|
97 |
+
{
|
98 |
+
$str = str_replace($spch, $alias, $str);
|
99 |
+
}
|
100 |
+
return $str;
|
101 |
+
}
|
102 |
+
|
103 |
+
public function write_ini_file($assoc_arr, $path, $has_sections = FALSE)
|
104 |
+
{
|
105 |
+
$content = "";
|
106 |
+
if (count($assoc_arr) > 0)
|
107 |
+
{
|
108 |
+
if ($has_sections)
|
109 |
+
{
|
110 |
+
foreach ($assoc_arr as $key => $elem)
|
111 |
+
{
|
112 |
+
$content .= "[" . $key . "]\n";
|
113 |
+
foreach ($elem as $key2 => $elem2)
|
114 |
+
{
|
115 |
+
if (is_array($elem2))
|
116 |
+
{
|
117 |
+
$celem2 = count($elem2);
|
118 |
+
for ($i = 0; $i < $celem2; $i++)
|
119 |
+
{
|
120 |
+
$content .= $key2 . "[] = \"" . $this->esc($elem2[$i]) . "\"\n";
|
121 |
+
}
|
122 |
+
}
|
123 |
+
else
|
124 |
+
if ($elem2 == "")
|
125 |
+
$content .= $key2 . " = \n";
|
126 |
+
else
|
127 |
+
$content .= $key2 . " = \"" . $this->esc($elem2) . "\"\n";
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
else
|
132 |
+
{
|
133 |
+
foreach ($assoc_arr as $key => $elem)
|
134 |
+
{
|
135 |
+
if (is_array($elem))
|
136 |
+
{
|
137 |
+
$celem = count($elem);
|
138 |
+
for ($i = 0; $i < $celem; $i++)
|
139 |
+
{
|
140 |
+
$content .= $key2 . "[] = \"" . $this->esc($elem[$i]) . "\"\n";
|
141 |
+
}
|
142 |
+
}
|
143 |
+
else
|
144 |
+
if ($elem == "")
|
145 |
+
$content .= $key2 . " = \n";
|
146 |
+
else
|
147 |
+
$content .= $key2 . " = \"" . $this->esc($elem) . "\"\n";
|
148 |
+
}
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
if (!$handle = fopen($path, 'w'))
|
153 |
+
{
|
154 |
+
return false;
|
155 |
+
}
|
156 |
+
if (!fwrite($handle, $content))
|
157 |
+
{
|
158 |
+
return false;
|
159 |
+
}
|
160 |
+
@chmod($path, 0664);
|
161 |
+
fclose($handle);
|
162 |
+
return true;
|
163 |
+
}
|
164 |
+
|
165 |
+
public function set($secname, $pname, $val)
|
166 |
+
{
|
167 |
+
$this->_props[$secname][$pname] = $val;
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* retrieve property value with default if not found
|
172 |
+
*
|
173 |
+
* @param string $secname
|
174 |
+
* section name
|
175 |
+
* @param string $pname
|
176 |
+
* property name
|
177 |
+
* @param string $default
|
178 |
+
* default value if not found (null if not set)
|
179 |
+
* @return string value if found or default if not found
|
180 |
+
*/
|
181 |
+
public function get($secname, $pname, $default = null)
|
182 |
+
{
|
183 |
+
if (isset($this->_props[$secname]) && isset($this->_props[$secname][$pname]))
|
184 |
+
{
|
185 |
+
$v = $this->_props[$secname][$pname];
|
186 |
+
return $v;
|
187 |
+
}
|
188 |
+
else
|
189 |
+
{
|
190 |
+
return $default;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
public function getsection($secname)
|
195 |
+
{
|
196 |
+
if (isset($this->_props[$secname]))
|
197 |
+
{
|
198 |
+
return $this->_props[$secname];
|
199 |
+
}
|
200 |
+
else
|
201 |
+
{
|
202 |
+
return array();
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
public function hasSection($secname)
|
207 |
+
{
|
208 |
+
return isset($this->_props[$secname]);
|
209 |
+
}
|
210 |
+
|
211 |
+
public function removeSection($secname)
|
212 |
+
{
|
213 |
+
if ($this->hasSection($secname))
|
214 |
+
{
|
215 |
+
unset($this->_props[$secname]);
|
216 |
+
}
|
217 |
+
}
|
218 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/remotefilegetter.php
ADDED
@@ -0,0 +1,381 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class RemoteFileGetter
|
4 |
+
{
|
5 |
+
protected $_errors;
|
6 |
+
protected $_user;
|
7 |
+
protected $_password;
|
8 |
+
protected $_logger = null;
|
9 |
+
|
10 |
+
public function setLogger($logger)
|
11 |
+
{
|
12 |
+
$this->_logger = $logger;
|
13 |
+
}
|
14 |
+
|
15 |
+
public function log($data)
|
16 |
+
{
|
17 |
+
if ($this->_logger != null)
|
18 |
+
{
|
19 |
+
$this->_logger->log($data);
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
public abstract function urlExists($url);
|
24 |
+
|
25 |
+
public abstract function copyRemoteFile($url, $dest);
|
26 |
+
|
27 |
+
// using credentials
|
28 |
+
public function setCredentials($user = null, $passwd = null)
|
29 |
+
{
|
30 |
+
$this->_user = $user;
|
31 |
+
$this->_password = $passwd;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getErrors()
|
35 |
+
{
|
36 |
+
return $this->_errors;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
class CURL_RemoteFileGetter extends RemoteFileGetter
|
41 |
+
{
|
42 |
+
protected $_cookie;
|
43 |
+
protected $_lookup_opts;
|
44 |
+
protected $_dl_opts;
|
45 |
+
protected $_lookup;
|
46 |
+
protected $_protocol;
|
47 |
+
protected $_creds;
|
48 |
+
protected $_opts;
|
49 |
+
protected $_user;
|
50 |
+
protected $_password;
|
51 |
+
|
52 |
+
public function __construct()
|
53 |
+
{
|
54 |
+
$this->_opts=array(
|
55 |
+
'http'=>array('lookup'=>$this->initBaseOptions('http', 'lookup'),
|
56 |
+
'dl'=>$this->initBaseOptions('http', 'dl')),
|
57 |
+
'https'=>array('lookup'=>$this->initBaseOptions('https', 'lookup'),
|
58 |
+
'dl'=>$this->initBaseOptions('https', 'dl')),
|
59 |
+
'ftp'=>array('dl'=>$this->initBaseOptions('ftp','dl'))
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
public function initBaseOptions($protocol,$mode)
|
64 |
+
{
|
65 |
+
$curlopts=array();
|
66 |
+
switch ($protocol)
|
67 |
+
{
|
68 |
+
case 'http':
|
69 |
+
case 'https':
|
70 |
+
switch($mode)
|
71 |
+
{
|
72 |
+
case 'lookup':
|
73 |
+
$curlopts=array(
|
74 |
+
// we want the response
|
75 |
+
CURLOPT_RETURNTRANSFER=>true,
|
76 |
+
// we want the headers
|
77 |
+
CURLOPT_HEADER=>true,
|
78 |
+
// we don't want the body
|
79 |
+
CURLOPT_NOBODY=>true,
|
80 |
+
// follow redirects
|
81 |
+
CURLOPT_FOLLOWLOCATION=>true,
|
82 |
+
// some stats on target
|
83 |
+
CURLOPT_FILETIME=>true);
|
84 |
+
break;
|
85 |
+
case 'dl':
|
86 |
+
$curlopts=array(
|
87 |
+
// force get
|
88 |
+
CURLOPT_HTTPGET=>true,
|
89 |
+
// no header
|
90 |
+
CURLOPT_HEADER=>false,
|
91 |
+
// we want body
|
92 |
+
CURLOPT_NOBODY=>false,
|
93 |
+
// redirect
|
94 |
+
CURLOPT_FOLLOWLOCATION=>true,
|
95 |
+
// handle 100 continue
|
96 |
+
CURLOPT_HTTPHEADER=>array('Expect:'),
|
97 |
+
// we don't want the response as we will store it in a file
|
98 |
+
CURLOPT_RETURNTRANSFER=>false,
|
99 |
+
//use binary
|
100 |
+
CURLOPT_BINARYTRANSFER=>true
|
101 |
+
);
|
102 |
+
break;
|
103 |
+
default:
|
104 |
+
break;
|
105 |
+
}
|
106 |
+
break;
|
107 |
+
/*
|
108 |
+
* Initializing for ftp
|
109 |
+
*/
|
110 |
+
case 'ftp':
|
111 |
+
$curlopts = array(
|
112 |
+
//longer timeouts for big files
|
113 |
+
CURLOPT_TIMEOUT =>300,
|
114 |
+
//use binary
|
115 |
+
CURLOPT_BINARYTRANSFER=>true,
|
116 |
+
CURLOPT_FOLLOWLOCATION=> 1,
|
117 |
+
//Better compatibility with some FTP Servers
|
118 |
+
CURLOPT_FTP_USE_EPSV=>0,
|
119 |
+
//no need to return anything, we'll have a file pointer
|
120 |
+
CURLOPT_RETURNTRANSFER=>0);
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
return $curlopts;
|
124 |
+
}
|
125 |
+
|
126 |
+
public function setAuthOptions($context,&$opts,$user=null,$pass=null)
|
127 |
+
{
|
128 |
+
$creds="";
|
129 |
+
if ($user == null)
|
130 |
+
{
|
131 |
+
$user=$this->_user;
|
132 |
+
$pass=$this->_password;
|
133 |
+
}
|
134 |
+
|
135 |
+
if($user)
|
136 |
+
{
|
137 |
+
$creds=$user.":";
|
138 |
+
}
|
139 |
+
|
140 |
+
if($pass)
|
141 |
+
{
|
142 |
+
$creds.=$pass;
|
143 |
+
}
|
144 |
+
|
145 |
+
if (!is_null($creds) && $creds != "" && !isset($opts[CURLOPT_USERPWD]))
|
146 |
+
{
|
147 |
+
if (substr($context['scheme'], 0, 4) == "http")
|
148 |
+
{
|
149 |
+
$opts[CURLOPT_HTTPAUTH] = CURLAUTH_ANY;
|
150 |
+
$opts[CURLOPT_UNRESTRICTED_AUTH] = true;
|
151 |
+
}
|
152 |
+
$opts[CURLOPT_USERPWD] = "$creds";
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
/*
|
157 |
+
* Creating a CURL context with adequate options from an URL For a given URL host/port/user , the same context is reused for optimizing performance
|
158 |
+
*/
|
159 |
+
public function createContext($url)
|
160 |
+
{
|
161 |
+
// handle spaces in url
|
162 |
+
$curl_url = str_replace(" ", "%20", $url);
|
163 |
+
// parsing url components
|
164 |
+
$comps = parse_url($url);
|
165 |
+
if ($comps == false || !isset($this->_opts[$comps['scheme']]))
|
166 |
+
{
|
167 |
+
throw new Exception("Unsupported URL : $url");
|
168 |
+
}
|
169 |
+
|
170 |
+
// create a curl context
|
171 |
+
$ch = curl_init();
|
172 |
+
$opts=$this->_opts[$comps['scheme']];
|
173 |
+
$ctx=array("curlhandle"=>$ch,"opts"=>$opts,"scheme"=>$comps['scheme']);
|
174 |
+
|
175 |
+
/*
|
176 |
+
* Inline user/pass if in url
|
177 |
+
*/
|
178 |
+
if (isset($comps['user']))
|
179 |
+
{
|
180 |
+
$ctx["creds"]=array($comps['user'],$comps['password']);
|
181 |
+
}
|
182 |
+
return $ctx;
|
183 |
+
}
|
184 |
+
|
185 |
+
public function destroyContext($context)
|
186 |
+
{
|
187 |
+
curl_close($context["curlhandle"]);
|
188 |
+
}
|
189 |
+
|
190 |
+
|
191 |
+
public function urlExists($remoteurl)
|
192 |
+
{
|
193 |
+
$context = $this->createContext($remoteurl);
|
194 |
+
// assume existing urls
|
195 |
+
if (!isset($context["opts"]["lookup"]))
|
196 |
+
{
|
197 |
+
return true;
|
198 |
+
}
|
199 |
+
$ch=$context["curlhandle"];
|
200 |
+
$opts=$context["opts"]["lookup"];
|
201 |
+
$this->setAuthOptions($context,$opts);
|
202 |
+
// optimized lookup through curl
|
203 |
+
curl_setopt_array($ch, $opts);
|
204 |
+
|
205 |
+
|
206 |
+
/* Get the HTML or whatever is linked in $url. */
|
207 |
+
$response = curl_exec($ch);
|
208 |
+
if ($context['scheme'] == "http" || $context['scheme'] == "https")
|
209 |
+
{
|
210 |
+
/* Check for 404 (file not found). */
|
211 |
+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
212 |
+
$exists = ($httpCode < 400);
|
213 |
+
/* retry on error */
|
214 |
+
|
215 |
+
if ($httpCode == 503 or $httpCode == 403)
|
216 |
+
{
|
217 |
+
/* wait for a half second */
|
218 |
+
usleep(500000);
|
219 |
+
$response = curl_exec($ch);
|
220 |
+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
221 |
+
$exists = ($httpCode < 400);
|
222 |
+
}
|
223 |
+
}
|
224 |
+
$this->destroyContext($context);
|
225 |
+
return $exists;
|
226 |
+
}
|
227 |
+
|
228 |
+
// using credentials
|
229 |
+
public function setCredentials($user = null, $passwd = null)
|
230 |
+
{
|
231 |
+
$this->_user = $user;
|
232 |
+
$this->_password = $passwd;
|
233 |
+
}
|
234 |
+
|
235 |
+
// using cookie
|
236 |
+
public function setCookie($cookie = null)
|
237 |
+
{
|
238 |
+
$this->_cookie = $cookie;
|
239 |
+
}
|
240 |
+
|
241 |
+
public function copyRemoteFile($url, $dest)
|
242 |
+
{
|
243 |
+
$result = false;
|
244 |
+
$this->_errors=array();
|
245 |
+
try
|
246 |
+
{
|
247 |
+
$result = $this->getRemoteFile($url, $dest, $this->_cookie);
|
248 |
+
}
|
249 |
+
catch (Exception $e)
|
250 |
+
{
|
251 |
+
$this->_errors = array("type"=>"source error","message"=>$e->getMessage(),"exception"=>$e);
|
252 |
+
}
|
253 |
+
return $result;
|
254 |
+
}
|
255 |
+
|
256 |
+
public function setURLOptions($url, &$optab)
|
257 |
+
{
|
258 |
+
$optab[CURLOPT_URL] = $url;
|
259 |
+
}
|
260 |
+
|
261 |
+
|
262 |
+
public function getRemoteFile($url, $dest, $authmode = null, $cookies = null)
|
263 |
+
{
|
264 |
+
$context = $this->createContext($url);
|
265 |
+
$ch=$context['curlhandle'];
|
266 |
+
$dl_opts = $context['opts']['dl'];
|
267 |
+
$outname = $dest;
|
268 |
+
|
269 |
+
if ($cookies)
|
270 |
+
{
|
271 |
+
|
272 |
+
if (substr($url, 0, 4) == "http")
|
273 |
+
{
|
274 |
+
$dl_opts[CURLOPT_COOKIE] = $cookies;
|
275 |
+
}
|
276 |
+
}
|
277 |
+
|
278 |
+
$fp = fopen($outname, "w");
|
279 |
+
if ($fp == false)
|
280 |
+
{
|
281 |
+
$this->destroyContext($context);
|
282 |
+
throw new Exception("Cannot write file:$outname");
|
283 |
+
}
|
284 |
+
$dl_opts[CURLOPT_FILE] = $fp;
|
285 |
+
$this->setURLOptions($url, $dl_opts);
|
286 |
+
$this->setAuthOptions($context,$dl_opts);
|
287 |
+
|
288 |
+
|
289 |
+
// Download the file , force expect to nothing to avoid buffer save problem
|
290 |
+
curl_setopt_array($ch, $dl_opts);
|
291 |
+
$inf = curl_getinfo($ch);
|
292 |
+
if (!curl_exec($ch))
|
293 |
+
{
|
294 |
+
if (curl_error($ch) != "")
|
295 |
+
{
|
296 |
+
$err = "Cannot fetch $url :" . curl_error($ch);
|
297 |
+
}
|
298 |
+
else
|
299 |
+
{
|
300 |
+
$err = "CURL Error downloading $url";
|
301 |
+
}
|
302 |
+
$this->destroyContext($context);
|
303 |
+
fclose($fp);
|
304 |
+
unlink($dest);
|
305 |
+
throw new Exception($err);
|
306 |
+
}
|
307 |
+
else
|
308 |
+
{
|
309 |
+
$proto=$context['scheme'];
|
310 |
+
if($proto=='http' || $proto=='https')
|
311 |
+
{
|
312 |
+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
313 |
+
$ok = ($httpCode < 400);
|
314 |
+
if(!$ok)
|
315 |
+
{
|
316 |
+
fclose($fp);
|
317 |
+
@unlink($outname);
|
318 |
+
throw new Exception('Cannot fetch URL :'.$url);
|
319 |
+
}
|
320 |
+
}
|
321 |
+
}
|
322 |
+
|
323 |
+
fclose($fp);
|
324 |
+
$this->destroyContext($context);
|
325 |
+
|
326 |
+
return true;
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
class URLFopen_RemoteFileGetter extends RemoteFileGetter
|
331 |
+
{
|
332 |
+
|
333 |
+
public function urlExists($url)
|
334 |
+
{
|
335 |
+
$fname = $url;
|
336 |
+
$h = @fopen($fname, "r");
|
337 |
+
if ($h !== false)
|
338 |
+
{
|
339 |
+
$exists = true;
|
340 |
+
fclose($h);
|
341 |
+
}
|
342 |
+
unset($h);
|
343 |
+
}
|
344 |
+
|
345 |
+
public function copyRemoteFile($url, $dest)
|
346 |
+
{
|
347 |
+
if (!$this->urlExists($url))
|
348 |
+
{
|
349 |
+
$this->_errors = array("type"=>"target error","message"=>"URL $url is unreachable");
|
350 |
+
return false;
|
351 |
+
}
|
352 |
+
|
353 |
+
$ok = @copy($url, $dest);
|
354 |
+
if (!$ok)
|
355 |
+
{
|
356 |
+
$this->_errors = error_get_last();
|
357 |
+
}
|
358 |
+
return $ok;
|
359 |
+
}
|
360 |
+
}
|
361 |
+
|
362 |
+
class RemoteFileGetterFactory
|
363 |
+
{
|
364 |
+
private static $__fginsts = array();
|
365 |
+
|
366 |
+
public static function getFGInstance($id = "default")
|
367 |
+
{
|
368 |
+
if (!isset(self::$__fginsts[$id]))
|
369 |
+
{
|
370 |
+
if (function_exists("curl_init"))
|
371 |
+
{
|
372 |
+
self::$__fginsts[$id] = new CURL_RemoteFileGetter();
|
373 |
+
}
|
374 |
+
else
|
375 |
+
{
|
376 |
+
self::$__fginsts[$id] = new URLFopen_RemoteFileGetter();
|
377 |
+
}
|
378 |
+
}
|
379 |
+
return self::$__fginsts[$id];
|
380 |
+
}
|
381 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/inc/timecounter.php
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Time counter class
|
5 |
+
* This class provides a way to measure :
|
6 |
+
*
|
7 |
+
* - time
|
8 |
+
* - counters
|
9 |
+
*
|
10 |
+
* store results into many categories for many timing aspects
|
11 |
+
*
|
12 |
+
* It is based on 2 levels :
|
13 |
+
* - sources : labels under which timing categories will be stored, it is a label, most of the time, a method name
|
14 |
+
* - categories : for each source, you can store many infos like "inDB","processing" and so on....
|
15 |
+
*
|
16 |
+
* time measure can be divided into phases, so you can measure different subparts of your processing like "initialization","lookup" aso....
|
17 |
+
* many counters can also be defined at the same category leve
|
18 |
+
* At the end, the timecounter will give this kind of results
|
19 |
+
*
|
20 |
+
* + cat1
|
21 |
+
* +timers
|
22 |
+
* + phase1 => time for phase 1 of cat1 of source 1
|
23 |
+
* + phase2 => time for phase 2 of cat1 of source 1
|
24 |
+
* +counters
|
25 |
+
* + counter1 => value of counter 1 of cat 1 of source 1
|
26 |
+
* + cat2
|
27 |
+
*
|
28 |
+
* Sources, categories & phases could be added dynamically, each time a new phase/counter/category or source is
|
29 |
+
* declared trough calls to addCounter, initTime,exitTime that does not exist yet, a container is created for it.
|
30 |
+
*
|
31 |
+
* sources are tags. categories are more like containers
|
32 |
+
*/
|
33 |
+
class TimeCounter
|
34 |
+
{
|
35 |
+
protected $_timingcats = array();
|
36 |
+
protected $_defaultsrc = "";
|
37 |
+
protected $_timingcontext = array();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Constructor
|
41 |
+
*
|
42 |
+
* @param string $defaultsrc
|
43 |
+
* : default timing source
|
44 |
+
*/
|
45 |
+
public function __construct($defaultsrc = "*")
|
46 |
+
{
|
47 |
+
$this->_defaultsrc = $defaultsrc;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Initializes default timing categories to use
|
52 |
+
*
|
53 |
+
* @param unknown $tcats
|
54 |
+
* array of timing categories
|
55 |
+
*/
|
56 |
+
public function initTimingCats($tcats)
|
57 |
+
{
|
58 |
+
foreach ($tcats as $tcat)
|
59 |
+
{
|
60 |
+
$this->_timingcats[$tcat] = array("_counters"=>array(),"_timers"=>array());
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* returns the content for a given timing category name
|
66 |
+
*
|
67 |
+
* @param string $cat
|
68 |
+
* : timing category name
|
69 |
+
* @return array informations for given category
|
70 |
+
*/
|
71 |
+
public function getTimingCategory($cat)
|
72 |
+
{
|
73 |
+
return $this->_timingcats[$cat];
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* return all timers
|
78 |
+
*
|
79 |
+
* @return all timers info by category
|
80 |
+
*/
|
81 |
+
public function getTimers()
|
82 |
+
{
|
83 |
+
$timers = array();
|
84 |
+
foreach ($this->_timingcats as $cname => $info)
|
85 |
+
{
|
86 |
+
$timers[$cname] = $info['_timers'];
|
87 |
+
}
|
88 |
+
return $timers;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* return all counters
|
93 |
+
*
|
94 |
+
* @return all counters info by category
|
95 |
+
*/
|
96 |
+
public function getCounters()
|
97 |
+
{
|
98 |
+
$counters = array();
|
99 |
+
foreach ($this->_timingcats as $cname => $info)
|
100 |
+
{
|
101 |
+
$counters[$cname] = $info['_counters'];
|
102 |
+
}
|
103 |
+
return $counters;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* creates a new counter
|
108 |
+
*
|
109 |
+
* @param string $cname
|
110 |
+
* : counter name
|
111 |
+
* @param string $tcats
|
112 |
+
* : array of category names to add counter to, if null => all categories
|
113 |
+
*/
|
114 |
+
public function addCounter($cname, $tcats = null)
|
115 |
+
{
|
116 |
+
if ($tcats == null)
|
117 |
+
{
|
118 |
+
$tcats = array_keys($this->_timingcats);
|
119 |
+
}
|
120 |
+
|
121 |
+
foreach ($tcats as $tcat)
|
122 |
+
{
|
123 |
+
if (!isset($this->_timingcats[$tcat]))
|
124 |
+
{
|
125 |
+
$this->_timingcats[$tcat] = array("_counters"=>array(),"_timers"=>array());
|
126 |
+
}
|
127 |
+
$this->_timingcats[$tcat]["_counters"][$cname] = 0;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* initializes a new counter
|
133 |
+
*
|
134 |
+
* @param string $cname
|
135 |
+
* : counter name
|
136 |
+
* @param string $tcats
|
137 |
+
* : array of category names to initialize counter for, if null => all categories
|
138 |
+
*/
|
139 |
+
public function initCounter($cname, $tcats = null)
|
140 |
+
{
|
141 |
+
if ($tcats == null)
|
142 |
+
{
|
143 |
+
$tcats = array_keys($this->_timingcats);
|
144 |
+
}
|
145 |
+
foreach ($tcats as $tcat)
|
146 |
+
{
|
147 |
+
$this->_timingcats[$tcat]["_counters"][$cname] = 0;
|
148 |
+
}
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* increments a counter
|
153 |
+
*
|
154 |
+
* @param string $cname
|
155 |
+
* : counter name
|
156 |
+
* @param string $tcats
|
157 |
+
* : array of category names to initialize counter for, if null => all categories
|
158 |
+
*/
|
159 |
+
public function incCounter($cname, $tcats = null)
|
160 |
+
{
|
161 |
+
if ($tcats == null)
|
162 |
+
{
|
163 |
+
$tcats = array_keys($this->_timingcats);
|
164 |
+
}
|
165 |
+
foreach ($tcats as $tcat)
|
166 |
+
{
|
167 |
+
if (!isset($this->_timingcats[$tcat]["_counters"][$cname]))
|
168 |
+
{
|
169 |
+
$this->_timingcats[$tcat]["_counters"][$cname] = 0;
|
170 |
+
}
|
171 |
+
$this->_timingcats[$tcat]["_counters"][$cname]++;
|
172 |
+
}
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Initializes a timer
|
177 |
+
*
|
178 |
+
* @param string $phase
|
179 |
+
* : timer phase to initialize
|
180 |
+
* @param string $src
|
181 |
+
* : source tag
|
182 |
+
* @param string $tcat
|
183 |
+
* : timing category to initialize timer for
|
184 |
+
*/
|
185 |
+
public function initTime($phase = "global", $src = null, $tcat = null)
|
186 |
+
{
|
187 |
+
if (isset($src))
|
188 |
+
{
|
189 |
+
array_push($this->_timingcontext, $src);
|
190 |
+
$this->_timingcontext = array_values(array_unique($this->_timingcontext));
|
191 |
+
}
|
192 |
+
if (count($this->_timingcontext) == 0)
|
193 |
+
return;
|
194 |
+
|
195 |
+
if (!isset($tcat))
|
196 |
+
{
|
197 |
+
$tcats = $this->_timingcats;
|
198 |
+
}
|
199 |
+
else
|
200 |
+
{
|
201 |
+
$tcats = array($tcat=>$this->_timingcats[$tcat]);
|
202 |
+
}
|
203 |
+
$t = microtime(true);
|
204 |
+
|
205 |
+
foreach ($tcats as $tcat => $dummy)
|
206 |
+
{
|
207 |
+
if (!isset($this->_timingcats[$tcat]["_timers"][$phase]))
|
208 |
+
{
|
209 |
+
$this->_timingcats[$tcat]["_timers"][$phase] = array();
|
210 |
+
}
|
211 |
+
$ctxc = count($this->_timingcontext);
|
212 |
+
for ($i = 0; $i < $ctxc; $i++)
|
213 |
+
{
|
214 |
+
$src = $this->_timingcontext[$i];
|
215 |
+
if (!isset($this->_timingcats[$tcat]["_timers"][$phase][$src]))
|
216 |
+
{
|
217 |
+
$this->_timingcats[$tcat]["_timers"][$phase][$src] = array("init"=>$t,"dur"=>0);
|
218 |
+
}
|
219 |
+
$this->_timingcats[$tcat]["_timers"][$phase][$src]["start"] = $t;
|
220 |
+
}
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* closes a timer for a given phase on a given category for a given source
|
226 |
+
*
|
227 |
+
* @param unknown $phase
|
228 |
+
* : time phase to exit
|
229 |
+
* @param string $src
|
230 |
+
* : source tag
|
231 |
+
* @param string $tcat
|
232 |
+
* : timing category
|
233 |
+
*/
|
234 |
+
public function exitTime($phase, $src = null, $tcat = null)
|
235 |
+
{
|
236 |
+
$targets = $this->_timingcontext;
|
237 |
+
if (count($targets) == 0)
|
238 |
+
{
|
239 |
+
return;
|
240 |
+
}
|
241 |
+
if (isset($src) && in_array($src, $this->_timingcontext))
|
242 |
+
{
|
243 |
+
$targets = array($src);
|
244 |
+
}
|
245 |
+
|
246 |
+
$ctargets = count($targets);
|
247 |
+
|
248 |
+
if ($ctargets == 0)
|
249 |
+
return;
|
250 |
+
if ($tcat == null)
|
251 |
+
{
|
252 |
+
$tcats = $this->_timingcats;
|
253 |
+
}
|
254 |
+
else
|
255 |
+
{
|
256 |
+
$tcats = array($tcat=>$this->_timingcats[$tcat]);
|
257 |
+
}
|
258 |
+
$end = microtime(true);
|
259 |
+
foreach ($tcats as $tcat => $phasetimes)
|
260 |
+
{
|
261 |
+
for ($i = 0; $i < $ctargets; $i++)
|
262 |
+
{
|
263 |
+
$src = $targets[$i];
|
264 |
+
if (isset($this->_timingcats[$tcat]["_timers"][$phase][$src]))
|
265 |
+
{
|
266 |
+
$this->_timingcats[$tcat]["_timers"][$phase][$src]["end"] = $end;
|
267 |
+
$this->_timingcats[$tcat]["_timers"][$phase][$src]["dur"] += $end -
|
268 |
+
$this->_timingcats[$tcat]["_timers"][$phase][$src]["start"];
|
269 |
+
}
|
270 |
+
else
|
271 |
+
{
|
272 |
+
echo "Invalid timing source : $src";
|
273 |
+
}
|
274 |
+
}
|
275 |
+
}
|
276 |
+
$this->_timingcontext = array_diff($this->_timingcontext, $targets);
|
277 |
+
}
|
278 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/magmi_datapump.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("properties.php");
|
3 |
+
|
4 |
+
class Magmi_DataPumpFactory
|
5 |
+
{
|
6 |
+
protected static $_factoryprops = null;
|
7 |
+
|
8 |
+
static function getDataPumpInstance($pumptype)
|
9 |
+
{
|
10 |
+
if (self::$_factoryprops == null)
|
11 |
+
{
|
12 |
+
self::$_factoryprops = new Properties();
|
13 |
+
self::$_factoryprops->load(dirname(__FILE__) . DIRSEP . "pumpfactory.ini");
|
14 |
+
}
|
15 |
+
$pumpinfo = self::$_factoryprops->get("DATAPUMPS", $pumptype, "");
|
16 |
+
$arr = explode("::", $pumpinfo);
|
17 |
+
if (count($arr) == 2)
|
18 |
+
{
|
19 |
+
$pumpfile = $arr[0];
|
20 |
+
$pumpclass = $arr[1];
|
21 |
+
|
22 |
+
try
|
23 |
+
{
|
24 |
+
require_once (dirname(__FILE__) . DIRSEP . "$pumpfile.php");
|
25 |
+
$pumpinst = new $pumpclass();
|
26 |
+
}
|
27 |
+
catch (Exception $e)
|
28 |
+
{
|
29 |
+
$pumpinst = null;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
else
|
33 |
+
{
|
34 |
+
echo "Invalid Pump Type";
|
35 |
+
}
|
36 |
+
return $pumpinst;
|
37 |
+
}
|
38 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/magmi_datapumpdatasource.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* This is a fake datasource for datapump, it just does nothing ;)
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
*/
|
8 |
+
class Magmi_DatapumpDS extends Magmi_Datasource
|
9 |
+
{
|
10 |
+
|
11 |
+
public function getPluginInfo()
|
12 |
+
{
|
13 |
+
return array("name"=>"DataPump Datasource","author"=>"Dweeves","version"=>"1.0.0");
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/productimport_datapump.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("magmi_productimportengine.php");
|
3 |
+
|
4 |
+
class Magmi_ProductImport_DataPump
|
5 |
+
{
|
6 |
+
protected $_engine = null;
|
7 |
+
protected $_params = array();
|
8 |
+
protected $_logger = null;
|
9 |
+
protected $_importcolumns = array();
|
10 |
+
protected $_defaultvalues = array();
|
11 |
+
protected $_stats;
|
12 |
+
protected $_crow;
|
13 |
+
protected $_rstep = 100;
|
14 |
+
protected $_mdpatched = false;
|
15 |
+
|
16 |
+
public function __construct()
|
17 |
+
{
|
18 |
+
$this->_engine = new Magmi_ProductImportEngine();
|
19 |
+
$this->_engine->setBuiltinPluginClasses("*datasources",
|
20 |
+
dirname(__FILE__) . DIRSEP . "magmi_datapumpdatasource.php::Magmi_DatapumpDS");
|
21 |
+
|
22 |
+
$this->_stats["tstart"] = microtime(true);
|
23 |
+
// differential
|
24 |
+
$this->_stats["tdiff"] = $this->_stats["tstart"];
|
25 |
+
}
|
26 |
+
|
27 |
+
public function setReportingStep($rstep)
|
28 |
+
{
|
29 |
+
$this->_rstep = $rstep;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function beginImportSession($profile, $mode, $logger = null)
|
33 |
+
{
|
34 |
+
$this->_engine->setLogger($logger);
|
35 |
+
$this->_engine->initialize();
|
36 |
+
$this->_params = array("profile"=>$profile,"mode"=>$mode);
|
37 |
+
$this->_engine->engineInit($this->_params);
|
38 |
+
$this->_engine->initImport($this->_params);
|
39 |
+
// intermediary report step
|
40 |
+
$this->_engine->initDbqStats();
|
41 |
+
$pstep = $this->_engine->getProp("GLOBAL", "step", 0.5);
|
42 |
+
// read each line
|
43 |
+
$this->_stats["lastrec"] = 0;
|
44 |
+
$this->_stats["lastdbtime"] = 0;
|
45 |
+
$this->crow = 0;
|
46 |
+
}
|
47 |
+
|
48 |
+
public function getEngine()
|
49 |
+
{
|
50 |
+
return $this->_engine;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function setDefaultValues($dv = array())
|
54 |
+
{
|
55 |
+
$this->_defaultvalues = $dv;
|
56 |
+
}
|
57 |
+
|
58 |
+
public function ingest($item = array())
|
59 |
+
{
|
60 |
+
$item = array_merge($this->_defaultvalues, $item);
|
61 |
+
$diff = array_diff(array_keys($item), $this->_importcolumns);
|
62 |
+
if (count($diff) > 0)
|
63 |
+
{
|
64 |
+
$this->_importcolumns = array_keys($item);
|
65 |
+
// process columns
|
66 |
+
$this->_engine->callPlugins("itemprocessors", "processColumnList", $this->_importcolumns);
|
67 |
+
$this->_engine->initAttrInfos($this->_importcolumns);
|
68 |
+
}
|
69 |
+
$res = $this->_engine->processDataSourceLine($item, $this->_rstep, $this->_stats["tstart"],
|
70 |
+
$this->_stats["tdiff"], $this->_stats["lastdbtime"], $this->stats["lastrec"]);
|
71 |
+
return $res;
|
72 |
+
}
|
73 |
+
|
74 |
+
public function endImportSession()
|
75 |
+
{
|
76 |
+
$this->_engine->reportStats($this->_engine->getCurrentRow(), $this->_stats["tstart"], $this->_stats["tdiff"],
|
77 |
+
$this->_stats["lastdbtime"], $this->stats["lastrec"]);
|
78 |
+
$skustats = $this->_engine->getSkuStats();
|
79 |
+
$this->_engine->log("Skus imported OK:" . $skustats["ok"] . "/" . $skustats["nsku"], "info");
|
80 |
+
if ($skustats["ko"] > 0)
|
81 |
+
{
|
82 |
+
$this->_engine->log("Skus imported KO:" . $skustats["ko"] . "/" . $skustats["nsku"], "warning");
|
83 |
+
}
|
84 |
+
|
85 |
+
$this->_engine->exitImport();
|
86 |
+
}
|
87 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/integration/inc/pumpfactory.ini
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
[DATAPUMPS]
|
2 |
+
productimport=productimport_datapump::Magmi_ProductImport_Datapump
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/optimizer/magmi_optimizer_plugin.php
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_OptimizerPlugin extends Magmi_GeneralImportPlugin
|
4 |
+
{
|
5 |
+
|
6 |
+
public function getPluginInfo()
|
7 |
+
{
|
8 |
+
return array("name"=>"Magmi Optimizer","author"=>"Dweeves","version"=>"1.0.5",
|
9 |
+
"url"=>$this->pluginDocUrl("Magmi_Optimizer"));
|
10 |
+
}
|
11 |
+
|
12 |
+
public function beforeImport()
|
13 |
+
{
|
14 |
+
$tbls = array("eav_attribute_option_value"=>array("value","MAGMI_EAOV_OPTIMIZATION_IDX"),
|
15 |
+
"catalog_product_entity_media_gallery"=>array("value","MAGMI_CPEM_OPTIMIZATION_IDX"),
|
16 |
+
"catalog_category_entity_varchar"=>array("value","MAGMI_CCEV_OPTIMIZATION_IDX"),
|
17 |
+
"eav_attribute"=>array("attribute_code","MAGMI_EA_CODE_OPTIMIZATION_IDX"));
|
18 |
+
$this->log("Optimizing magmi", "info");
|
19 |
+
foreach ($tbls as $tblname => $idxinfo)
|
20 |
+
{
|
21 |
+
try
|
22 |
+
{
|
23 |
+
$t = $this->tablename($tblname);
|
24 |
+
$this->log("Adding index {$idxinfo[1]} on $t", "info");
|
25 |
+
$sql = "ALTER TABLE $t ADD INDEX {$idxinfo[1]} (`{$idxinfo[0]}`)";
|
26 |
+
$this->exec_stmt($sql);
|
27 |
+
}
|
28 |
+
catch (Exception $e)
|
29 |
+
{
|
30 |
+
// ignore exception
|
31 |
+
$this->log("Already optmized!", "info");
|
32 |
+
}
|
33 |
+
}
|
34 |
+
return true;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function initialize($params)
|
38 |
+
{}
|
39 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/reindex/magmi_reindexing_plugin.php
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_ReindexingPlugin extends Magmi_GeneralImportPlugin
|
4 |
+
{
|
5 |
+
protected $_reindex;
|
6 |
+
protected $_indexlist = "catalog_product_attribute,catalog_product_price,catalog_product_flat,catalog_category_flat,catalog_category_product,cataloginventory_stock,catalog_url,catalogsearch_fulltext,tag_summary";
|
7 |
+
protected $_mdh;
|
8 |
+
|
9 |
+
public function getPluginInfo()
|
10 |
+
{
|
11 |
+
return array("name"=>"Magmi Magento Reindexer","author"=>"Dweeves","version"=>"1.0.3a",
|
12 |
+
"url"=>$this->pluginDocUrl("Magmi_Magento_Reindexer"));
|
13 |
+
}
|
14 |
+
|
15 |
+
public function afterImport()
|
16 |
+
{
|
17 |
+
$this->fixFlat();
|
18 |
+
$this->log("running indexer", "info");
|
19 |
+
$this->updateIndexes();
|
20 |
+
return true;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function OptimEav()
|
24 |
+
{
|
25 |
+
$tables = array("catalog_product_entity_varchar","catalog_product_entity_int","catalog_product_entity_text",
|
26 |
+
"catalog_product_entity_decimal","catalog_product_entity_datetime","catalog_product_entity_media_gallery",
|
27 |
+
"catalog_product_entity_tier_price");
|
28 |
+
|
29 |
+
$cpe = $this->tablename('catalog_product_entity');
|
30 |
+
$this->log("Optmizing EAV Tables...", "info");
|
31 |
+
foreach ($tables as $t)
|
32 |
+
{
|
33 |
+
$this->log("Optmizing $t....", "info");
|
34 |
+
$sql = "DELETE ta.* FROM " . $this->tablename($t) . " as ta
|
35 |
+
LEFT JOIN $cpe as cpe on cpe.entity_id=ta.entity_id
|
36 |
+
WHERE ta.store_id=0 AND cpe.entity_id IS NULL";
|
37 |
+
$this->delete($sql);
|
38 |
+
$this->log("$t optimized", "info");
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
public function fixFlat()
|
43 |
+
{
|
44 |
+
$this->log("Cleaning flat tables before reindex...", "info");
|
45 |
+
$stmt = $this->exec_stmt("SHOW TABLES LIKE '" . $this->tablename('catalog_product_flat') . "%'", NULL, false);
|
46 |
+
while ($row = $stmt->fetch(PDO::FETCH_NUM))
|
47 |
+
{
|
48 |
+
$tname = $row[0];
|
49 |
+
// removing records in flat tables that are no more linked to entries in catalog_product_entity table
|
50 |
+
// for some reasons, this seem to happen
|
51 |
+
$sql = "DELETE cpf.* FROM $tname as cpf
|
52 |
+
LEFT JOIN " . $this->tablename('catalog_product_entity') . " as cpe ON cpe.entity_id=cpf.entity_id
|
53 |
+
WHERE cpe.entity_id IS NULL";
|
54 |
+
$this->delete($sql);
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
public function getPluginParamNames()
|
59 |
+
{
|
60 |
+
return array("REINDEX:indexes","REINDEX:phpcli");
|
61 |
+
}
|
62 |
+
|
63 |
+
public function getIndexList()
|
64 |
+
{
|
65 |
+
return $this->_indexlist;
|
66 |
+
}
|
67 |
+
|
68 |
+
public function updateIndexes()
|
69 |
+
{
|
70 |
+
// make sure we are not in session
|
71 |
+
if (session_id() !== "")
|
72 |
+
{
|
73 |
+
session_write_close();
|
74 |
+
}
|
75 |
+
$cl = $this->getParam("REINDEX:phpcli") . " shell/indexer.php";
|
76 |
+
$idxlstr = $this->getParam("REINDEX:indexes", "");
|
77 |
+
$idxlist = explode(",", $idxlstr);
|
78 |
+
if (count($idxlist) == 0)
|
79 |
+
{
|
80 |
+
$this->log("No indexes selected , skipping reindexing...", "warning");
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
foreach ($idxlist as $idx)
|
84 |
+
{
|
85 |
+
$tstart = microtime(true);
|
86 |
+
$this->log("Reindexing $idx....", "info");
|
87 |
+
|
88 |
+
// Execute Reindex command, and specify that it should be ran from Magento directory
|
89 |
+
$out = $this->_mdh->exec_cmd($cl, "--reindex $idx", $this->_mdh->getMagentoDir());
|
90 |
+
$this->log($out, "info");
|
91 |
+
$tend = microtime(true);
|
92 |
+
$this->log("done in " . round($tend - $tstart, 2) . " secs", "info");
|
93 |
+
if (Magmi_StateManager::getState() == "canceled")
|
94 |
+
{
|
95 |
+
exit();
|
96 |
+
}
|
97 |
+
flush();
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
public function isRunnable()
|
102 |
+
{
|
103 |
+
return array(FSHelper::getExecMode() != null,"");
|
104 |
+
}
|
105 |
+
|
106 |
+
public function initialize($params)
|
107 |
+
{
|
108 |
+
$magdir = Magmi_Config::getInstance()->getMagentoDir();
|
109 |
+
$this->_mdh = MagentoDirHandlerFactory::getInstance()->getHandler($magdir);
|
110 |
+
$this->log("Using execution mode :" . $this->_mdh->getexecmode(), "startup");
|
111 |
+
}
|
112 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/general/reindex/options_panel.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="plugin_description">This plugin calls magento reindex script
|
3 |
+
via calling php cli. please ensure security configuration enable
|
4 |
+
"shell_exec()" calls from php</div>
|
5 |
+
|
6 |
+
<div class="formline">
|
7 |
+
<span class="label">PHP CLI command</span> <span class="value"><input
|
8 |
+
type="text" name="REINDEX:phpcli"
|
9 |
+
value="<?php echo $this->getParam("REINDEX:phpcli","php")?>"></input></span>
|
10 |
+
</div>
|
11 |
+
<hr />
|
12 |
+
<input type="hidden" name="REINDEX:indexes" id="indexes"
|
13 |
+
value="<?php echo $this->getParam("REINDEX:indexes")?>"></input>
|
14 |
+
<div>
|
15 |
+
<a name="REINDEX:config"></a> <span>Indexing:</span><a
|
16 |
+
href="#REINDEX:config" onclick="fcheck(1);">All</a> <a
|
17 |
+
href="#REINDEX:config" onclick="fcheck(0)">None</a>
|
18 |
+
<ul>
|
19 |
+
<?php
|
20 |
+
$idxarr = explode(",", $this->_plugin->getIndexList());
|
21 |
+
$indexes = explode(",", $this->getParam("REINDEX:indexes"));
|
22 |
+
foreach ($idxarr as $indexname)
|
23 |
+
{
|
24 |
+
?>
|
25 |
+
<li><input type="checkbox" name="<?php echo $indexname?>"
|
26 |
+
class="_magindex" <?php if(in_array($indexname,$indexes)){?>
|
27 |
+
checked=checked <?php }?>><?php echo $indexname?></li>
|
28 |
+
<?php }?>
|
29 |
+
</ul>
|
30 |
+
</div>
|
31 |
+
<script type="text/javascript">
|
32 |
+
getIndexes=function()
|
33 |
+
{
|
34 |
+
var outs=[];
|
35 |
+
$$('._magindex').each(function(it){if(it.checked){outs.push(it.name)}});
|
36 |
+
return outs.join(",");
|
37 |
+
};
|
38 |
+
|
39 |
+
|
40 |
+
|
41 |
+
fcheck=function(t)
|
42 |
+
{
|
43 |
+
$$('._magindex').each(function(it){it.checked=t});
|
44 |
+
updateIndexes();
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
updateIndexes=function()
|
49 |
+
{
|
50 |
+
$('indexes').value=getIndexes();
|
51 |
+
}
|
52 |
+
|
53 |
+
$$('._magindex').each(function(it){it.observe('click',updateIndexes)});
|
54 |
+
</script>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/columnmapper/000_columnmapper.php
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class ColumnMappingItemProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
protected $_dcols = array();
|
12 |
+
|
13 |
+
public function getPluginInfo()
|
14 |
+
{
|
15 |
+
return array("name"=>"Column mapper","author"=>"Dweeves","version"=>"0.0.3b",
|
16 |
+
"url"=>$this->pluginDocUrl("Column_mapper"));
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
21 |
+
*
|
22 |
+
* @param Magmi_Engine $mmi
|
23 |
+
* : reference to magmi engine(convenient to perform database operations)
|
24 |
+
* @param unknown_type $item
|
25 |
+
* : modifiable reference to item before import
|
26 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
27 |
+
* @return bool :
|
28 |
+
* true if you want the item to be imported after your custom processing
|
29 |
+
* false if you want to skip item import after your processing
|
30 |
+
*/
|
31 |
+
public function processColumnList(&$cols, $params = null)
|
32 |
+
{
|
33 |
+
$icols = $cols;
|
34 |
+
$ocols = array();
|
35 |
+
$scols = array();
|
36 |
+
foreach ($icols as $cname)
|
37 |
+
{
|
38 |
+
if (isset($this->_dcols[$cname]))
|
39 |
+
{
|
40 |
+
$mlist = array_unique(explode(",", $this->_dcols[$cname]));
|
41 |
+
$ncol = array_shift($mlist);
|
42 |
+
$ocols[] = $ncol;
|
43 |
+
if ($ncol != $cname)
|
44 |
+
{
|
45 |
+
$this->log("Replacing Column $cname by $ncol", "startup");
|
46 |
+
}
|
47 |
+
if (count($mlist) > 0)
|
48 |
+
{
|
49 |
+
$scols = array_merge($scols, $mlist);
|
50 |
+
$this->log("Replicating Column $cname to " . implode(",", $mlist), "startup");
|
51 |
+
}
|
52 |
+
}
|
53 |
+
else
|
54 |
+
{
|
55 |
+
$ocols[] = $cname;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
$ocols = array_unique(array_merge($ocols, $scols));
|
59 |
+
$cols = $ocols;
|
60 |
+
return true;
|
61 |
+
}
|
62 |
+
|
63 |
+
public function processItemBeforeId(&$item, $params = null)
|
64 |
+
{
|
65 |
+
foreach ($this->_dcols as $oname => $mnames)
|
66 |
+
{
|
67 |
+
if (isset($item[$oname]))
|
68 |
+
{
|
69 |
+
$mapped = explode(",", $mnames);
|
70 |
+
foreach ($mapped as $mname)
|
71 |
+
{
|
72 |
+
$mnane = trim($mname);
|
73 |
+
$item[$mname] = $item[$oname];
|
74 |
+
}
|
75 |
+
if (!in_array($oname, $mapped))
|
76 |
+
{
|
77 |
+
unset($item[$oname]);
|
78 |
+
}
|
79 |
+
}
|
80 |
+
}
|
81 |
+
return true;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function initialize($params)
|
85 |
+
{
|
86 |
+
foreach ($params as $k => $v)
|
87 |
+
{
|
88 |
+
if (preg_match_all("/^CMAP:(.*)$/", $k, $m) && $k != "CMAP:columnlist")
|
89 |
+
{
|
90 |
+
$colname = rawurldecode($m[1][0]);
|
91 |
+
$this->_dcols[$colname] = $params[$k];
|
92 |
+
}
|
93 |
+
}
|
94 |
+
}
|
95 |
+
|
96 |
+
public function getPluginParams($params)
|
97 |
+
{
|
98 |
+
$pp = array();
|
99 |
+
foreach ($params as $k => $v)
|
100 |
+
{
|
101 |
+
if (preg_match("/^CMAP:.*$/", $k))
|
102 |
+
{
|
103 |
+
$pp[$k] = $v;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
return $pp;
|
107 |
+
}
|
108 |
+
|
109 |
+
static public function getCategory()
|
110 |
+
{
|
111 |
+
return "Input Data Preprocessing";
|
112 |
+
}
|
113 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/columnmapper/options_panel.php
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin enables to change column names from datasource before they
|
3 |
+
are handled by magmi. enter columns to set new name for in mapped
|
4 |
+
column list field, separated by commas (,) when leaving the field, new
|
5 |
+
fields will be inserted for filling new column names. <b>You can put
|
6 |
+
several values (comma separated) in the mapped column names,doing so ,
|
7 |
+
the column mapper will replicate values of column to map to all mapped
|
8 |
+
columns !!!</b>
|
9 |
+
</div>
|
10 |
+
<?php $clist=$this->fixListParam($this->getParam("CMAP:columnlist"))?>
|
11 |
+
<div>
|
12 |
+
<ul class="formline">
|
13 |
+
<li class="label">Mapped columns list</li>
|
14 |
+
<li class="value"><input type="text" id="CMAP:columnlist"
|
15 |
+
name="CMAP:columnlist" size="80" value="<?php echo $clist?>"
|
16 |
+
onblur="cmap_mf.buildparamlist()"></input></li>
|
17 |
+
</ul>
|
18 |
+
<div id="CMAP:columnsetup"></div>
|
19 |
+
</div>
|
20 |
+
<script type="text/javascript">
|
21 |
+
var cm_vals=<?php echo tdarray_to_js($this,'CMAP:columnlist','CMAP')?>;
|
22 |
+
var cm_linetpl='<ul class="formline"><li class="label">New name for col {fieldname}</li><li class="value"><input type="text" name="CMAP:{fieldname.enc}" value="{value}"></input></li></ul>';
|
23 |
+
cmap_mf=new magmi_multifield('CMAP:columnlist','CMAP:columnsetup',cm_linetpl,cm_vals);
|
24 |
+
cmap_mf.buildparamlist();
|
25 |
+
</script>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/defaultvalues/00_default_values.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class DefaultValuesItemProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
protected $_dset = array();
|
12 |
+
protected $_dcols = array();
|
13 |
+
|
14 |
+
public function getPluginInfo()
|
15 |
+
{
|
16 |
+
return array("name"=>"Default Values setter","author"=>"Dweeves","version"=>"0.0.5",
|
17 |
+
"url"=>$this->pluginDocUrl("Default_Values_setter"));
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
22 |
+
*
|
23 |
+
* @param Magmi_Engine $mmi
|
24 |
+
* : reference to magmi engine instance (convenient to perform database operations)
|
25 |
+
* @param unknown_type $item
|
26 |
+
* : modifiable reference to item before import
|
27 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
28 |
+
* @return bool :
|
29 |
+
* true if you want the item to be imported after your custom processing
|
30 |
+
* false if you want to skip item import after your processing
|
31 |
+
*/
|
32 |
+
public function processItemBeforeId(&$item, $params = null)
|
33 |
+
{
|
34 |
+
foreach ($this->_dcols as $col)
|
35 |
+
{
|
36 |
+
$item[$col] = $this->_dset[$col];
|
37 |
+
}
|
38 |
+
return true;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function processItemAfterId(&$item, $params = null)
|
42 |
+
{
|
43 |
+
return true;
|
44 |
+
}
|
45 |
+
|
46 |
+
/*
|
47 |
+
* public function processItemException(&$item,$params=null) { }
|
48 |
+
*/
|
49 |
+
public function initialize($params)
|
50 |
+
{
|
51 |
+
foreach ($params as $k => $v)
|
52 |
+
{
|
53 |
+
if (preg_match_all("/^DEFAULT:(.*)$/", $k, $m) && $k != "DEFAULT:columnlist")
|
54 |
+
{
|
55 |
+
$this->_dset[$m[1][0]] = $params[$k];
|
56 |
+
}
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
public function getPluginParams($params)
|
61 |
+
{
|
62 |
+
$pp = array();
|
63 |
+
foreach ($params as $k => $v)
|
64 |
+
{
|
65 |
+
if (preg_match("/^DEFAULT:.*$/", $k))
|
66 |
+
{
|
67 |
+
$pp[$k] = $v;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
return $pp;
|
71 |
+
}
|
72 |
+
|
73 |
+
public function processColumnList(&$cols, $params = null)
|
74 |
+
{
|
75 |
+
$dcols = array_diff(array_keys($this->_dset), array_intersect($cols, array_keys($this->_dset)));
|
76 |
+
foreach ($dcols as $col)
|
77 |
+
{
|
78 |
+
if (!empty($this->_dset[$col]))
|
79 |
+
{
|
80 |
+
$cols[] = $col;
|
81 |
+
$this->_dcols[] = $col;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
$this->log("Adding Columns " . implode(",", $dcols), "startup");
|
85 |
+
|
86 |
+
return true;
|
87 |
+
}
|
88 |
+
|
89 |
+
static public function getCategory()
|
90 |
+
{
|
91 |
+
return "Input Data Preprocessing";
|
92 |
+
}
|
93 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/defaultvalues/options_panel.php
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $clist=$this->fixListParam($this->getParam("DEFAULT:columnlist"))?>
|
2 |
+
<div class="plugin_description">This plugin enables to set some default
|
3 |
+
item values if not found in input source. enter columns to set default
|
4 |
+
value for in default attribute list field, separated by commas (,) when
|
5 |
+
leaving the field, new fields will be inserted for filling default
|
6 |
+
values.</div>
|
7 |
+
<div>
|
8 |
+
<ul class="formline">
|
9 |
+
<li class="label">Default attribute list</li>
|
10 |
+
<li class="value"><input type="text" id="DEFAULT:columnlist"
|
11 |
+
name="DEFAULT:columnlist" size="80" value="<?php echo $clist?>"
|
12 |
+
onblur="default_mf.buildparamlist()"></input></li>
|
13 |
+
</ul>
|
14 |
+
<div style="position: relative">
|
15 |
+
<div id="DEFAULT:columnsetup"></div>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
<script type="text/javascript">
|
19 |
+
var df_vals=<?php echo tdarray_to_js($this,'DEFAULT:columnlist','DEFAULT')?>;
|
20 |
+
var df_linetpl='<ul class="formline"><li class="label">Default {fieldname}</li><li class="value"><input type="text" name="DEFAULT:{fieldname.enc}" value="{value}"></input></li></ul>';
|
21 |
+
default_mf=new magmi_multifield('DEFAULT:columnlist','DEFAULT:columnsetup',df_linetpl,df_vals);
|
22 |
+
default_mf.buildparamlist();
|
23 |
+
</script>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/02_genericmapper.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class GenericMapperProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
protected $_mapping;
|
12 |
+
|
13 |
+
public function getPluginInfo()
|
14 |
+
{
|
15 |
+
return array("name"=>"Generic mapper","author"=>"Dweeves","version"=>"0.0.6a",
|
16 |
+
"url"=>$this->pluginDocUrl("Generic_mapper"));
|
17 |
+
}
|
18 |
+
|
19 |
+
/**
|
20 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
21 |
+
*
|
22 |
+
* @param Magmi_Engine $mmi
|
23 |
+
* : reference to magmi engine instance (convenient to perform database operations)
|
24 |
+
* @param unknown_type $item
|
25 |
+
* : modifiable reference to item before import
|
26 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
27 |
+
* @return bool :
|
28 |
+
* true if you want the item to be imported after your custom processing
|
29 |
+
* false if you want to skip item import after your processing
|
30 |
+
*/
|
31 |
+
public function processItemBeforeId(&$item, $params = null)
|
32 |
+
{
|
33 |
+
foreach (array_keys($item) as $k)
|
34 |
+
{
|
35 |
+
$mapped = false;
|
36 |
+
if (isset($this->_mapping["$k.csv"]))
|
37 |
+
{
|
38 |
+
$mpd = $this->_mapping["$k.csv"]["DIRECT"];
|
39 |
+
if (isset($mpd[$item[$k]]))
|
40 |
+
{
|
41 |
+
$item[$k] = $mpd[$item[$k]];
|
42 |
+
$mapped = true;
|
43 |
+
}
|
44 |
+
else
|
45 |
+
{
|
46 |
+
$mpr = $this->_mapping["$k.csv"]["RE"];
|
47 |
+
foreach ($mpr as $re => $value)
|
48 |
+
{
|
49 |
+
if (preg_match("|$re|msi", $item[$k]))
|
50 |
+
{
|
51 |
+
$item[$k] = preg_replace("|$re|", $value, $item[$k]);
|
52 |
+
$mapped = true;
|
53 |
+
break;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
// f not found,try common mappings
|
59 |
+
if (!$mapped)
|
60 |
+
{
|
61 |
+
$mpd = $this->_mapping["__common__.csv"]["DIRECT"];
|
62 |
+
if (isset($mpd[$item[$k]]))
|
63 |
+
{
|
64 |
+
$item[$k] = $mpd[$item[$k]];
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
return true;
|
69 |
+
}
|
70 |
+
|
71 |
+
public function initialize($params)
|
72 |
+
{
|
73 |
+
$this->_mapping = array();
|
74 |
+
|
75 |
+
$dlist = glob(dirname(__file__) . "/mappings/default/*.csv");
|
76 |
+
if ($dlist == false)
|
77 |
+
{
|
78 |
+
$dlist = array();
|
79 |
+
$this->log("No default mapping found", "warning");
|
80 |
+
}
|
81 |
+
$slist = glob(dirname(__file__) . "/mappings/*.csv");
|
82 |
+
if ($slist == false)
|
83 |
+
{
|
84 |
+
$slist = array();
|
85 |
+
$this->log("No custom mapping found", "startup");
|
86 |
+
}
|
87 |
+
$flist = array_merge($dlist, $slist);
|
88 |
+
foreach ($flist as $fname)
|
89 |
+
{
|
90 |
+
$idx = basename($fname);
|
91 |
+
if (!isset($this->_mapping[$idx]))
|
92 |
+
{
|
93 |
+
$this->_mapping[$idx] = array("DIRECT"=>array(),"RE"=>array());
|
94 |
+
}
|
95 |
+
$mf = fopen("$fname", "r");
|
96 |
+
while (($data = fgetcsv($mf, 1000, ",")) !== FALSE)
|
97 |
+
{
|
98 |
+
if (substr($data[0], 0, 4) == "_RE:")
|
99 |
+
{
|
100 |
+
$target = "RE";
|
101 |
+
$key = substr($data[0], 4);
|
102 |
+
}
|
103 |
+
else
|
104 |
+
{
|
105 |
+
$target = "DIRECT";
|
106 |
+
$key = $data[0];
|
107 |
+
}
|
108 |
+
$this->_mapping[$idx][$target][$key] = $data[1];
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
static public function getCategory()
|
114 |
+
{
|
115 |
+
return "Input Data Preprocessing";
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/__common__.csv
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
"Yes",1
|
2 |
+
"No",0
|
3 |
+
"yes",1
|
4 |
+
"no",0
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/backorders.csv
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
"No Backorders","0"
|
2 |
+
"Allow Qty Below 0","1"
|
3 |
+
"Allow Qty Below 0 and Notify Customer","2"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/country_of_manufacture.csv
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"Afghanistan","AF"
|
2 |
+
"Åland Islands","AX"
|
3 |
+
"Albania","AL"
|
4 |
+
"Algeria","DZ"
|
5 |
+
"American Samoa","AS"
|
6 |
+
"Andorra","AD"
|
7 |
+
"Angola","AO"
|
8 |
+
"Anguilla","AI"
|
9 |
+
"Antarctica","AQ"
|
10 |
+
"Antigua and Barbuda","AG"
|
11 |
+
"Argentina","AR"
|
12 |
+
"Armenia","AM"
|
13 |
+
"Aruba","AW"
|
14 |
+
"Australia","AU"
|
15 |
+
"Austria","AT"
|
16 |
+
"Azerbaijan","AZ"
|
17 |
+
"Bahamas","BS"
|
18 |
+
"Bahrain","BH"
|
19 |
+
"Bangladesh","BD"
|
20 |
+
"Barbados","BB"
|
21 |
+
"Belarus","BY"
|
22 |
+
"Belgium","BE"
|
23 |
+
"Belize","BZ"
|
24 |
+
"Benin","BJ"
|
25 |
+
"Bermuda","BM"
|
26 |
+
"Bhutan","BT"
|
27 |
+
"Bolivia","BO"
|
28 |
+
"Bosnia and Herzegovina","BA"
|
29 |
+
"Botswana","BW"
|
30 |
+
"Bouvet Island","BV"
|
31 |
+
"Brazil","BR"
|
32 |
+
"British Indian Ocean Territory","IO"
|
33 |
+
"British Virgin Islands","VG"
|
34 |
+
"Brunei","BN"
|
35 |
+
"Bulgaria","BG"
|
36 |
+
"Burkina Faso","BF"
|
37 |
+
"Burundi","BI"
|
38 |
+
"Cambodia","KH"
|
39 |
+
"Cameroon","CM"
|
40 |
+
"Canada","CA"
|
41 |
+
"Cape Verde","CV"
|
42 |
+
"Cayman Islands","KY"
|
43 |
+
"Central African Republic","CF"
|
44 |
+
"Chad","TD"
|
45 |
+
"Chile","CL"
|
46 |
+
"China","CN"
|
47 |
+
"Christmas Island","CX"
|
48 |
+
"Cocos [Keeling] Islands","CC"
|
49 |
+
"Colombia","CO"
|
50 |
+
"Comoros","KM"
|
51 |
+
"Congo - Brazzaville","CG"
|
52 |
+
"Congo - Kinshasa","CD"
|
53 |
+
"Cook Islands","CK"
|
54 |
+
"Costa Rica","CR"
|
55 |
+
"Côte d’Ivoire","CI"
|
56 |
+
"Croatia","HR"
|
57 |
+
"Cuba","CU"
|
58 |
+
"Cyprus","CY"
|
59 |
+
"Czech Republic","CZ"
|
60 |
+
"Denmark","DK"
|
61 |
+
"Djibouti","DJ"
|
62 |
+
"Dominica","DM"
|
63 |
+
"Dominican Republic","DO"
|
64 |
+
"Ecuador","EC"
|
65 |
+
"Egypt","EG"
|
66 |
+
"El Salvador","SV"
|
67 |
+
"Equatorial Guinea","GQ"
|
68 |
+
"Eritrea","ER"
|
69 |
+
"Estonia","EE"
|
70 |
+
"Ethiopia","ET"
|
71 |
+
"Falkland Islands","FK"
|
72 |
+
"Faroe Islands","FO"
|
73 |
+
"Fiji","FJ"
|
74 |
+
"Finland","FI"
|
75 |
+
"France","FR"
|
76 |
+
"French Guiana","GF"
|
77 |
+
"French Polynesia","PF"
|
78 |
+
"French Southern Territories","TF"
|
79 |
+
"Gabon","GA"
|
80 |
+
"Gambia","GM"
|
81 |
+
"Georgia","GE"
|
82 |
+
"Germany","DE"
|
83 |
+
"Ghana","GH"
|
84 |
+
"Gibraltar","GI"
|
85 |
+
"Greece","GR"
|
86 |
+
"Greenland","GL"
|
87 |
+
"Grenada","GD"
|
88 |
+
"Guadeloupe","GP"
|
89 |
+
"Guam","GU"
|
90 |
+
"Guatemala","GT"
|
91 |
+
"Guernsey","GG"
|
92 |
+
"Guinea","GN"
|
93 |
+
"Guinea-Bissau","GW"
|
94 |
+
"Guyana","GY"
|
95 |
+
"Haiti","HT"
|
96 |
+
"Heard Island and McDonald Islands","HM"
|
97 |
+
"Honduras","HN"
|
98 |
+
"Hong Kong SAR China","HK"
|
99 |
+
"Hungary","HU"
|
100 |
+
"Iceland","IS"
|
101 |
+
"India","IN"
|
102 |
+
"Indonesia","ID"
|
103 |
+
"Iran","IR"
|
104 |
+
"Iraq","IQ"
|
105 |
+
"Ireland","IE"
|
106 |
+
"Isle of Man","IM"
|
107 |
+
"Israel","IL"
|
108 |
+
"Italy","IT"
|
109 |
+
"Jamaica","JM"
|
110 |
+
"Japan","JP"
|
111 |
+
"Jersey","JE"
|
112 |
+
"Jordan","JO"
|
113 |
+
"Kazakhstan","KZ"
|
114 |
+
"Kenya","KE"
|
115 |
+
"Kiribati","KI"
|
116 |
+
"Kuwait","KW"
|
117 |
+
"Kyrgyzstan","KG"
|
118 |
+
"Laos","LA"
|
119 |
+
"Latvia","LV"
|
120 |
+
"Lebanon","LB"
|
121 |
+
"Lesotho","LS"
|
122 |
+
"Liberia","LR"
|
123 |
+
"Libya","LY"
|
124 |
+
"Liechtenstein","LI"
|
125 |
+
"Lithuania","LT"
|
126 |
+
"Luxembourg","LU"
|
127 |
+
"Macau SAR China","MO"
|
128 |
+
"Macedonia","MK"
|
129 |
+
"Madagascar","MG"
|
130 |
+
"Malawi","MW"
|
131 |
+
"Malaysia","MY"
|
132 |
+
"Maldives","MV"
|
133 |
+
"Mali","ML"
|
134 |
+
"Malta","MT"
|
135 |
+
"Marshall Islands","MH"
|
136 |
+
"Martinique","MQ"
|
137 |
+
"Mauritania","MR"
|
138 |
+
"Mauritius","MU"
|
139 |
+
"Mayotte","YT"
|
140 |
+
"Mexico","MX"
|
141 |
+
"Micronesia","FM"
|
142 |
+
"Moldova","MD"
|
143 |
+
"Monaco","MC"
|
144 |
+
"Mongolia","MN"
|
145 |
+
"Montenegro","ME"
|
146 |
+
"Montserrat","MS"
|
147 |
+
"Morocco","MA"
|
148 |
+
"Mozambique","MZ"
|
149 |
+
"Myanmar [Burma]","MM"
|
150 |
+
"Namibia","NA"
|
151 |
+
"Nauru","NR"
|
152 |
+
"Nepal","NP"
|
153 |
+
"Netherlands","NL"
|
154 |
+
"Netherlands Antilles","AN"
|
155 |
+
"New Caledonia","NC"
|
156 |
+
"New Zealand","NZ"
|
157 |
+
"Nicaragua","NI"
|
158 |
+
"Niger","NE"
|
159 |
+
"Nigeria","NG"
|
160 |
+
"Niue","NU"
|
161 |
+
"Norfolk Island","NF"
|
162 |
+
"Northern Mariana Islands","MP"
|
163 |
+
"North Korea","KP"
|
164 |
+
"Norway","NO"
|
165 |
+
"Oman","OM"
|
166 |
+
"Pakistan","PK"
|
167 |
+
"Palau","PW"
|
168 |
+
"Palestinian Territories","PS"
|
169 |
+
"Panama","PA"
|
170 |
+
"Papua New Guinea","PG"
|
171 |
+
"Paraguay","PY"
|
172 |
+
"Peru","PE"
|
173 |
+
"Philippines","PH"
|
174 |
+
"Pitcairn Islands","PN"
|
175 |
+
"Poland","PL"
|
176 |
+
"Portugal","PT"
|
177 |
+
"Puerto Rico","PR"
|
178 |
+
"Qatar","QA"
|
179 |
+
"Réunion","RE"
|
180 |
+
"Romania","RO"
|
181 |
+
"Russia","RU"
|
182 |
+
"Rwanda","RW"
|
183 |
+
"Saint Barthélemy","BL"
|
184 |
+
"Saint Helena","SH"
|
185 |
+
"Saint Kitts and Nevis","KN"
|
186 |
+
"Saint Lucia","LC"
|
187 |
+
"Saint Martin","MF"
|
188 |
+
"Saint Pierre and Miquelon","PM"
|
189 |
+
"Saint Vincent and the Grenadines","VC"
|
190 |
+
"Samoa","WS"
|
191 |
+
"San Marino","SM"
|
192 |
+
"São Tomé and Príncipe","ST"
|
193 |
+
"Saudi Arabia","SA"
|
194 |
+
"Senegal","SN"
|
195 |
+
"Serbia","RS"
|
196 |
+
"Seychelles","SC"
|
197 |
+
"Sierra Leone","SL"
|
198 |
+
"Singapore","SG"
|
199 |
+
"Slovakia","SK"
|
200 |
+
"Slovenia","SI"
|
201 |
+
"Solomon Islands","SB"
|
202 |
+
"Somalia","SO"
|
203 |
+
"South Africa","ZA"
|
204 |
+
"South Georgia and the South Sandwich Islands","GS"
|
205 |
+
"South Korea","KR"
|
206 |
+
"Spain","ES"
|
207 |
+
"Sri Lanka","LK"
|
208 |
+
"Sudan","SD"
|
209 |
+
"Suriname","SR"
|
210 |
+
"Svalbard and Jan Mayen","SJ"
|
211 |
+
"Swaziland","SZ"
|
212 |
+
"Sweden","SE"
|
213 |
+
"Switzerland","CH"
|
214 |
+
"Syria","SY"
|
215 |
+
"Taiwan","TW"
|
216 |
+
"Tajikistan","TJ"
|
217 |
+
"Tanzania","TZ"
|
218 |
+
"Thailand","TH"
|
219 |
+
"Timor-Leste","TL"
|
220 |
+
"Togo","TG"
|
221 |
+
"Tokelau","TK"
|
222 |
+
"Tonga","TO"
|
223 |
+
"Trinidad and Tobago","TT"
|
224 |
+
"Tunisia","TN"
|
225 |
+
"Turkey","TR"
|
226 |
+
"Turkmenistan","TM"
|
227 |
+
"Turks and Caicos Islands","TC"
|
228 |
+
"Tuvalu","TV"
|
229 |
+
"Uganda","UG"
|
230 |
+
"Ukraine","UA"
|
231 |
+
"United Arab Emirates","AE"
|
232 |
+
"United Kingdom","GB"
|
233 |
+
"United States","US"
|
234 |
+
"Uruguay","UY"
|
235 |
+
"U.S. Minor Outlying Islands","UM"
|
236 |
+
"U.S. Virgin Islands","VI"
|
237 |
+
"Uzbekistan","UZ"
|
238 |
+
"Vanuatu","VU"
|
239 |
+
"Vatican City","VA"
|
240 |
+
"Venezuela","VE"
|
241 |
+
"Vietnam","VN"
|
242 |
+
"Wallis and Futuna","WF"
|
243 |
+
"Western Sahara","EH"
|
244 |
+
"Yemen","YE"
|
245 |
+
"Zambia","ZM"
|
246 |
+
"Zimbabwe","ZW"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/msrp_display_actual_price_type.csv
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
"In Cart","2"
|
2 |
+
"Before Order Confirmation","3"
|
3 |
+
"On Gesture","1"
|
4 |
+
"Use config","0"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/msrp_enabled.csv
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
"No",0
|
2 |
+
"Yes",1
|
3 |
+
"Use config",2
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/options_container.csv
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
"Product Info Column","container1"
|
2 |
+
"Block after Info Column","container2"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/page_layout.csv
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"No layout updates",""
|
2 |
+
"CMS Page","cms_one_column"
|
3 |
+
"Product Description Page","two_columns_left"
|
4 |
+
"1 column","one_column"
|
5 |
+
"2 columns with right bar","two_columns_right"
|
6 |
+
"3 columns","three_columns"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/status.csv
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
"Enabled",1
|
2 |
+
"Disabled",2
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/tax_class_id.csv
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
"None","0"
|
2 |
+
"default","1"
|
3 |
+
"Taxable Goods","2"
|
4 |
+
"Shipping","4"
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/mappings/default/visibility.csv
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
"Not Visible Individually",1
|
2 |
+
"Catalog",2
|
3 |
+
"Search",3
|
4 |
+
"Catalog, Search",4
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/genericmapper/options_panel.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin provides value mapping for csv values before they are
|
3 |
+
handled by magmi typically visibility & page_layout need mapping
|
4 |
+
for magmi to process them correctly. to change the mappings accordingly
|
5 |
+
to your config,please edit the csv files located at :
|
6 |
+
<pre>[magmi_dir]/plugins/itemprocessors/genericmapper/mappings</pre>
|
7 |
+
the csv files have the following names [column_to_map].csv
|
8 |
+
</div>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/importlimiter/01_importlimiter.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ImportLimiter extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $_recranges;
|
6 |
+
protected $_rmax = -1;
|
7 |
+
protected $_filters;
|
8 |
+
protected $_col_filter = NULL;
|
9 |
+
|
10 |
+
public function getPluginInfo()
|
11 |
+
{
|
12 |
+
return array("name"=>"Magmi Import Limiter","author"=>"Dweeves","version"=>"0.0.6",
|
13 |
+
"url"=>$this->pluginDocUrl("Magmi_Import_Limiter"));
|
14 |
+
}
|
15 |
+
|
16 |
+
public function filtermatch($item, $fltdef)
|
17 |
+
{
|
18 |
+
$negate = 0;
|
19 |
+
$field = $fltdef[0];
|
20 |
+
$match = false;
|
21 |
+
if ($field[0] == "!")
|
22 |
+
{
|
23 |
+
$field = substr($field, 1);
|
24 |
+
$negate = 1;
|
25 |
+
}
|
26 |
+
$re = $fltdef[1];
|
27 |
+
if (in_array($field, array_keys($item)))
|
28 |
+
{
|
29 |
+
$v = $item[$field];
|
30 |
+
$match = preg_match("|$re|", $v);
|
31 |
+
if ($negate)
|
32 |
+
{
|
33 |
+
$match = !$match;
|
34 |
+
}
|
35 |
+
if ($match)
|
36 |
+
{
|
37 |
+
$this->log("skipping sku {$item['sku']} => Filter '$field::$re'", "info");
|
38 |
+
}
|
39 |
+
}
|
40 |
+
return $match;
|
41 |
+
}
|
42 |
+
|
43 |
+
public function processItemBeforeId(&$item, $params = null)
|
44 |
+
{
|
45 |
+
$crow = $this->getCurrentRow();
|
46 |
+
$ok = (count($this->_recranges) == 0);
|
47 |
+
|
48 |
+
if (!$ok)
|
49 |
+
{
|
50 |
+
if ($this->_rmax > -1 && $crow == $this->_rmax)
|
51 |
+
{
|
52 |
+
$this->setLastItem($item);
|
53 |
+
}
|
54 |
+
foreach ($this->_recranges as $rr)
|
55 |
+
{
|
56 |
+
$ok = ($crow >= $rr[0] && ($crow <= $rr[1] || $rr[1] == -1));
|
57 |
+
if ($ok)
|
58 |
+
{
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
if ($ok)
|
65 |
+
{
|
66 |
+
foreach ($this->_filters as $fltdef)
|
67 |
+
{
|
68 |
+
// negative filters
|
69 |
+
$ok = $ok && (!$this->filtermatch($item, $fltdef));
|
70 |
+
if (!$ok)
|
71 |
+
{
|
72 |
+
break;
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
76 |
+
else
|
77 |
+
{
|
78 |
+
$this->log("Filtered row $crow not in range " . $this->getParam("LIMITER:ranges", ""));
|
79 |
+
}
|
80 |
+
|
81 |
+
return $ok;
|
82 |
+
}
|
83 |
+
|
84 |
+
public function parseFilters($fltstr)
|
85 |
+
{
|
86 |
+
$this->_filters = array();
|
87 |
+
if ($fltstr == "")
|
88 |
+
{
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
$fltlist = explode(";;", $fltstr);
|
92 |
+
foreach ($fltlist as $fltdef)
|
93 |
+
{
|
94 |
+
$fltinf = explode("::", $fltdef);
|
95 |
+
$this->_filters[] = $fltinf;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
public function parseRanges($rangestr)
|
100 |
+
{
|
101 |
+
$this->_recranges = array();
|
102 |
+
if ($rangestr == "")
|
103 |
+
{
|
104 |
+
return;
|
105 |
+
}
|
106 |
+
$rangelist = explode(",", $rangestr);
|
107 |
+
foreach ($rangelist as $rdef)
|
108 |
+
{
|
109 |
+
$rlist = explode("-", $rdef);
|
110 |
+
if ($rlist[0] == "")
|
111 |
+
{
|
112 |
+
$rlist[0] = -1;
|
113 |
+
}
|
114 |
+
else
|
115 |
+
{
|
116 |
+
$rmin = $rlist[0];
|
117 |
+
}
|
118 |
+
if (count($rlist) > 1)
|
119 |
+
{
|
120 |
+
if ($rlist[1] == "")
|
121 |
+
{
|
122 |
+
$rlist[1] = -1;
|
123 |
+
}
|
124 |
+
else
|
125 |
+
{
|
126 |
+
$rmax = $rlist[1];
|
127 |
+
if ($rmax > $this->_rmax && $this->_rmax != -1)
|
128 |
+
{
|
129 |
+
$this->_rmax = $rmax;
|
130 |
+
}
|
131 |
+
}
|
132 |
+
}
|
133 |
+
else
|
134 |
+
{
|
135 |
+
$rmax = $rmin;
|
136 |
+
}
|
137 |
+
$this->_recranges[] = array($rmin,$rmax);
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
public function processColumnList(&$cols, $params = null)
|
142 |
+
{
|
143 |
+
if (count($this->_col_filter) > 0)
|
144 |
+
{
|
145 |
+
$this->log("limiting columns to :" . implode(",", $this->_col_filter), "startup");
|
146 |
+
$cols = $this->_col_filter;
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
public function initialize($params)
|
151 |
+
{
|
152 |
+
$this->parseRanges($this->getParam("LIMITER:ranges", ""));
|
153 |
+
$this->parseFilters($this->getParam("LIMITER:filters", ""));
|
154 |
+
$this->_col_filter = explode(",", $this->getParam("LIMITER:col_filter"));
|
155 |
+
return true;
|
156 |
+
}
|
157 |
+
|
158 |
+
public function getPluginParamNames()
|
159 |
+
{
|
160 |
+
return array('LIMITER:ranges','LIMITER:filters','LIMITER:col_filter');
|
161 |
+
}
|
162 |
+
|
163 |
+
static public function getCategory()
|
164 |
+
{
|
165 |
+
return "Input Data Preprocessing";
|
166 |
+
}
|
167 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/importlimiter/options_panel.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin is made to limit magmi
|
2 |
+
import to selected record ranges or matching values. ranges are ranges
|
3 |
+
of rows to be imported filters are regexps or strings that if matched
|
4 |
+
will exclude record from import</div>
|
5 |
+
|
6 |
+
<div class="ifield">
|
7 |
+
<span class="">Column filter:</span><input type="text"
|
8 |
+
name="LIMITER:col_filter" size="80"
|
9 |
+
value="<?php echo $this->getParam("LIMITER:col_filter")?>"></input>
|
10 |
+
<div class="fieldhelp"></div>
|
11 |
+
<div class="fieldinfo">
|
12 |
+
This field defines what columns should be imported
|
13 |
+
<div class="fieldsyntax" style="display: none">
|
14 |
+
<pre>
|
15 |
+
You should put column names, comma separated ie : sku,qty
|
16 |
+
</pre>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
|
21 |
+
<div class="ifield">
|
22 |
+
<span class="">Limiter ranges:</span><input type="text"
|
23 |
+
name="LIMITER:ranges" size="80"
|
24 |
+
value="<?php echo $this->getParam("LIMITER:ranges")?>"></input>
|
25 |
+
<div class="fieldhelp"></div>
|
26 |
+
<div class="fieldinfo">
|
27 |
+
This field defines what lines should be imported
|
28 |
+
<div class="fieldsyntax" style="display: none">
|
29 |
+
<pre>
|
30 |
+
1-100 : for the first 100 records of csv
|
31 |
+
100- : for all records after 100 (including 100th)
|
32 |
+
1-10,40-50,67,78,89 : for records 1 to 10,40 to 50 , 67 , 78 & 89
|
33 |
+
</pre>
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
<div class="ifield">
|
38 |
+
|
39 |
+
<span class="">Limiter filters:</span><input type="text"
|
40 |
+
name="LIMITER:filters" size="80"
|
41 |
+
value="<?php echo $this->getParam("LIMITER:filters")?>"></input>
|
42 |
+
<div class="fieldhelp"></div>
|
43 |
+
<div class="fieldinfo">
|
44 |
+
This field defines what content should not be imported with a regexp
|
45 |
+
like syntax.
|
46 |
+
<div class="fieldsyntax" style="display: none">
|
47 |
+
<pre>
|
48 |
+
sku::00.* : exclude all skus that begin with 00
|
49 |
+
!name::.*blue.* : exclude all items with name not blue (see the ! before the "name" field to negate the filter)
|
50 |
+
sku:00.*;;!name::.*blue.* : exclude all items with skus that begin with 00 which name does not contain blue
|
51 |
+
</pre>
|
52 |
+
</div>
|
53 |
+
</div>
|
54 |
+
</div>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/productdeleter/options_panel.php
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugins should be used to delete
|
2 |
+
existing products</div>
|
3 |
+
<ul class="formline">
|
4 |
+
<li><input type="checkbox" name="PDEL:delsimples"
|
5 |
+
<?php if($this->getParam("PDEL:delsimples",false)==true){?>
|
6 |
+
checked="checked" <?php }?>>Delete children products</li>
|
7 |
+
|
8 |
+
</ul>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/productdeleter/productdeleter.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ProductDeleter extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
|
6 |
+
public function getPluginInfo()
|
7 |
+
{
|
8 |
+
return array("name"=>"Product Deleter","author"=>"Dweeves","version"=>"0.0.2",
|
9 |
+
"url"=>$this->pluginDocUrl("Product_Deleter"));
|
10 |
+
}
|
11 |
+
|
12 |
+
public function getPluginParamNames()
|
13 |
+
{
|
14 |
+
return array("PDEL:delsimples");
|
15 |
+
}
|
16 |
+
|
17 |
+
public function removeFromFlat($pid)
|
18 |
+
{
|
19 |
+
$this->log("Cleaning flat tables before reindex...", "info");
|
20 |
+
$stmt = $this->exec_stmt("SHOW TABLES LIKE '" . $this->tablename('catalog_product_flat') . "%'", NULL, false);
|
21 |
+
while ($row = $stmt->fetch(PDO::FETCH_NUM))
|
22 |
+
{
|
23 |
+
$tname = $row[0];
|
24 |
+
// removing records in flat tables that are no more linked to entries in catalog_product_entity table
|
25 |
+
// for some reasons, this seem to happen
|
26 |
+
$sql = "DELETE cpf.* FROM $tname as cpf
|
27 |
+
WHERE cpf.entity_id=?";
|
28 |
+
$this->delete($sql, $pid);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
public function processItemAfterId(&$item, $params = null)
|
33 |
+
{
|
34 |
+
|
35 |
+
// get item ids, since we are before id
|
36 |
+
$pid = $params["product_id"];
|
37 |
+
if (isset($item["magmi:delete"]) && $item["magmi:delete"] == 1)
|
38 |
+
{
|
39 |
+
$this->log("DELETING SKU '" . $item["sku"] . "' =>" . $pid, "info");
|
40 |
+
// delete simple products if flag set
|
41 |
+
if ($this->getParam("PDEL:delsimples", false) == true)
|
42 |
+
{
|
43 |
+
$childrensel = "SELECT entity_id FROM " . $this->tablename("catalog_product_entity") . " as cpe
|
44 |
+
JOIN " . $this->tablename("catalog_product_super_link") .
|
45 |
+
" as cpl ON cpl.parent_id=? AND cpe.entity_id=cpl.product_id";
|
46 |
+
$sql = "DELETE cpe.* FROM " . $this->tablename("catalog_product_entity") .
|
47 |
+
" cpe WHERE cpe.entity_id IN (SELECT s1.entity_id FROM ($childrensel) as s1)";
|
48 |
+
|
49 |
+
$this->delete($sql, $pid);
|
50 |
+
}
|
51 |
+
// delete from indexes table if store is set
|
52 |
+
$this->removeFromFlat($pid);
|
53 |
+
|
54 |
+
// delete product (this cascades for all eav & relations)
|
55 |
+
$sql = "DELETE FROM " . $this->tablename("catalog_product_entity") . " WHERE entity_id=?";
|
56 |
+
$this->delete($sql, $pid);
|
57 |
+
$this->log($sql, "info");
|
58 |
+
$item = array();
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/skufinder/001_skufinder.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class SkuFinderItemProcessor extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
private $_compchecked = FALSE;
|
6 |
+
|
7 |
+
public function getPluginInfo()
|
8 |
+
{
|
9 |
+
return array("name"=>"SKU Finder","author"=>"Dweeves","version"=>"0.0.2",
|
10 |
+
"url"=>$this->pluginDocUrl("SKU_Finder"));
|
11 |
+
}
|
12 |
+
|
13 |
+
public function processItemBeforeId(&$item, $params = null)
|
14 |
+
{
|
15 |
+
$matchfield = trim($this->getParam("SKUF:matchfield"));
|
16 |
+
// protection from tricky testers ;)
|
17 |
+
if ($matchfield == "sku")
|
18 |
+
{
|
19 |
+
return true;
|
20 |
+
}
|
21 |
+
$attinfo = $this->getAttrInfo($matchfield);
|
22 |
+
if ($this->_compchecked == FALSE)
|
23 |
+
{
|
24 |
+
// Checking attribute compatibility with sku matching
|
25 |
+
if ($attinfo == NULL)
|
26 |
+
{
|
27 |
+
$this->log("$matchfield is not a valid attribute", "error");
|
28 |
+
$item["__MAGMI_LAST__"] = 1;
|
29 |
+
return false;
|
30 |
+
}
|
31 |
+
if ($attinfo["is_unique"] == 0 || $attinfo["is_global"] == 0)
|
32 |
+
{
|
33 |
+
$this->log("sku matching attribute $matchfield must be unique & global scope");
|
34 |
+
$item["__MAGMI_LAST__"] = 1;
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
if ($attinfo["backend_type"] == "static")
|
38 |
+
{
|
39 |
+
$this->log("$matchfield is " . $attinfo["backend_type"] . ", it cannot be used as sku matching field.",
|
40 |
+
"error");
|
41 |
+
$item["__MAGMI_LAST__"] = 1;
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
if ($attinfo["frontend_input"] == "select" || $attinfo["frontend_input"] == "multiselect")
|
45 |
+
{
|
46 |
+
$this->log(
|
47 |
+
"$matchfield is " . $attinfo["frontend_input"] . ", it cannot be used as sku matching field.",
|
48 |
+
"error");
|
49 |
+
$item["__MAGMI_LAST__"] = 1;
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
$this->_compchecked = true;
|
53 |
+
}
|
54 |
+
|
55 |
+
// no item data for selected matching field, skipping
|
56 |
+
if (!isset($item[$matchfield]) && trim($item["matchfield"]) !== '')
|
57 |
+
{
|
58 |
+
$this->log("No value for $matchfield in datasource", "error");
|
59 |
+
return false;
|
60 |
+
}
|
61 |
+
// now find sku
|
62 |
+
$cpebt = $this->tablebname("catalog_product_entity_" . $attinfo["backend_type"]);
|
63 |
+
$sql = "SELECT sku FROM " . $this->tablename("catalog_product_entity") . " as cpe JOIN
|
64 |
+
$cpebt as cpebt ON cpebt.value=? AND cpebt.attribute_id=? AND cpebt.entity_id=cpe.entity_id";
|
65 |
+
$stmt = $this->select($sql, array($item[$matchfield],$attinfo["attribute_id"]));
|
66 |
+
$n = 0;
|
67 |
+
while ($result = $stmt->fetch())
|
68 |
+
{
|
69 |
+
// if more than one result, cannot match single sku
|
70 |
+
if ($n > 1)
|
71 |
+
{
|
72 |
+
$this->log("Several skus match $matchfield value : " . $item[$matchfield], "error");
|
73 |
+
return false;
|
74 |
+
}
|
75 |
+
else
|
76 |
+
{
|
77 |
+
$item["sku"] = $result["sku"];
|
78 |
+
}
|
79 |
+
$n++;
|
80 |
+
}
|
81 |
+
// if no item found, warning & skip
|
82 |
+
if ($n == 0)
|
83 |
+
{
|
84 |
+
$this->log("No sku found matching $matchfield value : " . $item[$matchfield], "warning");
|
85 |
+
return false;
|
86 |
+
}
|
87 |
+
// found a single sku ! item sku is in place, continue with processor chain
|
88 |
+
return true;
|
89 |
+
}
|
90 |
+
|
91 |
+
static public function getCategory()
|
92 |
+
{
|
93 |
+
return "Input Data Preprocessing";
|
94 |
+
}
|
95 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/base/itemprocessors/skufinder/options_panel.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugins can be used in <b>update</b> mode to find sku from custom
|
3 |
+
column in datasource. this column <b>MUST</b> be an attribute code
|
4 |
+
</div>
|
5 |
+
<ul class="formline">
|
6 |
+
<li class="label"><span>sku find attribute code</span></li>
|
7 |
+
<li class="value"><input type="text" name="SKUF:matchfield"
|
8 |
+
value="<?php $this->getParam("SKUF:matchfield","")?>"></li>
|
9 |
+
|
10 |
+
</ul>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/categories/categoryimport.php
ADDED
@@ -0,0 +1,464 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class CategoryImporter extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $_idcache = array();
|
6 |
+
protected $_catattr = array();
|
7 |
+
protected $_cattrinfos = array();
|
8 |
+
protected $_catroots = array();
|
9 |
+
protected $_catrootw = array();
|
10 |
+
protected $_cat_eid = null;
|
11 |
+
protected $_tsep;
|
12 |
+
// tricky escaped separator that matches slugging separator
|
13 |
+
protected $_escapedtsep = "---";
|
14 |
+
|
15 |
+
public function initialize($params)
|
16 |
+
{
|
17 |
+
$this->initCats();
|
18 |
+
$this->_cattrinfos = array("varchar"=>array("name"=>array(),"url_key"=>array(),"url_path"=>array()),
|
19 |
+
"int"=>array("is_active"=>array(),"is_anchor"=>array(),"include_in_menu"=>array()));
|
20 |
+
foreach ($this->_cattrinfos as $catype => $attrlist)
|
21 |
+
{
|
22 |
+
foreach (array_keys($attrlist) as $catatt)
|
23 |
+
{
|
24 |
+
$this->_cattrinfos[$catype][$catatt] = $this->getCatAttributeInfos($catatt);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
$this->_tsep = $this->getParam("CAT:treesep", "/");
|
28 |
+
}
|
29 |
+
|
30 |
+
public function initCats()
|
31 |
+
{
|
32 |
+
// zioigor - 20110426 missing call to tablename method for table_prfix
|
33 |
+
$t = $this->tablename("catalog_category_entity");
|
34 |
+
$csg = $this->tablename("core_store_group");
|
35 |
+
$cs = $this->tablename("core_store");
|
36 |
+
$ccev = $t . "_varchar";
|
37 |
+
$ea = $this->tablename("eav_attribute");
|
38 |
+
$result = $this->selectAll(
|
39 |
+
"SELECT cs.store_id,csg.website_id,cce.entity_type_id,cce.path,ccev.value as name
|
40 |
+
FROM $cs as cs
|
41 |
+
JOIN $csg as csg on csg.group_id=cs.group_id
|
42 |
+
JOIN $t as cce ON cce.entity_id=csg.root_category_id
|
43 |
+
JOIN $ea as ea ON ea.attribute_code='name' AND ea.entity_type_id=cce.entity_type_id
|
44 |
+
JOIN $ccev as ccev ON ccev.attribute_id=ea.attribute_id AND ccev.entity_id=cce.entity_id
|
45 |
+
");
|
46 |
+
foreach ($result as $row)
|
47 |
+
{
|
48 |
+
$rootinfo = array("path"=>$row["path"],"etid"=>$row["entity_type_id"],"name"=>$row["name"],
|
49 |
+
"rootarr"=>explode("/", $row["path"]));
|
50 |
+
$this->_catroots[$row["store_id"]] = $rootinfo;
|
51 |
+
$this->_catrootw[$row["website_id"]][] = $row["store_id"];
|
52 |
+
if ($this->_cat_eid == null)
|
53 |
+
{
|
54 |
+
$this->_cat_eid = $row["entity_type_id"];
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
public function getCatAttributeInfos($attcode)
|
60 |
+
{
|
61 |
+
$t = $this->tablename("eav_attribute");
|
62 |
+
$sql = "SELECT * FROM $t WHERE entity_type_id=? AND attribute_code=?";
|
63 |
+
$info = $this->selectAll($sql, array($this->_cat_eid,$attcode));
|
64 |
+
return $info[0];
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getCache($cdef, $bp)
|
68 |
+
{
|
69 |
+
$ck = "$bp::$cdef";
|
70 |
+
return $this->_idcache[$ck];
|
71 |
+
}
|
72 |
+
|
73 |
+
public function isInCache($cdef, $bp)
|
74 |
+
{
|
75 |
+
$ck = "$bp::$cdef";
|
76 |
+
return isset($this->_idcache[$ck]);
|
77 |
+
}
|
78 |
+
|
79 |
+
public function putInCache($cdef, $bp, $idarr)
|
80 |
+
{
|
81 |
+
$ck = "$bp::$cdef";
|
82 |
+
$this->_idcache[$ck] = $idarr;
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getPluginInfo()
|
86 |
+
{
|
87 |
+
return array("name"=>"On the fly category creator/importer","author"=>"Dweeves","version"=>"0.2.4",
|
88 |
+
"url"=>$this->pluginDocUrl("On_the_fly_category_creator/importer"));
|
89 |
+
}
|
90 |
+
|
91 |
+
public function getExistingCategory($parentpath, $cattr)
|
92 |
+
{
|
93 |
+
$cet = $this->tablename("catalog_category_entity");
|
94 |
+
$cetv = $this->tablename("catalog_category_entity_varchar");
|
95 |
+
$parentid = array_pop($parentpath);
|
96 |
+
$sql = "SELECT cet.entity_id FROM $cet as cet
|
97 |
+
JOIN $cetv as cetv ON cetv.entity_id=cet.entity_id AND cetv.attribute_id=? AND cetv.value=?
|
98 |
+
WHERE cet.parent_id=? ";
|
99 |
+
$catid = $this->selectone($sql,
|
100 |
+
array($this->_cattrinfos["varchar"]["name"]["attribute_id"],$cattr["name"],$parentid), "entity_id");
|
101 |
+
return $catid;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function getCategoryId($parentpath, $cattrs)
|
105 |
+
{
|
106 |
+
$cattrs["name"] = str_replace($this->_escapedtsep, $this->_tsep, $cattrs["name"]);
|
107 |
+
// get exisiting cat id
|
108 |
+
$catid = $this->getExistingCategory($parentpath, $cattrs);
|
109 |
+
// if found , return it
|
110 |
+
if ($catid != null)
|
111 |
+
{
|
112 |
+
return $catid;
|
113 |
+
}
|
114 |
+
// otherwise, get new category values from parent & siblings
|
115 |
+
$cet = $this->tablename("catalog_category_entity");
|
116 |
+
$path = implode("/", $parentpath);
|
117 |
+
$parentid = array_pop($parentpath);
|
118 |
+
// get child info using parent data
|
119 |
+
$sql = "SELECT cce.entity_type_id,cce.attribute_set_id,cce.level+1 as level,COALESCE(MAX(eac.position),0)+1 as position
|
120 |
+
FROM $cet as cce
|
121 |
+
LEFT JOIN $cet as eac ON eac.parent_id=cce.entity_id
|
122 |
+
WHERE cce.entity_id=?
|
123 |
+
GROUP BY eac.parent_id";
|
124 |
+
$info = $this->selectAll($sql, $parentid);
|
125 |
+
$info = $info[0];
|
126 |
+
// insert new category
|
127 |
+
$sql = "INSERT INTO $cet (entity_type_id,attribute_set_id,parent_id,position,level,path,children_count) VALUES (?,?,?,?,?,?,?)";
|
128 |
+
// insert empty path until we get category id
|
129 |
+
$data = array($info["entity_type_id"],$info["attribute_set_id"],$parentid,$info["position"],$info["level"],"",0);
|
130 |
+
// insert in db,get cat id
|
131 |
+
$catid = $this->insert($sql, $data);
|
132 |
+
|
133 |
+
unset($data);
|
134 |
+
// set category path with inserted category id
|
135 |
+
$sql = "UPDATE $cet SET path=?,created_at=NOW(),updated_at=NOW() WHERE entity_id=?";
|
136 |
+
$data = array("$path/$catid",$catid);
|
137 |
+
$this->update($sql, $data);
|
138 |
+
unset($data);
|
139 |
+
// set category attributes
|
140 |
+
foreach ($this->_cattrinfos as $tp => $attinfo)
|
141 |
+
{
|
142 |
+
$inserts = array();
|
143 |
+
$data = array();
|
144 |
+
$tb = $this->tablename("catalog_category_entity_$tp");
|
145 |
+
|
146 |
+
foreach ($attinfo as $attrcode => $attdata)
|
147 |
+
{
|
148 |
+
if (isset($attdata["attribute_id"]))
|
149 |
+
{
|
150 |
+
$inserts[] = "(?,?,?,?,?)";
|
151 |
+
$data[] = $info["entity_type_id"];
|
152 |
+
$data[] = $attdata["attribute_id"];
|
153 |
+
$data[] = 0; // store id 0 for categories
|
154 |
+
$data[] = $catid;
|
155 |
+
$data[] = $cattrs[$attrcode];
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
$sql = "INSERT INTO $tb (entity_type_id,attribute_id,store_id,entity_id,value) VALUES " .
|
160 |
+
implode(",", $inserts) . " ON DUPLICATE KEY UPDATE value=VALUES(`value`)";
|
161 |
+
$this->insert($sql, $data);
|
162 |
+
unset($data);
|
163 |
+
unset($inserts);
|
164 |
+
}
|
165 |
+
return $catid;
|
166 |
+
}
|
167 |
+
|
168 |
+
public function extractCatAttrs(&$catdef)
|
169 |
+
{
|
170 |
+
$cdefs = explode($this->_tsep, $catdef);
|
171 |
+
$odefs = array();
|
172 |
+
$clist = array();
|
173 |
+
foreach ($cdefs as $cdef)
|
174 |
+
{
|
175 |
+
|
176 |
+
$attrs = array();
|
177 |
+
$parts = explode("::", $cdef);
|
178 |
+
$cp = count($parts);
|
179 |
+
$cname = trim($parts[0]);
|
180 |
+
$odefs[] = $cname;
|
181 |
+
$attrs = array("name"=>$cname,"is_active"=>($cp > 1) ? $parts[1] : 1,"is_anchor"=>($cp > 2) ? $parts[2] : 1,
|
182 |
+
"include_in_menu"=>$cp > 3 ? $parts[3] : 1,"url_key"=>Slugger::slug($cname),
|
183 |
+
"url_path"=>Slugger::slug(implode("/", $odefs), true) . $this->getParam("CAT:urlending", ".html"));
|
184 |
+
$clist[] = $attrs;
|
185 |
+
}
|
186 |
+
$catdef = implode($this->_tsep, $odefs);
|
187 |
+
return $clist;
|
188 |
+
}
|
189 |
+
|
190 |
+
public function getCategoryIdsFromDef($pcatdef, $srdefs)
|
191 |
+
{
|
192 |
+
$srp = "%RP:base%";
|
193 |
+
foreach (array_keys($srdefs) as $tsrp)
|
194 |
+
{
|
195 |
+
// check which root we have
|
196 |
+
if (substr($pcatdef, 0, strlen($tsrp)) == $tsrp)
|
197 |
+
{
|
198 |
+
$srp = $tsrp;
|
199 |
+
break;
|
200 |
+
}
|
201 |
+
}
|
202 |
+
// remove explicit root
|
203 |
+
$pcatdef = str_replace($srp . $this->_tsep, "", $pcatdef);
|
204 |
+
$zcatparts = explode($this->_tsep, $pcatdef);
|
205 |
+
// cleaning parts (trimming, removing empty)
|
206 |
+
$pcatparts = array();
|
207 |
+
$czcatparts = count($zcatparts);
|
208 |
+
for ($i = 0; $i < $czcatparts; $i++)
|
209 |
+
{
|
210 |
+
$cp = trim($zcatparts[$i]);
|
211 |
+
if ($cp != "")
|
212 |
+
{
|
213 |
+
$pcatparts[] = $cp;
|
214 |
+
}
|
215 |
+
}
|
216 |
+
$catparts = array();
|
217 |
+
$catpos = array();
|
218 |
+
// build a position table to restore after cat ids will be created
|
219 |
+
foreach ($pcatparts as $cp)
|
220 |
+
{
|
221 |
+
$a = explode("::", $cp);
|
222 |
+
$catparts[] = $a[0];
|
223 |
+
$catpos[] = (count($a) > 1 ? $a[1] : "0");
|
224 |
+
// remove position to build catpart array
|
225 |
+
}
|
226 |
+
|
227 |
+
// build a position free category def
|
228 |
+
$catdef = implode($this->_tsep, $catparts);
|
229 |
+
|
230 |
+
// if full def is in cache, use it
|
231 |
+
if ($this->isInCache($catdef, $srp))
|
232 |
+
{
|
233 |
+
$catids = $this->getCache($catdef, $srp);
|
234 |
+
}
|
235 |
+
else
|
236 |
+
{
|
237 |
+
// category ids
|
238 |
+
$catids = array();
|
239 |
+
$lastcached = array();
|
240 |
+
|
241 |
+
// path as array , basepath is always "/" separated
|
242 |
+
$basearr = explode("/", $srdefs[$srp]["path"]);
|
243 |
+
// for each cat tree branch
|
244 |
+
$pdef = array();
|
245 |
+
foreach ($catparts as $catpart)
|
246 |
+
{
|
247 |
+
// ignore empty
|
248 |
+
if ($catpart == "")
|
249 |
+
{
|
250 |
+
continue;
|
251 |
+
}
|
252 |
+
// add it to the current tree level
|
253 |
+
$pdef[] = $catpart;
|
254 |
+
$ptest = implode($this->_tsep, $pdef);
|
255 |
+
// test for tree level in cache
|
256 |
+
if ($this->isInCache($ptest, $srp))
|
257 |
+
{
|
258 |
+
// if yes , set current known cat ids to corresponding cached branch
|
259 |
+
$catids = $this->getCache($ptest, $srp);
|
260 |
+
// store last cached branch
|
261 |
+
$lastcached = $pdef;
|
262 |
+
}
|
263 |
+
else
|
264 |
+
// no more tree info in cache,stop further retrieval, we need to create missing levels
|
265 |
+
{
|
266 |
+
break;
|
267 |
+
}
|
268 |
+
}
|
269 |
+
// add store tree root to category path
|
270 |
+
$curpath = array_merge($basearr, $catids);
|
271 |
+
// get categories attributes
|
272 |
+
$catattributes = $this->extractCatAttrs($catdef);
|
273 |
+
$ccatids = count($catids);
|
274 |
+
$ccatparts = count($catparts);
|
275 |
+
// iterate on missing levels.
|
276 |
+
for ($i = $ccatids; $i < $ccatparts; $i++)
|
277 |
+
{
|
278 |
+
if ($catparts[$i] == "")
|
279 |
+
{
|
280 |
+
continue;
|
281 |
+
}
|
282 |
+
// retrieve category id (by creating it if needed from categories attributes)
|
283 |
+
$catid = $this->getCategoryId($curpath, $catattributes[$i]);
|
284 |
+
// add newly created level to item category ids
|
285 |
+
$catids[] = $catid;
|
286 |
+
// add newly created level to current paths
|
287 |
+
$curpath[] = $catid;
|
288 |
+
// cache newly created levels
|
289 |
+
$lastcached[] = $catparts[$i];
|
290 |
+
$this->putInCache(implode($this->_tsep, $lastcached), $srp, $catids);
|
291 |
+
}
|
292 |
+
}
|
293 |
+
$ccatparts = count($catparts);
|
294 |
+
// added position handling
|
295 |
+
for ($i = 0; $i < $ccatparts; $i++)
|
296 |
+
{
|
297 |
+
$catids[$i] .= "::" . $catpos[$i];
|
298 |
+
}
|
299 |
+
|
300 |
+
return $catids;
|
301 |
+
}
|
302 |
+
|
303 |
+
public function processColumnList(&$cols, $params)
|
304 |
+
{
|
305 |
+
$cols[] = "category_ids";
|
306 |
+
$cols = array_unique($cols);
|
307 |
+
return true;
|
308 |
+
}
|
309 |
+
|
310 |
+
public function getStoreRootPaths(&$item)
|
311 |
+
{
|
312 |
+
$rootpaths = array();
|
313 |
+
$sids = $this->getItemStoreIds($item, 2);
|
314 |
+
$trimroot = "";
|
315 |
+
// remove admin from store ids (no category root on it)
|
316 |
+
if ($sids[0] == 0)
|
317 |
+
{
|
318 |
+
array_shift($sids);
|
319 |
+
}
|
320 |
+
// only admin store set,use websites store roots
|
321 |
+
if (count($sids) == 0)
|
322 |
+
{
|
323 |
+
$wsids = $this->getItemWebsites($item);
|
324 |
+
foreach ($wsids as $wsid)
|
325 |
+
{
|
326 |
+
$sids = array_merge($sids, $this->_catrootw[$wsid]);
|
327 |
+
}
|
328 |
+
}
|
329 |
+
$rootpaths["__error__"] = array();
|
330 |
+
// If using explicit root assignment , identify which root it is
|
331 |
+
if (preg_match_all("|\[(.*?)\]|", $item["categories"], $matches))
|
332 |
+
{
|
333 |
+
$cm1 = count($matches[1]);
|
334 |
+
// for each found explicit root
|
335 |
+
for ($i = 0; $i < $cm1; $i++)
|
336 |
+
{
|
337 |
+
// test store matching
|
338 |
+
foreach ($sids as $sid)
|
339 |
+
{
|
340 |
+
$srp = $this->_catroots[$sid];
|
341 |
+
$rname = $matches[1][$i];
|
342 |
+
$cmatch = (trim($rname) == $srp["name"]);
|
343 |
+
// found a store match
|
344 |
+
if ($cmatch)
|
345 |
+
{
|
346 |
+
// set a specific store key
|
347 |
+
$k = "%RP:$sid%";
|
348 |
+
// store root path definitions
|
349 |
+
$rootpaths[$k] = array("path"=>$srp["path"],"rootarr"=>$srp["rootarr"]);
|
350 |
+
$trimroot = trim($rname);
|
351 |
+
// replace root name with store root key
|
352 |
+
$item["categories"] = str_replace($matches[0][$i], $k, $item["categories"]);
|
353 |
+
break;
|
354 |
+
}
|
355 |
+
}
|
356 |
+
}
|
357 |
+
// now finding unmatched replaces
|
358 |
+
}
|
359 |
+
if (preg_match_all("|\[(.*?)\]|", $item["categories"], $matches))
|
360 |
+
{
|
361 |
+
$cm1 = count($matches[1]);
|
362 |
+
|
363 |
+
for ($i = 0; $i < $cm1; $i++)
|
364 |
+
{
|
365 |
+
$rootpaths['__error__'] = $matches[1];
|
366 |
+
}
|
367 |
+
}
|
368 |
+
$sids = array_keys($this->_catroots);
|
369 |
+
$srp = $this->_catroots[$sids[0]];
|
370 |
+
$rootpaths["%RP:base%"] = array("path"=>$srp["path"],"rootarr"=>$srp["rootarr"]);
|
371 |
+
|
372 |
+
return $rootpaths;
|
373 |
+
}
|
374 |
+
|
375 |
+
public function processEscaping($icats)
|
376 |
+
{
|
377 |
+
return str_replace("\\" . $this->_tsep, $this->_escapedtsep, $icats);
|
378 |
+
}
|
379 |
+
|
380 |
+
public function processItemAfterId(&$item, $params = null)
|
381 |
+
{
|
382 |
+
if (isset($item["categories"]))
|
383 |
+
{
|
384 |
+
// handle escaping
|
385 |
+
$icats = $this->processEscaping($item["categories"]);
|
386 |
+
// first apply category root on each category
|
387 |
+
|
388 |
+
$root = $this->getParam("CAT:baseroot", "");
|
389 |
+
if ($root != "")
|
390 |
+
{
|
391 |
+
$catlist = explode(";;", $icats);
|
392 |
+
$ccatlist = count($catlist);
|
393 |
+
for ($i = 0; $i < $ccatlist; $i++)
|
394 |
+
{
|
395 |
+
if (trim($catlist[$i]) != "")
|
396 |
+
{
|
397 |
+
$catlist[$i] = $root . $this->_tsep . $catlist[$i];
|
398 |
+
}
|
399 |
+
}
|
400 |
+
// recompose rooted categories
|
401 |
+
$item["categories"] = implode(";;", $catlist);
|
402 |
+
}
|
403 |
+
// get store root category paths, this may modify categories !!!!!
|
404 |
+
$rootpaths = $this->getStoreRootPaths($item);
|
405 |
+
|
406 |
+
// process escaping at the end
|
407 |
+
$icats = $this->processEscaping($item["categories"]);
|
408 |
+
|
409 |
+
if (count($rootpaths["__error__"]) > 0)
|
410 |
+
{
|
411 |
+
$this->log("Cannot find site root with names : " . implode(",", $rootpaths["__error__"]), "error");
|
412 |
+
return false;
|
413 |
+
}
|
414 |
+
// unset error if empty
|
415 |
+
unset($rootpaths["__error__"]);
|
416 |
+
// categories may have been changed , use escaping
|
417 |
+
$catlist = explode(";;", $icats);
|
418 |
+
$catids = array();
|
419 |
+
foreach ($catlist as $catdef)
|
420 |
+
{
|
421 |
+
$cdef = $this->getCategoryIdsFromDef($catdef, $rootpaths);
|
422 |
+
if ($this->getParam("CAT:lastonly", 0) == 1)
|
423 |
+
{
|
424 |
+
$cdef = array($cdef[count($cdef) - 1]);
|
425 |
+
}
|
426 |
+
$catids = array_unique(array_merge($catids, $cdef));
|
427 |
+
}
|
428 |
+
|
429 |
+
// assign to category roots
|
430 |
+
if ($this->getParam("CAT:lastonly", 0) == 0)
|
431 |
+
{
|
432 |
+
foreach (array_values($rootpaths) as $ra)
|
433 |
+
{
|
434 |
+
$id = array_pop($ra["rootarr"]);
|
435 |
+
$catids[] = $id;
|
436 |
+
}
|
437 |
+
}
|
438 |
+
$catids = array_unique($catids);
|
439 |
+
$item["category_ids"] = implode(",", $catids);
|
440 |
+
}
|
441 |
+
return true;
|
442 |
+
}
|
443 |
+
|
444 |
+
public function getPluginParamNames()
|
445 |
+
{
|
446 |
+
return array('CAT:baseroot','CAT:lastonly','CAT:urlending','CAT:treesep');
|
447 |
+
}
|
448 |
+
|
449 |
+
public function afterImport()
|
450 |
+
{
|
451 |
+
$this->log("Updating Category children count....", "info");
|
452 |
+
// automatically update all children_count for catalog categories
|
453 |
+
$cce = $this->tablename("catalog_category_entity");
|
454 |
+
$sql = "UPDATE $cce as cce
|
455 |
+
LEFT JOIN
|
456 |
+
(SELECT s1.entity_id as cid, COALESCE( COUNT( s2.entity_id ) , 0 ) AS cnt
|
457 |
+
FROM $cce AS s1
|
458 |
+
LEFT JOIN $cce AS s2 ON s2.parent_id = s1.entity_id
|
459 |
+
GROUP BY s1.entity_id) as sq ON sq.cid=cce.entity_id
|
460 |
+
SET cce.children_count=sq.cnt";
|
461 |
+
$this->update($sql);
|
462 |
+
return true;
|
463 |
+
}
|
464 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/categories/options_panel.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin let you create categories on the fly. it enable creation or
|
3 |
+
use of full category tree. multiple categories supported :)
|
4 |
+
<p>
|
5 |
+
the column (in csv or mapped) should be <b>categories</b>
|
6 |
+
</p>
|
7 |
+
<div class="fieldinfo">
|
8 |
+
<p>"light" syntax for the values:
|
9 |
+
level1_category/level2_category/level3_category,level1_category2/level2_category2</p>
|
10 |
+
<p>"verbose" syntax for the values:</p>
|
11 |
+
<p>all category levels separated by configurable tree separator ,
|
12 |
+
defaulting to /</p>
|
13 |
+
<p>in each level you can put [category name]:[x]:[y]:[z] (each of x,y
|
14 |
+
or z being optional) with</p>
|
15 |
+
<ul>
|
16 |
+
<li>x: 0 or 1 , is_active</li>
|
17 |
+
<li>y: 0 or 1 , is_anchor</li>
|
18 |
+
<li>x: 0 or 1 , include_in_menu</li>
|
19 |
+
</ul>
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
<div class="formline">
|
23 |
+
<?php $lastonly=$this->getParam("CAT:lastonly",0)?>
|
24 |
+
<span>Assign product to :</span><select name="CAT:lastonly">
|
25 |
+
<option value="0" <?php if($lastonly==0){?> selected="selected"
|
26 |
+
<?php }?>>all categories in tree</option>
|
27 |
+
<option value="1" <?php if($lastonly==1){?> selected="selected"
|
28 |
+
<?php }?>>last category of each branch</option>
|
29 |
+
</select>
|
30 |
+
<div class="fieldinfo">When checked, this options will assign product
|
31 |
+
only to the categories that are located at the last level of the
|
32 |
+
defined trees</div>
|
33 |
+
</div>
|
34 |
+
<div class="formline">
|
35 |
+
<span class="label">Tree level separator:</span> <span class="value"><input
|
36 |
+
type="text" name="CAT:treesep" maxlength=3 size=3
|
37 |
+
" value="<?php echo $this->getParam("CAT:treesep","/")?>"></input></span>
|
38 |
+
</div>
|
39 |
+
<div class="formline">
|
40 |
+
<span>base category tree:</span><input type="text" name="CAT:baseroot"
|
41 |
+
size="80" value="<?php echo $this->getParam("CAT:baseroot","")?>"></input>
|
42 |
+
<div class="fieldinfo">
|
43 |
+
this enable you to import the categories prepending a base root tree
|
44 |
+
to the values found in csv (use same syntax as described above)<br />
|
45 |
+
<b>IMPORTANT , use tree level separator defined above in case of
|
46 |
+
multilevel base tree</b>
|
47 |
+
</div>
|
48 |
+
</div>
|
49 |
+
<div class="formline">
|
50 |
+
<span>url ending:</span><input type="text" name="CAT:urlending"
|
51 |
+
size="80"
|
52 |
+
value="<?php echo $this->getParam("CAT:urlending",".html")?>"></input>
|
53 |
+
<div class="fieldinfo">Choose what url ending to put on category page
|
54 |
+
(defaults to .html)</div>
|
55 |
+
</div>
|
56 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/customoptions/options_panel.php
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin let you import custom
|
2 |
+
options for products</div>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/customoptions/pablo_customoptions.php
ADDED
@@ -0,0 +1,372 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class CustomOptionsItemProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
private $_containerMap = array("Product Info Column"=>"container1","Block after Info Column"=>"container2");
|
12 |
+
protected $_optids = array();
|
13 |
+
protected $_opttypeids = array();
|
14 |
+
protected $_multivals = array('drop_down','multiple','radio','checkbox');
|
15 |
+
|
16 |
+
public function getPluginInfo()
|
17 |
+
{
|
18 |
+
return array("name"=>"Custom Options","author"=>"Pablo & Dweeves","version"=>"0.0.7a",
|
19 |
+
"url"=>$this->pluginDocUrl("Custom_Options"));
|
20 |
+
}
|
21 |
+
|
22 |
+
public function processItemBeforeId(&$item, $params = null)
|
23 |
+
{
|
24 |
+
return true;
|
25 |
+
}
|
26 |
+
|
27 |
+
public function getOptId($field)
|
28 |
+
{
|
29 |
+
return isset($this->_optids[$field]) ? $this->_optids[$field] : null;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function setOptId($field, $val)
|
33 |
+
{
|
34 |
+
$this->_optids[$field] = $val;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getOptTypeIds($field)
|
38 |
+
{
|
39 |
+
return isset($this->_opttypeids[$field]) ? $this->_opttypeids[$field] : null;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function setOptTypeIds($field, $arr)
|
43 |
+
{
|
44 |
+
$this->_opttypeids[$field] = $arr;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function createOption($pid, $sids, $opt)
|
48 |
+
{
|
49 |
+
$t1 = $this->tablename('catalog_product_option');
|
50 |
+
$t2 = $this->tablename('catalog_product_option_title');
|
51 |
+
$t3 = $this->tablename('catalog_product_option_price');
|
52 |
+
$values = array($pid,$opt['type'],$opt['is_require'],$opt['sort_order'],$opt['sku']);
|
53 |
+
$f = "product_id, type, is_require,sort_order,sku";
|
54 |
+
$i = "?,?,?,?,?";
|
55 |
+
|
56 |
+
foreach (array("max_characters","file_extension","image_size_x","image_size_y") as $extra)
|
57 |
+
{
|
58 |
+
if (isset($opt[$extra]))
|
59 |
+
{
|
60 |
+
$values[] = $opt[$extra];
|
61 |
+
$i .= ",?";
|
62 |
+
$f .= ",$extra";
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
$optionId = $this->getOptId($opt['__field']);
|
67 |
+
if (!isset($optionId))
|
68 |
+
{
|
69 |
+
$sql = "INSERT INTO $t1 ($f) VALUES ($i)";
|
70 |
+
$optionId = $this->insert($sql, $values);
|
71 |
+
$this->setOptId($opt['__field'], $optionId);
|
72 |
+
}
|
73 |
+
$tvals = array();
|
74 |
+
$tins = array();
|
75 |
+
$pvals = array();
|
76 |
+
$pins = array();
|
77 |
+
|
78 |
+
foreach ($sids as $sid)
|
79 |
+
{
|
80 |
+
$tins[] = "(?,?,?)";
|
81 |
+
$tvals[] = $optionId;
|
82 |
+
$tvals[] = $sid;
|
83 |
+
$tvals[] = $opt["title"];
|
84 |
+
// price inserts only if option can have price
|
85 |
+
if (isset($opt['price']))
|
86 |
+
{
|
87 |
+
$pins[] = "(?,?,?,?)";
|
88 |
+
$pvals[] = $optionId;
|
89 |
+
$pvals[] = $sid;
|
90 |
+
$pvals[] = $opt["price"];
|
91 |
+
$pvals[] = $opt["price_type"];
|
92 |
+
}
|
93 |
+
// here we set admin values, so no more value needed since all other stores will share it
|
94 |
+
if ($sid == 0)
|
95 |
+
{
|
96 |
+
break;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
$sql = "INSERT IGNORE INTO $t2 (option_id, store_id, title) VALUES " . implode(",", $tins);
|
101 |
+
$this->insert($sql, $tvals);
|
102 |
+
|
103 |
+
if (count($pins) > 0)
|
104 |
+
{
|
105 |
+
$sql = "INSERT IGNORE INTO $t3 (option_id, store_id, price, price_type) VALUES " . implode(",", $pins);
|
106 |
+
$this->insert($sql, $pvals);
|
107 |
+
}
|
108 |
+
return $optionId;
|
109 |
+
}
|
110 |
+
|
111 |
+
public function createOptionValues($field, $sids, $valarr)
|
112 |
+
{
|
113 |
+
if (!isset($valarr) || count($valarr) == 0)
|
114 |
+
{
|
115 |
+
return;
|
116 |
+
}
|
117 |
+
$t4 = $this->tablename('catalog_product_option_type_value');
|
118 |
+
$t5 = $this->tablename('catalog_product_option_type_title');
|
119 |
+
$t6 = $this->tablename('catalog_product_option_type_price');
|
120 |
+
|
121 |
+
$ttvals = array();
|
122 |
+
$ttins = array();
|
123 |
+
$tpvals = array();
|
124 |
+
$tpins = array();
|
125 |
+
$optid = $this->getOptId($field);
|
126 |
+
|
127 |
+
$optionTypeIds = $this->getOptTypeIds($field);
|
128 |
+
$optionTypeId = null;
|
129 |
+
$cvalarr = count($valarr);
|
130 |
+
for ($i = 0; $i < $cvalarr; $i++)
|
131 |
+
{
|
132 |
+
$val = $valarr[$i];
|
133 |
+
if ($i < count($optionTypeIds))
|
134 |
+
{
|
135 |
+
$optionTypeId = $optionTypeIds[$i];
|
136 |
+
}
|
137 |
+
else
|
138 |
+
{
|
139 |
+
$sql = "INSERT INTO $t4
|
140 |
+
(option_id, sku, sort_order)
|
141 |
+
VALUES (?, ?, ?)";
|
142 |
+
$optionTypeId = $this->insert($sql, array($optid,$val["sku"],$val["sort_order"]));
|
143 |
+
$optionTypeIds[] = $optionTypeId;
|
144 |
+
}
|
145 |
+
foreach ($sids as $sid)
|
146 |
+
{
|
147 |
+
$ttins[] = "(?,?,?)";
|
148 |
+
$ttvals[] = $optionTypeId;
|
149 |
+
$ttvals[] = $sid;
|
150 |
+
$ttvals[] = $val["title"];
|
151 |
+
$tpins[] = "(?,?,?,?)";
|
152 |
+
$tpvals[] = $optionTypeId;
|
153 |
+
$tpvals[] = $sid;
|
154 |
+
$tpvals[] = $val["price"];
|
155 |
+
$tpvals[] = $val["price_type"];
|
156 |
+
// here we set admin values, so no more value needed since all other stores will share it
|
157 |
+
if ($sid == 0)
|
158 |
+
{
|
159 |
+
break;
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
$this->setOptTypeIds($field, $optionTypeIds);
|
165 |
+
|
166 |
+
$sql = "INSERT IGNORE INTO $t5 (option_type_id, store_id, title) VALUES " . implode(",", $ttins);
|
167 |
+
$this->insert($sql, $ttvals);
|
168 |
+
|
169 |
+
$sql = "INSERT IGNORE INTO $t6 (option_type_id, store_id, price, price_type) VALUES " . implode(",", $tpins);
|
170 |
+
$this->insert($sql, $tpvals);
|
171 |
+
}
|
172 |
+
|
173 |
+
public function isMultiValue($type)
|
174 |
+
{
|
175 |
+
$mv = in_array($type, $this->_multivals);
|
176 |
+
return $mv;
|
177 |
+
}
|
178 |
+
|
179 |
+
public function BuildCustomOption($field, $value)
|
180 |
+
{
|
181 |
+
$fieldParts = explode(":", $field);
|
182 |
+
$title = $fieldParts[0];
|
183 |
+
$type = $fieldParts[1];
|
184 |
+
$is_required = $fieldParts[2];
|
185 |
+
$sort_order = isset($fieldParts[3]) ? $fieldParts[3] : 0;
|
186 |
+
// @list($title,$type,$is_required,$sort_order) = $fieldParts;
|
187 |
+
$title = ucfirst(str_replace('_', ' ', $title));
|
188 |
+
$opt = array('__field'=>$field,'is_delete'=>0,'title'=>$title,'previous_group'=>'','previous_type'=>'',
|
189 |
+
'type'=>$type,'is_require'=>$is_required,'sort_order'=>$sort_order,'values'=>array());
|
190 |
+
|
191 |
+
$values = explode('|', $value);
|
192 |
+
|
193 |
+
foreach ($values as $v)
|
194 |
+
{
|
195 |
+
$ovalues = array();
|
196 |
+
$parts = explode(':', $v);
|
197 |
+
$mv = $this->isMultiValue($type);
|
198 |
+
if ($mv)
|
199 |
+
{
|
200 |
+
if (preg_match("|\[(.*)\]|", $parts[0], $matches))
|
201 |
+
{
|
202 |
+
$opt['title'] = $matches[1];
|
203 |
+
array_shift($parts);
|
204 |
+
}
|
205 |
+
$ovalues["title"] = ($parts[0] != '' ? $parts[0] : $title);
|
206 |
+
}
|
207 |
+
else
|
208 |
+
{
|
209 |
+
$opt['title'] = ($parts[0] != '' ? $parts[0] : $title);
|
210 |
+
}
|
211 |
+
|
212 |
+
$c = count($parts);
|
213 |
+
$price_type = ($c > 1) ? ($parts[1] != '' ? $parts[1] : 'fixed') : 'fixed';
|
214 |
+
$price = ($c > 2) ? $parts[2] : 0;
|
215 |
+
$sku = ($c > 3) ? $parts[3] : '';
|
216 |
+
$sort_order = ($c > 4) ? $parts[4] : 0;
|
217 |
+
|
218 |
+
switch ($type)
|
219 |
+
{
|
220 |
+
|
221 |
+
case 'file':
|
222 |
+
if ($c > 5)
|
223 |
+
{
|
224 |
+
$opt['file_extension'] = $parts[5];
|
225 |
+
}
|
226 |
+
if ($c > 6)
|
227 |
+
{
|
228 |
+
$opt['image_size_x'] = $parts[6];
|
229 |
+
}
|
230 |
+
if ($c > 6)
|
231 |
+
{
|
232 |
+
$opt['image_size_y'] = $parts[7];
|
233 |
+
}
|
234 |
+
$opt['sku'] = $sku;
|
235 |
+
$opt['price'] = $price;
|
236 |
+
break;
|
237 |
+
case 'field':
|
238 |
+
case 'area':
|
239 |
+
$opt['max_characters'] = $sort_order;
|
240 |
+
case 'date':
|
241 |
+
case 'date_time':
|
242 |
+
case 'time':
|
243 |
+
$opt['price_type'] = $price_type;
|
244 |
+
$opt['price'] = $price;
|
245 |
+
$opt['sku'] = $sku;
|
246 |
+
break;
|
247 |
+
/* NO BREAK */
|
248 |
+
case 'drop_down':
|
249 |
+
case 'radio':
|
250 |
+
case 'checkbox':
|
251 |
+
case 'multiple':
|
252 |
+
default:
|
253 |
+
$ovalues["price_type"] = $price_type;
|
254 |
+
$ovalues["price"] = $price;
|
255 |
+
$opt['sku'] = '';
|
256 |
+
$ovalues["sku"] = $sku;
|
257 |
+
$ovalues["sort_order"] = $sort_order;
|
258 |
+
$opt['values'][] = $ovalues;
|
259 |
+
}
|
260 |
+
}
|
261 |
+
return $opt;
|
262 |
+
}
|
263 |
+
|
264 |
+
public function processItemAfterId(&$item, $params = null)
|
265 |
+
{
|
266 |
+
$hasOptions = 0;
|
267 |
+
$requiredOptions = 0;
|
268 |
+
$custom_options = array();
|
269 |
+
$itemCopy = $item;
|
270 |
+
|
271 |
+
foreach ($itemCopy as $field => $value)
|
272 |
+
{
|
273 |
+
$fieldParts = explode(':', $field);
|
274 |
+
if (count($fieldParts) > 2)
|
275 |
+
{
|
276 |
+
if (strlen($value) > 0)
|
277 |
+
{
|
278 |
+
$custom_options[] = $this->BuildCustomOption($field, $value);
|
279 |
+
}
|
280 |
+
unset($item[$field]);
|
281 |
+
}
|
282 |
+
unset($fieldParts);
|
283 |
+
}
|
284 |
+
|
285 |
+
// create new custom options
|
286 |
+
if (count($custom_options) > 0)
|
287 |
+
{
|
288 |
+
$pid = $params['product_id'];
|
289 |
+
$tname = $this->tablename('catalog_product_entity');
|
290 |
+
foreach ($custom_options as $opt)
|
291 |
+
{
|
292 |
+
if ($opt["is_require"])
|
293 |
+
{
|
294 |
+
$requiredOptions = 1;
|
295 |
+
break;
|
296 |
+
}
|
297 |
+
}
|
298 |
+
$data = array(1,$requiredOptions,$pid);
|
299 |
+
// set product has having options
|
300 |
+
$sql = "UPDATE `$tname` SET has_options=?,required_options=? WHERE entity_id=?";
|
301 |
+
$this->update($sql, $data);
|
302 |
+
$t1 = $this->tablename('catalog_product_option');
|
303 |
+
// destroy existing options if first time we encounter item
|
304 |
+
if (!$params["same"])
|
305 |
+
{
|
306 |
+
$sql = "DELETE $t1 FROM $t1 WHERE $t1.product_id=$pid";
|
307 |
+
$this->delete($sql);
|
308 |
+
unset($this->_opttypeids);
|
309 |
+
unset($this->_optids);
|
310 |
+
$this->_opttypeids = array();
|
311 |
+
$this->_optids = array();
|
312 |
+
}
|
313 |
+
// check options container
|
314 |
+
$oc = isset($item['options_container']) ? $item['options_container'] : "container2";
|
315 |
+
if (!in_array($oc, array('container1','container2')))
|
316 |
+
{
|
317 |
+
$item['options_container'] = $this->_containerMap[$oc];
|
318 |
+
}
|
319 |
+
else
|
320 |
+
{
|
321 |
+
$item['options_container'] = $oc;
|
322 |
+
}
|
323 |
+
// fill custom options table
|
324 |
+
$sids = $this->getItemStoreIds($item, 0);
|
325 |
+
if (!$params["same"])
|
326 |
+
{
|
327 |
+
$sids = array_unique(array_merge(array(0), $sids));
|
328 |
+
}
|
329 |
+
|
330 |
+
foreach ($custom_options as $option)
|
331 |
+
{
|
332 |
+
$opt = $this->createOption($pid, $sids, $option);
|
333 |
+
$this->createOptionValues($option['__field'], $sids, $option["values"]);
|
334 |
+
}
|
335 |
+
}
|
336 |
+
unset($custom_options);
|
337 |
+
return true;
|
338 |
+
}
|
339 |
+
|
340 |
+
/*
|
341 |
+
* public function processItemException(&$item,$params=null) { }
|
342 |
+
*/
|
343 |
+
public function getPluginDescription()
|
344 |
+
{
|
345 |
+
return "This plugins enable to import custom options using specific column syntax";
|
346 |
+
}
|
347 |
+
|
348 |
+
public function initialize($params)
|
349 |
+
{
|
350 |
+
return true;
|
351 |
+
}
|
352 |
+
|
353 |
+
public function processColumnList(&$cols, $params = null)
|
354 |
+
{
|
355 |
+
// detect if we have at least one custom option
|
356 |
+
$hasopt = false;
|
357 |
+
foreach ($cols as $k)
|
358 |
+
{
|
359 |
+
$hasopt = count(explode(":", $k)) > 1;
|
360 |
+
if ($hasopt)
|
361 |
+
{
|
362 |
+
break;
|
363 |
+
}
|
364 |
+
}
|
365 |
+
// if we have at least one custom option, add options_container if not exist
|
366 |
+
if ($hasopt && !in_array('options_container', $cols))
|
367 |
+
{
|
368 |
+
$cols[] = 'options_container';
|
369 |
+
}
|
370 |
+
return true;
|
371 |
+
}
|
372 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/downloadable/downloadableprocessor.php
ADDED
@@ -0,0 +1,302 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class DownloadableProcessor extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $_filePath;
|
6 |
+
|
7 |
+
public function initialize($params)
|
8 |
+
{
|
9 |
+
$this->_filePath = $this->getMagentoDir() . DIRSEP . "media" . DIRSEP . "downloadable" . DIRSEP . "files" .
|
10 |
+
DIRSEP . "links" . DIRSEP;
|
11 |
+
}
|
12 |
+
|
13 |
+
public function getPluginInfo()
|
14 |
+
{
|
15 |
+
return array("name"=>"Downloadable products importer","author"=>"Tangkoko SARL","version"=>"1.0.0.1",
|
16 |
+
"url"=>"http://store.tangkoko.com/fr/extensions-magento/magmi-downloadable-products-importer-plugin.html");
|
17 |
+
}
|
18 |
+
|
19 |
+
public function processItemBeforeId(&$item, $params = null)
|
20 |
+
{
|
21 |
+
// if item is not configurable, nothing to do
|
22 |
+
if ($item["type"] !== "downloadable")
|
23 |
+
{
|
24 |
+
return true;
|
25 |
+
}
|
26 |
+
|
27 |
+
return true;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function processItemAfterId(&$item, $params = null)
|
31 |
+
{
|
32 |
+
// if item is not downloadable, nothing to do
|
33 |
+
if ($item["type"] !== "downloadable")
|
34 |
+
{
|
35 |
+
return true;
|
36 |
+
}
|
37 |
+
|
38 |
+
$filename = $item["sku"] . ".zip";
|
39 |
+
$sampleFilename = "sample_" . $item["sku"] . ".zip";
|
40 |
+
// donnes à importer dans les liens des produits téléchargeable
|
41 |
+
if (isset($item["links"]))
|
42 |
+
{
|
43 |
+
|
44 |
+
$this->log($item["links"], "debug");
|
45 |
+
$links = array();
|
46 |
+
$str_links = explode(";", $item["links"]);
|
47 |
+
foreach ($str_links as $str_link)
|
48 |
+
{
|
49 |
+
$arr_link = explode(",", $str_link);
|
50 |
+
$link = array();
|
51 |
+
foreach ($arr_link as $str_link)
|
52 |
+
{
|
53 |
+
$val = preg_split('/[\s:]+[\s]*/', $str_link, 2);
|
54 |
+
$link[$val[0]] = $val[1];
|
55 |
+
}
|
56 |
+
$links[] = $link;
|
57 |
+
}
|
58 |
+
|
59 |
+
$pid = $params["product_id"];
|
60 |
+
|
61 |
+
$existingLinks = $this->getExistingLinks($pid);
|
62 |
+
$nbupdate = count($existingLinks);
|
63 |
+
$nbdiff = count($links) - count($existingLinks);
|
64 |
+
$updateLinks = array();
|
65 |
+
try
|
66 |
+
{
|
67 |
+
if ($nbdiff > 0) // update existing links and add new links (more in xml file than database)
|
68 |
+
{
|
69 |
+
$addLinks = array();
|
70 |
+
|
71 |
+
for ($j = $nbupdate; $j < count($links); $j++)
|
72 |
+
{
|
73 |
+
$addLinks[] = $links[$j];
|
74 |
+
}
|
75 |
+
|
76 |
+
// ajoute les nouveaux liens
|
77 |
+
$i = 0;
|
78 |
+
|
79 |
+
foreach ($addLinks as $addLink)
|
80 |
+
{
|
81 |
+
|
82 |
+
if ($addLink["file"] = $this->copyFile($addLink))
|
83 |
+
{
|
84 |
+
$addLink["link_id"] = $this->addLink($addLink, $pid);
|
85 |
+
$addLink["price_id"] = $this->addLinkPrice($addLink);
|
86 |
+
$addLink["title_id"] = $this->addLinkTitle($addLink);
|
87 |
+
if ($addLink["sample"])
|
88 |
+
{
|
89 |
+
$addLink["sample"] = $this->copyFile($addLink);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
$i++;
|
93 |
+
}
|
94 |
+
}
|
95 |
+
elseif ($nbdiff < 0)
|
96 |
+
{ // update existing and delete links (more in database than xml file)
|
97 |
+
$nbdiff = $nbdiff * -1; // number to delete
|
98 |
+
$nbupdate = count($existingLinks) - $nbdiff; // nb links to update = number of existing links - difference
|
99 |
+
$i = 0;
|
100 |
+
$deleteLinks = array();
|
101 |
+
if (count($existingLinks))
|
102 |
+
{
|
103 |
+
|
104 |
+
$i = 0;
|
105 |
+
|
106 |
+
$reverse = array_reverse($existingLinks);
|
107 |
+
foreach ($reverse as $deletelink)
|
108 |
+
{
|
109 |
+
if ($i >= $nbdiff)
|
110 |
+
break;
|
111 |
+
$deleteLinks[] = $deletelink["link_id"];
|
112 |
+
$i++;
|
113 |
+
}
|
114 |
+
$this->deleteLinks($deleteLinks);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
if (count($existingLinks))
|
119 |
+
{
|
120 |
+
$i = 0;
|
121 |
+
foreach ($existingLinks as $updatelink)
|
122 |
+
{
|
123 |
+
if ($i >= $nbupdate)
|
124 |
+
break;
|
125 |
+
$links[$i]["link_id"] = $updatelink["link_id"];
|
126 |
+
$updateLinks[] = $links[$i];
|
127 |
+
$i++;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
if (count($updateLinks))
|
132 |
+
{
|
133 |
+
foreach ($updateLinks as $updateLink)
|
134 |
+
{
|
135 |
+
if ($updateLink["file"] = $this->copyFile($updateLink, $filename))
|
136 |
+
$this->updateLink($updateLink);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
}
|
140 |
+
catch (Exception $e)
|
141 |
+
{
|
142 |
+
die($e->getMessage());
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
public function copyFile($link)
|
148 |
+
{
|
149 |
+
if (preg_match("|.*?://.*|", $link["file"]))
|
150 |
+
{
|
151 |
+
$filename = $this->getFilename($link["file"]);
|
152 |
+
}
|
153 |
+
else
|
154 |
+
{
|
155 |
+
$filename = basename($link["file"]);
|
156 |
+
}
|
157 |
+
|
158 |
+
if ($filename)
|
159 |
+
{
|
160 |
+
$destdir = $this->_filePath . $filename[0] . DIRSEP . $filename[1] . DIRSEP;
|
161 |
+
$cpfilename = $destdir . $filename;
|
162 |
+
|
163 |
+
@mkdir($this->_filePath . $filename[0], 0777);
|
164 |
+
@mkdir($destdir, 0777);
|
165 |
+
|
166 |
+
if (preg_match("|.*?://.*|", $link["file"]))
|
167 |
+
{
|
168 |
+
if (is_file($cpfilename))
|
169 |
+
unlink($cpfilename);
|
170 |
+
$this->download($link["file"], $cpfilename);
|
171 |
+
}
|
172 |
+
else
|
173 |
+
{
|
174 |
+
|
175 |
+
if (!@copy($link["file"], $cpfilename))
|
176 |
+
{
|
177 |
+
unlink($cpfilename);
|
178 |
+
@copy($link["file"], $cpfilename);
|
179 |
+
}
|
180 |
+
}
|
181 |
+
}
|
182 |
+
else
|
183 |
+
{
|
184 |
+
$this->log("Le fichier n' pas été trouvé à l'emplacement " . $link["file"], "warning");
|
185 |
+
return false;
|
186 |
+
}
|
187 |
+
return substr($cpfilename, strlen($this->_filePath) - 1);
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* download files and return hash key content
|
192 |
+
*/
|
193 |
+
public function download($url, $tmp_path)
|
194 |
+
{
|
195 |
+
$this->log("Téléchargement " . $url, "warning");
|
196 |
+
$ch = curl_init($url);
|
197 |
+
$fp = fopen($tmp_path, "w+");
|
198 |
+
curl_setopt($ch, CURLOPT_FILE, $fp);
|
199 |
+
curl_setopt($ch, CURLOPT_HEADER, 0);
|
200 |
+
$this->log("BEGIN Download " . $url, "warning");
|
201 |
+
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
202 |
+
|
203 |
+
if ($httpCode == 404)
|
204 |
+
{
|
205 |
+
throw new Exception("File " . $url . " not found !");
|
206 |
+
}
|
207 |
+
curl_exec($ch);
|
208 |
+
curl_close($ch);
|
209 |
+
$this->log("End Download " . $url, "warning");
|
210 |
+
fclose($fp);
|
211 |
+
}
|
212 |
+
|
213 |
+
private function getFilename($url)
|
214 |
+
{
|
215 |
+
$ch = curl_init();
|
216 |
+
curl_setopt($ch, CURLOPT_URL, $url);
|
217 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
218 |
+
curl_setopt($ch, CURLOPT_HEADER, 1);
|
219 |
+
curl_setopt($ch, CURLOPT_NOBODY, true);
|
220 |
+
$header = curl_exec($ch);
|
221 |
+
curl_close($ch);
|
222 |
+
|
223 |
+
return $this->extractCustomHeader('Content-Disposition: attachment; filename=', '\n', $header);
|
224 |
+
}
|
225 |
+
|
226 |
+
private function extractCustomHeader($start, $end, $header)
|
227 |
+
{
|
228 |
+
$pattern = '/' . $start . '(.*?)' . $end . '/';
|
229 |
+
if (preg_match($pattern, $header, $result))
|
230 |
+
{
|
231 |
+
return $result[1];
|
232 |
+
}
|
233 |
+
else
|
234 |
+
{
|
235 |
+
return false;
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* retrieve existing product links
|
241 |
+
*/
|
242 |
+
public function getExistingLinks($pid)
|
243 |
+
{
|
244 |
+
$dl = $this->tablename('downloadable_link');
|
245 |
+
$sql = "select * from downloadable_link where product_id = ?";
|
246 |
+
$links = $this->selectAll($sql, array($pid));
|
247 |
+
return $links;
|
248 |
+
}
|
249 |
+
|
250 |
+
public function deleteLinks($lids)
|
251 |
+
{
|
252 |
+
$dl = $this->tablename('downloadable_link');
|
253 |
+
$sql = "DELETE FROM $dl WHERE link_id in(" . implode(",", $lids) . ")";
|
254 |
+
$this->delete($sql);
|
255 |
+
}
|
256 |
+
|
257 |
+
public function updateLink($link)
|
258 |
+
{
|
259 |
+
$dl = $this->tablename('downloadable_link');
|
260 |
+
$dlt = $this->tablename('downloadable_link_title');
|
261 |
+
|
262 |
+
$sql = "UPDATE $dl as dl
|
263 |
+
JOIN $dlt as dlt ON dl.link_id=dlt.link_id AND dlt.store_id=0
|
264 |
+
SET link_file = ?,
|
265 |
+
title = ?
|
266 |
+
WHERE dl.link_id = ?";
|
267 |
+
|
268 |
+
$this->update($sql, array($link["file"],$link["title"],$link["link_id"]));
|
269 |
+
}
|
270 |
+
|
271 |
+
public function addLink($link, $pid)
|
272 |
+
{
|
273 |
+
if ($link["is_shareable"] == "config")
|
274 |
+
{
|
275 |
+
$link["is_shareable"] = 2;
|
276 |
+
}
|
277 |
+
$dl = $this->tablename('downloadable_link');
|
278 |
+
$sql = "INSERT INTO $dl(product_id,sort_order, number_of_downloads,is_shareable, link_file,link_type) VALUES (?,?,?,?,?,?)";
|
279 |
+
// insert links
|
280 |
+
$data = array($pid,$link["sort_order"],$link["number_of_downloads"],$link["is_shareable"],$link["file"],"file");
|
281 |
+
// insert in db
|
282 |
+
return $this->insert($sql, $data);
|
283 |
+
}
|
284 |
+
|
285 |
+
public function addLinkPrice($link)
|
286 |
+
{
|
287 |
+
$dlp = $this->tablename('downloadable_link_price');
|
288 |
+
$sql = "INSERT INTO $dlp(link_id,website_id,price) VALUES (?,?,?)";
|
289 |
+
// insert links prices
|
290 |
+
$data = array($link["link_id"],0,0);
|
291 |
+
return $this->insert($sql, $data);
|
292 |
+
}
|
293 |
+
|
294 |
+
public function addLinkTitle($link)
|
295 |
+
{
|
296 |
+
$dlt = $this->tablename('downloadable_link_title');
|
297 |
+
$sql = "INSERT INTO $dlt(link_id,store_id,title) VALUES (?,?,?)";
|
298 |
+
// insert links titles
|
299 |
+
$data = array($link["link_id"],0,$link["title"]);
|
300 |
+
return $this->insert($sql, $data);
|
301 |
+
}
|
302 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/downloadable/options_panel.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin import downloadable products
|
3 |
+
<p>
|
4 |
+
A column name
|
5 |
+
<code>"links"</code>
|
6 |
+
must contain links attribute.
|
7 |
+
</p>
|
8 |
+
</div>
|
9 |
+
|
10 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/imageprocessor/imageitattributeemprocessor.php
ADDED
@@ -0,0 +1,654 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ImageAttributeItemProcessor extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $forcename = null;
|
6 |
+
protected $magdir = null;
|
7 |
+
protected $imgsourcedirs = array();
|
8 |
+
protected $errattrs = array();
|
9 |
+
protected $_errorimgs = array();
|
10 |
+
protected $_lastimage = "";
|
11 |
+
protected $_handled_attributes = array();
|
12 |
+
protected $_img_baseattrs = array("image","small_image","thumbnail");
|
13 |
+
protected $_active = false;
|
14 |
+
protected $_newitem;
|
15 |
+
protected $_mdh;
|
16 |
+
protected $_remoteroot = "";
|
17 |
+
protected $debug;
|
18 |
+
|
19 |
+
public function initialize($params)
|
20 |
+
{
|
21 |
+
// declare current class as attribute handler
|
22 |
+
$this->registerAttributeHandler($this, array("frontend_input:(media_image|gallery)"));
|
23 |
+
$this->magdir = Magmi_Config::getInstance()->getMagentoDir();
|
24 |
+
$this->_mdh = MagentoDirHandlerFactory::getInstance()->getHandler($this->magdir);
|
25 |
+
$this->_mdh->setRemoteGetterId("image");
|
26 |
+
// remote root
|
27 |
+
if ($this->getParam("IMG:remoteroot", ""))
|
28 |
+
{
|
29 |
+
if ($this->getParam("IMG:remoteauth", false) == true)
|
30 |
+
{
|
31 |
+
$this->_mdh->setRemoteCredentials($this->getParam("IMG:remoteuser"), $this->getParam("IMG:remotepass"));
|
32 |
+
}
|
33 |
+
$this->_remoteroot = $this->getParam("IMG:remoteroot");
|
34 |
+
}
|
35 |
+
$this->forcename = $this->getParam("IMG:renaming");
|
36 |
+
foreach ($params as $k => $v)
|
37 |
+
{
|
38 |
+
if (preg_match_all("/^IMG_ERR:(.*)$/", $k, $m))
|
39 |
+
{
|
40 |
+
$this->errattrs[$m[1][0]] = $params[$k];
|
41 |
+
}
|
42 |
+
}
|
43 |
+
$this->debug = $this->getParam("IMG:debug", 0);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function getPluginInfo()
|
47 |
+
{
|
48 |
+
return array("name"=>"Image attributes processor","author"=>"Dweeves","version"=>"1.0.29",
|
49 |
+
"url"=>$this->pluginDocUrl("Image_attributes_processor"));
|
50 |
+
}
|
51 |
+
|
52 |
+
public function isErrorImage($img)
|
53 |
+
{
|
54 |
+
return isset($this->_errorimgs[$img]);
|
55 |
+
}
|
56 |
+
|
57 |
+
public function cachesort($v1, $v2)
|
58 |
+
{
|
59 |
+
return $v2 - $v1;
|
60 |
+
}
|
61 |
+
|
62 |
+
public function setErrorImg($img)
|
63 |
+
{
|
64 |
+
$mxerrcache = $this->getParam("IMG:maxerrorcache", 100);
|
65 |
+
// remove limit => 10%
|
66 |
+
$removelimit = intval($mxerrcache / 10);
|
67 |
+
if (count($this->_errorimgs) > $mxerrcache)
|
68 |
+
{
|
69 |
+
uasort($this->prepared, array($this,"cachesort"));
|
70 |
+
array_splice($this->_errorimgs, $removelimit, count($this->_errorimgs));
|
71 |
+
}
|
72 |
+
$this->_errorimgs[$img] = microtime(true);
|
73 |
+
}
|
74 |
+
|
75 |
+
// Image removal feature
|
76 |
+
public function handleRemoveImages($pid, &$item, $ivalue)
|
77 |
+
{
|
78 |
+
$gal_attinfo = $this->getAttrInfo("media_gallery");
|
79 |
+
$t = $this->tablename('catalog_product_entity_media_gallery');
|
80 |
+
$tv = $this->tablename('catalog_product_entity_media_gallery_value');
|
81 |
+
$rimgs = explode(";", $ivalue);
|
82 |
+
$rivals = array();
|
83 |
+
foreach ($rimgs as $rimg)
|
84 |
+
{
|
85 |
+
$rivals[] = '/' . implode('/', array($rimg[0],$rimg[1],$rimg));
|
86 |
+
}
|
87 |
+
|
88 |
+
$sql = "DELETE $t.* FROM $t
|
89 |
+
WHERE $t.entity_id=? AND $t.attribute_id=? AND $t.value IN (" . $this->arr2values($rivals) . ")";
|
90 |
+
$this->delete($sql, array_merge(array($pid,$gal_attinfo["attribute_id"]), $rivals));
|
91 |
+
}
|
92 |
+
|
93 |
+
public function handleGalleryTypeAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
94 |
+
{
|
95 |
+
// do nothing if empty
|
96 |
+
if ($ivalue == "")
|
97 |
+
{
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
// use ";" as image separator
|
101 |
+
$images = explode(";", $ivalue);
|
102 |
+
$imageindex = 0;
|
103 |
+
// for each image
|
104 |
+
foreach ($images as $imagefile)
|
105 |
+
{
|
106 |
+
// trim image file in case of spaced split
|
107 |
+
$imagefile = trim($imagefile);
|
108 |
+
// handle exclude flag explicitely
|
109 |
+
$exclude = $this->getExclude($imagefile, false);
|
110 |
+
$infolist = explode("::", $imagefile);
|
111 |
+
$label = null;
|
112 |
+
if (count($infolist) > 1)
|
113 |
+
{
|
114 |
+
$label = $infolist[1];
|
115 |
+
$imagefile = $infolist[0];
|
116 |
+
}
|
117 |
+
unset($infolist);
|
118 |
+
// copy it from source dir to product media dir
|
119 |
+
$imagefile = $this->copyImageFile($imagefile, $item,
|
120 |
+
array("store"=>$storeid,"attr_code"=>$attrcode,"imageindex"=>$imageindex == 0 ? "" : $imageindex));
|
121 |
+
if ($imagefile !== false)
|
122 |
+
{
|
123 |
+
// add to gallery
|
124 |
+
$targetsids = $this->getStoreIdsForStoreScope($item["store"]);
|
125 |
+
$vid = $this->addImageToGallery($pid, $storeid, $attrdesc, $imagefile, $targetsids, $label, $exclude);
|
126 |
+
}
|
127 |
+
$imageindex++;
|
128 |
+
}
|
129 |
+
unset($images);
|
130 |
+
// we don't want to insert after that
|
131 |
+
$ovalue = false;
|
132 |
+
return $ovalue;
|
133 |
+
}
|
134 |
+
|
135 |
+
public function removeImageFromGallery($pid, $storeid, $attrdesc)
|
136 |
+
{
|
137 |
+
$t = $this->tablename('catalog_product_entity_media_gallery');
|
138 |
+
$tv = $this->tablename('catalog_product_entity_media_gallery_value');
|
139 |
+
|
140 |
+
$sql = "DELETE $tv.* FROM $tv
|
141 |
+
JOIN $t ON $t.value_id=$tv.value_id AND $t.entity_id=? AND $t.attribute_id=?
|
142 |
+
WHERE $tv.store_id=?";
|
143 |
+
$this->delete($sql, array($pid,$attrdesc["attribute_id"],$storeid));
|
144 |
+
}
|
145 |
+
|
146 |
+
public function getExclude(&$val, $default = true)
|
147 |
+
{
|
148 |
+
$exclude = $default;
|
149 |
+
if ($val[0] == "+" || $val[0] == "-")
|
150 |
+
{
|
151 |
+
$exclude = $val[0] == "-";
|
152 |
+
$val = substr($val, 1);
|
153 |
+
}
|
154 |
+
return $exclude;
|
155 |
+
}
|
156 |
+
|
157 |
+
public function findImageFile($ivalue)
|
158 |
+
{
|
159 |
+
// do no try to find remote image
|
160 |
+
if (is_remote_path($ivalue))
|
161 |
+
{
|
162 |
+
return $ivalue;
|
163 |
+
}
|
164 |
+
// if existing, return it directly
|
165 |
+
if (realpath($ivalue))
|
166 |
+
{
|
167 |
+
return $ivalue;
|
168 |
+
}
|
169 |
+
|
170 |
+
// ok , so it's a relative path
|
171 |
+
$imgfile = false;
|
172 |
+
$scandirs = explode(";", $this->getParam("IMG:sourcedir"));
|
173 |
+
$cscandirs = count($scandirs);
|
174 |
+
// iterate on image sourcedirs, trying to resolve file name based on input value and current source dir
|
175 |
+
for ($i = 0; $i < $cscandirs && $imgfile === false; $i++)
|
176 |
+
{
|
177 |
+
$sd = $scandirs[$i];
|
178 |
+
// scandir is relative, use mdh
|
179 |
+
if ($sd[0] != "/")
|
180 |
+
{
|
181 |
+
$sd = $this->_mdh->getMagentoDir() . "/" . $sd;
|
182 |
+
}
|
183 |
+
$imgfile = abspath($ivalue, $sd, true);
|
184 |
+
}
|
185 |
+
return $imgfile;
|
186 |
+
}
|
187 |
+
|
188 |
+
public function handleImageTypeAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
189 |
+
{
|
190 |
+
// remove attribute value if empty
|
191 |
+
if ($ivalue == "" || $ivalue == "__NULL__")
|
192 |
+
{
|
193 |
+
$this->removeImageFromGallery($pid, $storeid, $attrdesc);
|
194 |
+
return "__MAGMI_DELETE__";
|
195 |
+
}
|
196 |
+
|
197 |
+
// add support for explicit exclude
|
198 |
+
$exclude = $this->getExclude($ivalue, true);
|
199 |
+
$imagefile = trim($ivalue);
|
200 |
+
|
201 |
+
// else copy image file
|
202 |
+
$imagefile = $this->copyImageFile($imagefile, $item, array("store"=>$storeid,"attr_code"=>$attrcode));
|
203 |
+
$ovalue = $imagefile;
|
204 |
+
// add to gallery as excluded
|
205 |
+
if ($imagefile !== false)
|
206 |
+
{
|
207 |
+
$label = null;
|
208 |
+
if (isset($item[$attrcode . "_label"]))
|
209 |
+
{
|
210 |
+
$label = $item[$attrcode . "_label"];
|
211 |
+
}
|
212 |
+
$targetsids = $this->getStoreIdsForStoreScope($item["store"]);
|
213 |
+
$vid = $this->addImageToGallery($pid, $storeid, $attrdesc, $imagefile, $targetsids, $label, $exclude,
|
214 |
+
$attrdesc["attribute_id"]);
|
215 |
+
}
|
216 |
+
return $ovalue;
|
217 |
+
}
|
218 |
+
|
219 |
+
public function handleVarcharAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
220 |
+
{
|
221 |
+
if (trim($ivalue) == "")
|
222 |
+
{
|
223 |
+
return trim($ivalue);
|
224 |
+
}
|
225 |
+
// trimming
|
226 |
+
$ivalue = trim($ivalue);
|
227 |
+
// If not already a remote image & force remote root, set it & set authentication
|
228 |
+
if (!is_remote_path($ivalue))
|
229 |
+
{
|
230 |
+
if ($this->_remoteroot != "")
|
231 |
+
{
|
232 |
+
$ivalue = $this->_remoteroot . str_replace("//", "/", "/$ivalue");
|
233 |
+
}
|
234 |
+
}
|
235 |
+
if (is_remote_path($ivalue))
|
236 |
+
{
|
237 |
+
// Amazon images patch , remove SLXXXX part
|
238 |
+
if (strpos($ivalue, 'amazon.com/images/I') !== false)
|
239 |
+
{
|
240 |
+
$pattern = '/\bSL[0-9]+\./i';
|
241 |
+
$ivalue = preg_replace($pattern, '', $ivalue);
|
242 |
+
}
|
243 |
+
}
|
244 |
+
|
245 |
+
// if it's a gallery
|
246 |
+
switch ($attrdesc["frontend_input"])
|
247 |
+
{
|
248 |
+
case "gallery":
|
249 |
+
|
250 |
+
$ovalue = $this->handleGalleryTypeAttribute($pid, $item, $storeid, $attrcode, $attrdesc, $ivalue);
|
251 |
+
break;
|
252 |
+
case "media_image":
|
253 |
+
$ovalue = $this->handleImageTypeAttribute($pid, $item, $storeid, $attrcode, $attrdesc, $ivalue);
|
254 |
+
break;
|
255 |
+
default:
|
256 |
+
$ovalue = "__MAGMI_UNHANDLED__";
|
257 |
+
}
|
258 |
+
return $ovalue;
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* imageInGallery
|
263 |
+
*
|
264 |
+
* @param int $pid
|
265 |
+
* : product id to test image existence in gallery
|
266 |
+
* @param string $imgname
|
267 |
+
* : image file name (relative to /products/media in magento dir)
|
268 |
+
* @return bool : if image is already present in gallery for a given product id
|
269 |
+
*/
|
270 |
+
public function getImageId($pid, $attid, $imgname, $refid = null)
|
271 |
+
{
|
272 |
+
$t = $this->tablename('catalog_product_entity_media_gallery');
|
273 |
+
|
274 |
+
$sql = "SELECT $t.value_id FROM $t ";
|
275 |
+
if ($refid != null)
|
276 |
+
{
|
277 |
+
$vc = $this->tablename('catalog_product_entity_varchar');
|
278 |
+
$sql .= " JOIN $vc ON $t.entity_id=$vc.entity_id AND $t.value=$vc.value AND $vc.attribute_id=?
|
279 |
+
WHERE $t.entity_id=?";
|
280 |
+
$imgid = $this->selectone($sql, array($refid,$pid), 'value_id');
|
281 |
+
}
|
282 |
+
else
|
283 |
+
{
|
284 |
+
$sql .= " WHERE value=? AND entity_id=? AND attribute_id=?";
|
285 |
+
$imgid = $this->selectone($sql, array($imgname,$pid,$attid), 'value_id');
|
286 |
+
}
|
287 |
+
|
288 |
+
if ($imgid == null)
|
289 |
+
{
|
290 |
+
// insert image in media_gallery
|
291 |
+
$sql = "INSERT INTO $t
|
292 |
+
(attribute_id,entity_id,value)
|
293 |
+
VALUES
|
294 |
+
(?,?,?)";
|
295 |
+
|
296 |
+
$imgid = $this->insert($sql, array($attid,$pid,$imgname));
|
297 |
+
}
|
298 |
+
else
|
299 |
+
{
|
300 |
+
$sql = "UPDATE $t
|
301 |
+
SET value=?
|
302 |
+
WHERE value_id=?";
|
303 |
+
$this->update($sql, array($imgname,$imgid));
|
304 |
+
}
|
305 |
+
return $imgid;
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* reset product gallery
|
310 |
+
*
|
311 |
+
* @param int $pid
|
312 |
+
* : product id
|
313 |
+
*/
|
314 |
+
public function resetGallery($pid, $storeid, $attid)
|
315 |
+
{
|
316 |
+
$tgv = $this->tablename('catalog_product_entity_media_gallery_value');
|
317 |
+
$tg = $this->tablename('catalog_product_entity_media_gallery');
|
318 |
+
$sql = "DELETE emgv,emg FROM `$tgv` as emgv
|
319 |
+
JOIN `$tg` AS emg ON emgv.value_id = emg.value_id AND emgv.store_id=?
|
320 |
+
WHERE emg.entity_id=? AND emg.attribute_id=?";
|
321 |
+
$this->delete($sql, array($storeid,$pid,$attid));
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* adds an image to product image gallery only if not already exists
|
326 |
+
*
|
327 |
+
* @param int $pid
|
328 |
+
* : product id to test image existence in gallery
|
329 |
+
* @param array $attrdesc
|
330 |
+
* : product attribute description
|
331 |
+
* @param string $imgname
|
332 |
+
* : image file name (relative to /products/media in magento dir)
|
333 |
+
*/
|
334 |
+
public function addImageToGallery($pid, $storeid, $attrdesc, $imgname, $targetsids, $imglabel = null, $excluded = false,
|
335 |
+
$refid = null)
|
336 |
+
{
|
337 |
+
$gal_attinfo = $this->getAttrInfo("media_gallery");
|
338 |
+
$tg = $this->tablename('catalog_product_entity_media_gallery');
|
339 |
+
$tgv = $this->tablename('catalog_product_entity_media_gallery_value');
|
340 |
+
$vid = $this->getImageId($pid, $gal_attinfo["attribute_id"], $imgname, $refid);
|
341 |
+
if ($vid != null)
|
342 |
+
{
|
343 |
+
|
344 |
+
// et maximum current position in the product gallery
|
345 |
+
$sql = "SELECT MAX( position ) as maxpos
|
346 |
+
FROM $tgv AS emgv
|
347 |
+
JOIN $tg AS emg ON emg.value_id = emgv.value_id AND emg.entity_id = ?
|
348 |
+
WHERE emgv.store_id=?
|
349 |
+
GROUP BY emg.entity_id";
|
350 |
+
$pos = $this->selectone($sql, array($pid,$storeid), 'maxpos');
|
351 |
+
$pos = ($pos == null ? 0 : $pos + 1);
|
352 |
+
// nsert new value (ingnore duplicates)
|
353 |
+
|
354 |
+
$vinserts = array();
|
355 |
+
$data = array();
|
356 |
+
|
357 |
+
foreach ($targetsids as $tsid)
|
358 |
+
{
|
359 |
+
$vinserts[] = "(?,?,?,?," . ($imglabel == null ? "NULL" : "?") . ")";
|
360 |
+
$data = array_merge($data, array($vid,$tsid,$pos,$excluded ? 1 : 0));
|
361 |
+
if ($imglabel != null)
|
362 |
+
{
|
363 |
+
$data[] = $imglabel;
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
if (count($data) > 0)
|
368 |
+
{
|
369 |
+
$sql = "INSERT INTO $tgv
|
370 |
+
(value_id,store_id,position,disabled,label)
|
371 |
+
VALUES " . implode(",", $vinserts) . "
|
372 |
+
ON DUPLICATE KEY UPDATE label=VALUES(`label`),disabled=VALUES(`disabled`)";
|
373 |
+
$this->insert($sql, $data);
|
374 |
+
}
|
375 |
+
unset($vinserts);
|
376 |
+
unset($data);
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
public function parsename($info, $item, $extra)
|
381 |
+
{
|
382 |
+
$info = $this->parseCalculatedValue($info, $item, $extra);
|
383 |
+
return $info;
|
384 |
+
}
|
385 |
+
|
386 |
+
public function getPluginParams($params)
|
387 |
+
{
|
388 |
+
$pp = array();
|
389 |
+
foreach ($params as $k => $v)
|
390 |
+
{
|
391 |
+
if (preg_match("/^IMG(_ERR)?:.*$/", $k))
|
392 |
+
{
|
393 |
+
$pp[$k] = $v;
|
394 |
+
}
|
395 |
+
}
|
396 |
+
return $pp;
|
397 |
+
}
|
398 |
+
|
399 |
+
public function fillErrorAttributes(&$item)
|
400 |
+
{
|
401 |
+
foreach ($this->errattrs as $k => $v)
|
402 |
+
{
|
403 |
+
$this->addExtraAttribute($k);
|
404 |
+
$item[$k] = $v;
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
public function getImagenameComponents($fname, $formula, $extra)
|
409 |
+
{
|
410 |
+
$matches = array();
|
411 |
+
$xname = $fname;
|
412 |
+
if (preg_match("|re::(.*)::(.*)|", $formula, $matches))
|
413 |
+
{
|
414 |
+
$rep = $matches[2];
|
415 |
+
$xname = preg_replace("|" . $matches[1] . "|", $rep, $xname);
|
416 |
+
$extra['parsed'] = true;
|
417 |
+
}
|
418 |
+
$xname = basename($xname);
|
419 |
+
$m = preg_match("/(.*)\.(jpg|png|gif)$/i", $xname, $matches);
|
420 |
+
if ($m)
|
421 |
+
{
|
422 |
+
$extra["imagename"] = $xname;
|
423 |
+
$extra["imagename.ext"] = $matches[2];
|
424 |
+
$extra["imagename.noext"] = $matches[1];
|
425 |
+
}
|
426 |
+
else
|
427 |
+
{
|
428 |
+
$uid = uniqid("img", true);
|
429 |
+
$extra = array_merge($extra, array("imagename"=>"$uid.jpg","imagename.ext"=>"jpg","imagename.noext"=>$uid));
|
430 |
+
}
|
431 |
+
|
432 |
+
return $extra;
|
433 |
+
}
|
434 |
+
|
435 |
+
public function getTargetName($fname, $item, $extra)
|
436 |
+
{
|
437 |
+
$cname = basename($fname);
|
438 |
+
if (isset($this->forcename) && $this->forcename != "")
|
439 |
+
{
|
440 |
+
$extra = $this->getImagenameComponents($fname, $this->forcename, $extra);
|
441 |
+
$pname = ($extra['parsed'] ? $extra['imagename'] : $this->forcename);
|
442 |
+
$cname = $this->parsename($pname, $item, $extra);
|
443 |
+
}
|
444 |
+
$cname = strtolower(preg_replace("/%[0-9][0-9|A-F]/", "_", rawurlencode($cname)));
|
445 |
+
|
446 |
+
return $cname;
|
447 |
+
}
|
448 |
+
|
449 |
+
public function saveImage($imgfile, $target)
|
450 |
+
{
|
451 |
+
$result = $this->_mdh->copy($imgfile, $target);
|
452 |
+
return $result;
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* copy image file from source directory to
|
457 |
+
* product media directory
|
458 |
+
*
|
459 |
+
* @param $imgfile :
|
460 |
+
* name of image file name in source directory
|
461 |
+
* @return : name of image file name relative to magento catalog media dir,including leading
|
462 |
+
* directories made of first char & second char of image file name.
|
463 |
+
*/
|
464 |
+
public function copyImageFile($imgfile, &$item, $extra)
|
465 |
+
{
|
466 |
+
if ($imgfile == "__NULL__" || $imgfile == null)
|
467 |
+
{
|
468 |
+
return false;
|
469 |
+
}
|
470 |
+
|
471 |
+
// check for source image in error
|
472 |
+
if ($this->isErrorImage($imgfile))
|
473 |
+
{
|
474 |
+
if ($this->_newitem)
|
475 |
+
{
|
476 |
+
$this->fillErrorAttributes($item);
|
477 |
+
}
|
478 |
+
;
|
479 |
+
return false;
|
480 |
+
}
|
481 |
+
|
482 |
+
$source = $this->findImageFile($imgfile);
|
483 |
+
if ($source == false)
|
484 |
+
{
|
485 |
+
$this->log("$imgfile cannot be found in images path", "warning");
|
486 |
+
// last image in error,add it to error cache
|
487 |
+
$this->setErrorImg($imgfile);
|
488 |
+
return false;
|
489 |
+
}
|
490 |
+
$imgfile = $source;
|
491 |
+
$checkexist = ($this->getParam("IMG:existingonly") == "yes");
|
492 |
+
$curlh = false;
|
493 |
+
$bimgfile = $this->getTargetName($imgfile, $item, $extra);
|
494 |
+
// source file exists
|
495 |
+
$i1 = $bimgfile[0];
|
496 |
+
$i2 = $bimgfile[1];
|
497 |
+
// magento image value (relative to media catalog)
|
498 |
+
$impath = "/$i1/$i2/$bimgfile";
|
499 |
+
// target directory;
|
500 |
+
$l2d = "media/catalog/product/$i1/$i2";
|
501 |
+
// test for existence
|
502 |
+
$targetpath = "$l2d/$bimgfile";
|
503 |
+
/* test for same image (without problem) */
|
504 |
+
if ($impath == $this->_lastimage)
|
505 |
+
{
|
506 |
+
return $impath;
|
507 |
+
}
|
508 |
+
/* test if imagefile comes from export */
|
509 |
+
if (!$this->_mdh->file_exists($targetpath) || $this->getParam("IMG:writemode") == "override")
|
510 |
+
{
|
511 |
+
// if we already had problems with this target,assume we'll get others.
|
512 |
+
if ($this->isErrorImage($impath))
|
513 |
+
{
|
514 |
+
return false;
|
515 |
+
}
|
516 |
+
|
517 |
+
/* try to recursively create target dir */
|
518 |
+
if (!$this->_mdh->file_exists($l2d))
|
519 |
+
{
|
520 |
+
|
521 |
+
$tst = $this->_mdh->mkdir($l2d, Magmi_Config::getInstance()->getDirMask(), true);
|
522 |
+
if (!$tst)
|
523 |
+
{
|
524 |
+
// if we had problem creating target directory,add target to error cache
|
525 |
+
$errors = $this->_mdh->getLastError();
|
526 |
+
$this->log("error creating $l2d: {$errors["type"]},{$errors["message"]}", "warning");
|
527 |
+
unset($errors);
|
528 |
+
$this->setErrorImg($impath);
|
529 |
+
return false;
|
530 |
+
}
|
531 |
+
}
|
532 |
+
|
533 |
+
if (!$this->saveImage($imgfile, $targetpath))
|
534 |
+
{
|
535 |
+
$errors = $this->_mdh->getLastError();
|
536 |
+
$this->fillErrorAttributes($item);
|
537 |
+
$this->log("error copying $l2d/$bimgfile : {$errors["type"]},{$errors["message"]}", "warning");
|
538 |
+
unset($errors);
|
539 |
+
$this->setErrorImg($impath);
|
540 |
+
return false;
|
541 |
+
}
|
542 |
+
else
|
543 |
+
{
|
544 |
+
@$this->_mdh->chmod("$l2d/$bimgfile", Magmi_Config::getInstance()->getFileMask());
|
545 |
+
}
|
546 |
+
}
|
547 |
+
$this->_lastimage = $impath;
|
548 |
+
/* return image file name relative to media dir (with leading / ) */
|
549 |
+
return $impath;
|
550 |
+
}
|
551 |
+
|
552 |
+
public function updateLabel($attrdesc, $pid, $sids, $label)
|
553 |
+
{
|
554 |
+
$tg = $this->tablename('catalog_product_entity_media_gallery');
|
555 |
+
$tgv = $this->tablename('catalog_product_entity_media_gallery_value');
|
556 |
+
$vc = $this->tablename('catalog_product_entity_varchar');
|
557 |
+
$sql = "UPDATE $tgv as emgv
|
558 |
+
JOIN $tg as emg ON emg.value_id=emgv.value_id AND emg.entity_id=?
|
559 |
+
JOIN $vc as ev ON ev.entity_id=emg.entity_id AND ev.value=emg.value and ev.attribute_id=?
|
560 |
+
SET label=?
|
561 |
+
WHERE emgv.store_id IN (" . implode(",", $sids) . ")";
|
562 |
+
$this->update($sql, array($pid,$attrdesc["attribute_id"],$label));
|
563 |
+
}
|
564 |
+
|
565 |
+
public function processItemAfterId(&$item, $params = null)
|
566 |
+
{
|
567 |
+
if (!$this->_active)
|
568 |
+
{
|
569 |
+
return true;
|
570 |
+
}
|
571 |
+
$this->_newitem = $params["new"];
|
572 |
+
$pid = $params["product_id"];
|
573 |
+
foreach ($this->_img_baseattrs as $attrcode)
|
574 |
+
{
|
575 |
+
// if only image/small_image/thumbnail label is present (ie: no image field)
|
576 |
+
if (isset($item[$attrcode . "_label"]) && !isset($item[$attrcode]))
|
577 |
+
{
|
578 |
+
// force label update
|
579 |
+
$attrdesc = $this->getAttrInfo($attrcode);
|
580 |
+
$this->updateLabel($attrdesc, $pid, $this->getItemStoreIds($item, $attr_desc["is_global"]),
|
581 |
+
$item[$attrcode . "_label"]);
|
582 |
+
unset($attrdesc);
|
583 |
+
}
|
584 |
+
}
|
585 |
+
// Reset media_gallery
|
586 |
+
$galreset = !(isset($item["media_gallery_reset"])) || $item["media_gallery_reset"] == 1;
|
587 |
+
$forcereset = (isset($item["media_gallery_reset"])) && $item["media_gallery_reset"] == 1;
|
588 |
+
|
589 |
+
if ((isset($item["media_gallery"]) && $galreset) || $forcereset)
|
590 |
+
{
|
591 |
+
$gattrdesc = $this->getAttrInfo("media_gallery");
|
592 |
+
$sids = $this->getItemStoreIds($item, $gattrdesc["is_global"]);
|
593 |
+
foreach ($sids as $sid)
|
594 |
+
{
|
595 |
+
$this->resetGallery($pid, $sid, $gattrdesc["attribute_id"]);
|
596 |
+
}
|
597 |
+
}
|
598 |
+
if (isset($item["image_remove"]))
|
599 |
+
{
|
600 |
+
$this->handleRemoveImages($pid, $item, $item["image_remove"]);
|
601 |
+
}
|
602 |
+
return true;
|
603 |
+
}
|
604 |
+
|
605 |
+
public function processColumnList(&$cols, $params = null)
|
606 |
+
{
|
607 |
+
// automatically add modified attributes if not found in datasource
|
608 |
+
|
609 |
+
// automatically add media_gallery for attributes to handle
|
610 |
+
$imgattrs = array_intersect(array_merge($this->_img_baseattrs, array('media_gallery')), $cols);
|
611 |
+
if (count($imgattrs) > 0)
|
612 |
+
{
|
613 |
+
$this->_active = true;
|
614 |
+
$cols = array_unique(array_merge(array_keys($this->errattrs), $cols, $imgattrs));
|
615 |
+
}
|
616 |
+
else
|
617 |
+
{
|
618 |
+
$this->log("no image attributes found in datasource, disabling image processor", "startup");
|
619 |
+
}
|
620 |
+
return true;
|
621 |
+
}
|
622 |
+
|
623 |
+
// Cleanup gallery from removed images if no more image values are present in any store
|
624 |
+
public function endImport()
|
625 |
+
{
|
626 |
+
if (!$this->_active)
|
627 |
+
{
|
628 |
+
return;
|
629 |
+
}
|
630 |
+
$attids = array();
|
631 |
+
foreach ($this->_img_baseattrs as $attrcode)
|
632 |
+
{
|
633 |
+
$inf = $this->getAttrInfo($attrcode);
|
634 |
+
if (count($inf) > 0)
|
635 |
+
{
|
636 |
+
$attids[] = $inf["attribute_id"];
|
637 |
+
}
|
638 |
+
}
|
639 |
+
if (count($attids) > 0)
|
640 |
+
{
|
641 |
+
$tg = $this->tablename('catalog_product_entity_media_gallery');
|
642 |
+
$tgv = $this->tablename('catalog_product_entity_media_gallery_value');
|
643 |
+
$sql = "DELETE emg.* FROM $tg as emg
|
644 |
+
LEFT JOIN (SELECT emg.value_id,count(emgv.value_id) as cnt FROM $tgv as emgv JOIN $tg as emg ON emg.value_id=emgv.value_id GROUP BY emg.value_id ) as t1 ON t1.value_id=emg.value_id
|
645 |
+
WHERE attribute_id IN (" . implode(",", $attids) . ") AND t1.cnt IS NULL";
|
646 |
+
$this->delete($sql);
|
647 |
+
}
|
648 |
+
else
|
649 |
+
{
|
650 |
+
$this->log("Unexpected problem in image attributes retrieval", "warning");
|
651 |
+
}
|
652 |
+
unset($attids);
|
653 |
+
}
|
654 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/imageprocessor/options_panel.php
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin is the new image importing
|
2 |
+
feature of magmi. It enables image renaming from input value with some
|
3 |
+
dynamic values coming from input values.</div>
|
4 |
+
|
5 |
+
<div class="formline">
|
6 |
+
<span>Image search path:</span><input type="text" name="IMG:sourcedir"
|
7 |
+
size="80"
|
8 |
+
value="<?php echo $this->getParam("IMG:sourcedir","media/import")?>"></input>
|
9 |
+
<div class="fieldinfo">
|
10 |
+
semicolon separated list of search paths for images<br>if relative
|
11 |
+
path is used, it means "relative to magento base dir",absolute path is
|
12 |
+
used as is
|
13 |
+
</div>
|
14 |
+
</div>
|
15 |
+
<div class="formline ifield">
|
16 |
+
<span>Image Renaming:</span><input type="text" name="IMG:renaming"
|
17 |
+
size="80" value="<?php echo $this->getParam("IMG:renaming")?>"></input>
|
18 |
+
<div class="fieldhelp"></div>
|
19 |
+
<div class="fieldinfo">
|
20 |
+
Leave blank to keep original image name.
|
21 |
+
<div class="fieldsyntax" style="display: none">
|
22 |
+
<ul>
|
23 |
+
<li>You can use "dynamic variables" to fill this field.</li>
|
24 |
+
<li>{item.[some item field]} and
|
25 |
+
{magmi.[store|imagename|imagename.noext|imagename.ext|attr_code]}
|
26 |
+
are supported.</li>
|
27 |
+
<li>{item.sku}.jpg : will create an image with item sku value as
|
28 |
+
name and a jpg extension.</li>
|
29 |
+
<li>{item.sku}_{magmi.store}.jpg : this is a little trickier.<br />
|
30 |
+
if you've got 5 stores,i will create 5 different copies of the
|
31 |
+
input image & force the name to be [item sku]_[store id].jpg
|
32 |
+
for each copy.
|
33 |
+
</li>
|
34 |
+
<li>{item.sku}_{magmi.imagename.noext}_{magmi.attr_code}.jpg, will
|
35 |
+
create [sku]_[image name without extension]_[column name].jpg
|
36 |
+
magento filename.</li>
|
37 |
+
</ul>
|
38 |
+
</div>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
<div class="formline">
|
42 |
+
<span>Image import mode</span>
|
43 |
+
<?php $iwm=$this->getParam("IMG:writemode","keep");?>
|
44 |
+
<select name="IMG:writemode">
|
45 |
+
<option value="keep" <?php if($iwm=="keep"){?> selected="selected"
|
46 |
+
<?php }?>>Keep existing images</option>
|
47 |
+
<option value="override" <?php if($iwm=="override"){?>
|
48 |
+
selected="selected" <?php }?>>Override existing images</option>
|
49 |
+
</select> <span>Assign only existing images</span> <select
|
50 |
+
name="IMG:existingonly">
|
51 |
+
<?php $existonly=$this->getParam("IMG:existingonly","no");?>
|
52 |
+
<option value="yes" <?php if($existonly=="yes"){?> selected="selected"
|
53 |
+
<?php }?>>Yes</option>
|
54 |
+
<option value="no" <?php if($existonly=="no"){?> selected="selected"
|
55 |
+
<?php }?>>No</option>
|
56 |
+
</select>
|
57 |
+
</div>
|
58 |
+
<div id="IMG:err_attrsetup">
|
59 |
+
<ul class="formline">
|
60 |
+
<li class="label">Change attributes on image error</li>
|
61 |
+
<li class="value"><input type="text" id="IMG:err_attrlist"
|
62 |
+
name="IMG:err_attrlist" size="80"
|
63 |
+
value="<?php echo $this->fixListParam($this->getParam("IMG:err_attrlist"))?>"
|
64 |
+
onblur="img_mf.buildparamlist()"></input></li>
|
65 |
+
</ul>
|
66 |
+
</div>
|
67 |
+
|
68 |
+
<div class="formline">
|
69 |
+
<span>Debug mode</span> <select name="IMG:debug">
|
70 |
+
<?php $qdd=$this->getParam("IMG:debug","no");?>
|
71 |
+
<option value="yes" <?php if($qdd=="yes"){?> selected="selected"
|
72 |
+
<?php }?>>Enable</option>
|
73 |
+
<option value="no" <?php if($qdd=="no"){?> selected="selected"
|
74 |
+
<?php }?>>Disable</option>
|
75 |
+
</select>
|
76 |
+
</div>
|
77 |
+
|
78 |
+
<div id="imgremote_details">
|
79 |
+
<h3>Remote Images Connection</h3>
|
80 |
+
|
81 |
+
<ul class="formline">
|
82 |
+
<li class="label">Remote Image root</li>
|
83 |
+
<li class="value"><input type="text" id="IMG:remoteroot"
|
84 |
+
name="IMG:remoteroot" style="width: 500px"
|
85 |
+
value="<?php echo $this->getParam("IMG:remoteroot","")?>"></li>
|
86 |
+
</ul>
|
87 |
+
|
88 |
+
<ul class="formline">
|
89 |
+
<li class="label">Remote root Authentication</li>
|
90 |
+
<li class="value"><input type="checkbox" id="IMG:remoteauth"
|
91 |
+
name="IMG:remoteauth"
|
92 |
+
<?php if($this->getParam("IMG:remoteauth",false)==true){?>
|
93 |
+
checked="checked" <?php }?>>authentication needed</li>
|
94 |
+
</ul>
|
95 |
+
|
96 |
+
<div id="imgremoteauth"
|
97 |
+
<?php if($this->getParam("IMG:remoteauth",false)==false){?>
|
98 |
+
style="display: none" <?php }?>>
|
99 |
+
<ul class="formline">
|
100 |
+
<li class="label">User</li>
|
101 |
+
<li class="value"><input type="text" name="IMG:remoteuser"
|
102 |
+
id="IMG:remoteuser"
|
103 |
+
value="<?php echo $this->getParam("IMG:remoteuser","")?>"></li>
|
104 |
+
|
105 |
+
</ul>
|
106 |
+
<ul class="formline">
|
107 |
+
<li class="label">Password</li>
|
108 |
+
<li class="value"><input type="text" name="IMG:remotepass"
|
109 |
+
id="IMG:remotepass"
|
110 |
+
value="<?php echo $this->getParam("IMG:remotepass","")?>"></li>
|
111 |
+
</ul>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
|
115 |
+
<ul class="formline">
|
116 |
+
<li class="label"><span>Pre-download check</span></li>
|
117 |
+
<li class="value"><select name="IMG:predlcheck">
|
118 |
+
<?php $qdlc=$this->getParam("IMG:predlcheck","yes");?>
|
119 |
+
<option value="yes" <?php if($qdlc=="yes"){?> selected="selected"
|
120 |
+
<?php }?>>Enable</option>
|
121 |
+
<option value="no" <?php if($qdlc=="no"){?> selected="selected"
|
122 |
+
<?php }?>>Disable</option>
|
123 |
+
</select></li>
|
124 |
+
</ul>
|
125 |
+
|
126 |
+
<script type="text/javascript">
|
127 |
+
var img_vals=<?php echo tdarray_to_js($this,'IMG:err_attrlist','IMG_ERR')?>;
|
128 |
+
var img_linetpl='<ul class="formline"><li class="label">set {fieldname} as</li><li class="value"><input type="text" name="IMG_ERR:{fieldname.enc}" value="{value}"></input></li></ul>';
|
129 |
+
img_mf=new magmi_multifield('IMG:err_attrlist','IMG:err_attrsetup',img_linetpl,img_vals);
|
130 |
+
img_mf.buildparamlist();
|
131 |
+
$('IMG:remoteauth').observe('click',function()
|
132 |
+
{
|
133 |
+
if($('IMG:remoteauth').checked)
|
134 |
+
{
|
135 |
+
$('imgremoteauth').show();
|
136 |
+
}
|
137 |
+
else
|
138 |
+
{
|
139 |
+
$('imgremoteauth').hide();
|
140 |
+
}
|
141 |
+
});
|
142 |
+
|
143 |
+
</script>
|
144 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/itemindexer/options_panel.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin fills some magento index
|
2 |
+
tables on the fly while importing item.</div>
|
3 |
+
<div>
|
4 |
+
<ul class="formline">
|
5 |
+
<li class="label">URL endings</li>
|
6 |
+
<li class="value"><input type="text" name="OTFI:urlending"
|
7 |
+
value="<?php echo $this->getParam("OTFI:urlending",".html")?>"></input></li>
|
8 |
+
</ul>
|
9 |
+
<ul class="formline">
|
10 |
+
<li class="label">Use Categories in url</li>
|
11 |
+
<li class="value">
|
12 |
+
<?php $usecat=$this->getParam("OTFI:usecatinurl",1);?>
|
13 |
+
<select name="OTFI:usecatinurl">
|
14 |
+
<option value="1" <?php if($usecat==1){?> selected="selected"
|
15 |
+
<?php }?>>Yes</option>
|
16 |
+
<option value="0" <?php if($usecat==0){?> selected="selected"
|
17 |
+
<?php }?>>No</option>
|
18 |
+
</select>
|
19 |
+
</li>
|
20 |
+
</ul>
|
21 |
+
|
22 |
+
</div>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/itemindexer/otfindexer.php
ADDED
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ItemIndexer extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $_toindex;
|
6 |
+
protected $tns;
|
7 |
+
protected $visinf;
|
8 |
+
protected $catpaths;
|
9 |
+
|
10 |
+
public function getPluginInfo()
|
11 |
+
{
|
12 |
+
return array("name"=>"On the fly indexer","author"=>"Dweeves","version"=>"0.1.6",
|
13 |
+
"url"=>$this->pluginDocUrl("On_the_fly_indexer"));
|
14 |
+
}
|
15 |
+
|
16 |
+
public function getPluginParamNames()
|
17 |
+
{
|
18 |
+
return array("OTFI:urlending","OTFI:usecatinurl");
|
19 |
+
}
|
20 |
+
|
21 |
+
public function initialize($params)
|
22 |
+
{
|
23 |
+
$this->_toindex = null;
|
24 |
+
// initialize shortname array for tables
|
25 |
+
$this->tns = array("cpe"=>$this->tablename("catalog_product_entity"),
|
26 |
+
"cce"=>$this->tablename("catalog_category_entity"),"ccp"=>$this->tablename("catalog_category_product"),
|
27 |
+
"cpw"=>$this->tablename("catalog_product_website"),"cs"=>$this->tablename("core_store"),
|
28 |
+
"csg"=>$this->tablename("core_store_group"),"cpev"=>$this->tablename("catalog_product_entity_varchar"),
|
29 |
+
"cpei"=>$this->tablename("catalog_product_entity_int"),
|
30 |
+
"ccev"=>$this->tablename("catalog_category_entity_varchar"),"ea"=>$this->tablename("eav_attribute"),
|
31 |
+
"ccpi"=>$this->tablename("catalog_category_product_index"),"curw"=>$this->tablename("core_url_rewrite"));
|
32 |
+
$inf = $this->getAttrInfo("visibility");
|
33 |
+
if ($inf == null)
|
34 |
+
{
|
35 |
+
$this->initAttrInfos(array("visibility"));
|
36 |
+
$inf = $this->getAttrInfo("visibility");
|
37 |
+
}
|
38 |
+
$this->visinf = $inf;
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Return item category ids from PID (full tree)
|
43 |
+
*
|
44 |
+
* @param $baselevel :
|
45 |
+
* begin tree from specified category level (defaults 0)
|
46 |
+
* @return array of category ids (all mixed branches) for the item
|
47 |
+
* *
|
48 |
+
*/
|
49 |
+
public function getItemCategoryIds($pid)
|
50 |
+
{
|
51 |
+
$sql = "SELECT cce.path FROM {$this->tns["ccp"]} as ccp
|
52 |
+
JOIN {$this->tns["cce"]} as cce ON ccp.category_id=cce.entity_id
|
53 |
+
WHERE ccp.product_id=?";
|
54 |
+
$result = $this->selectAll($sql, $pid);
|
55 |
+
$catidlist = array();
|
56 |
+
foreach ($result as $row)
|
57 |
+
{
|
58 |
+
$catidlist = array_merge($catidlist, explode("/", $row["path"]));
|
59 |
+
}
|
60 |
+
$catidlist = array_unique($catidlist);
|
61 |
+
sort($catidlist);
|
62 |
+
return $catidlist;
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Return item category paths per store from PID
|
67 |
+
* *
|
68 |
+
*/
|
69 |
+
public function getItemCategoryPaths($pid)
|
70 |
+
{
|
71 |
+
$sql = "SELECT cce.path as cpath,SUBSTR(cce.path,LOCATE('/',cce.path,3)+1) as cshortpath,csg.default_store_id as store_id,cce.entity_id as catid
|
72 |
+
FROM {$this->tns["ccp"]} as ccp
|
73 |
+
JOIN {$this->tns["cce"]} as cce ON cce.entity_id=ccp.category_id
|
74 |
+
JOIN {$this->tns["csg"]} as csg ON csg.root_category_id=SUBSTR(SUBSTRING_INDEX(cce.path,'/',2),LOCATE('/',SUBSTRING_INDEX(cce.path,'/',2))+1)
|
75 |
+
WHERE ccp.product_id=?";
|
76 |
+
$result = $this->selectAll($sql, $pid);
|
77 |
+
$cpaths = array();
|
78 |
+
foreach ($result as $row)
|
79 |
+
{
|
80 |
+
$sid = $row["store_id"];
|
81 |
+
if (!isset($cpaths[$sid]))
|
82 |
+
{
|
83 |
+
$cpaths[$sid] = array();
|
84 |
+
}
|
85 |
+
$cpaths[$sid][] = $row;
|
86 |
+
}
|
87 |
+
unset($result);
|
88 |
+
return $cpaths;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Build catalog_category_product_index entry for given pid
|
93 |
+
*
|
94 |
+
* @param int $pid
|
95 |
+
* , product id to create index entry for
|
96 |
+
*/
|
97 |
+
public function buildCatalogCategoryProductIndex($pid)
|
98 |
+
{
|
99 |
+
$catidlist = $this->getItemCategoryIds($pid);
|
100 |
+
if (count($catidlist) == 0)
|
101 |
+
{
|
102 |
+
return;
|
103 |
+
}
|
104 |
+
array_shift($catidlist);
|
105 |
+
// get all category ids on which the product is affected
|
106 |
+
|
107 |
+
// let's make a IN placeholder string with that
|
108 |
+
$catidin = $this->arr2values($catidlist);
|
109 |
+
// first delete lines where last inserted product was
|
110 |
+
$sql = "DELETE FROM {$this->tns["ccpi"]} WHERE product_id=?";
|
111 |
+
$this->delete($sql, $pid);
|
112 |
+
// then add lines for index
|
113 |
+
$sqlsel = "INSERT IGNORE INTO {$this->tns["ccpi"]}
|
114 |
+
SELECT cce.entity_id as category_id,ccp.product_id,ccp.position,IF(cce.entity_id=ccp.category_id,1,0) as is_parent,csg.default_store_id,cpei.value as visibility
|
115 |
+
FROM {$this->tns["ccp"]} as ccp
|
116 |
+
JOIN {$this->tns["cpe"]} as cpe ON ccp.product_id=cpe.entity_id
|
117 |
+
JOIN {$this->tns["cpei"]} as cpei ON cpei.attribute_id=? AND cpei.entity_id=cpe.entity_id
|
118 |
+
JOIN {$this->tns["cce"]} as cce ON cce.entity_id IN ($catidin)
|
119 |
+
JOIN {$this->tns["csg"]} as csg ON csg.root_category_id=SUBSTR(SUBSTRING_INDEX(cce.path,'/',2),LOCATE('/',SUBSTRING_INDEX(cce.path,'/',2))+1)
|
120 |
+
WHERE ccp.product_id=?
|
121 |
+
ORDER by is_parent DESC,csg.default_store_id,cce.entity_id";
|
122 |
+
// build data array for request
|
123 |
+
$data = array_merge(array($this->visinf["attribute_id"]), $catidlist, array($pid));
|
124 |
+
// create index line(s)
|
125 |
+
$this->insert($sqlsel, $data);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Build core_url_rewrite index entry for given pid
|
130 |
+
*
|
131 |
+
* @param int $pid
|
132 |
+
* , product id to create index entry for
|
133 |
+
*/
|
134 |
+
public function buildUrlCatProdRewrite($pid, $purlk)
|
135 |
+
{
|
136 |
+
$catpathlist = $this->getItemCategoryPaths($pid);
|
137 |
+
$data = array();
|
138 |
+
$vstr = array();
|
139 |
+
// now we have catpaths per store
|
140 |
+
$cnames = array();
|
141 |
+
foreach ($catpathlist as $storeid => $paths)
|
142 |
+
{
|
143 |
+
$catids = array();
|
144 |
+
|
145 |
+
foreach ($paths as $pathinfo)
|
146 |
+
{
|
147 |
+
$catids = array_unique(array_merge($catids, explode("/", $pathinfo["cshortpath"])));
|
148 |
+
}
|
149 |
+
|
150 |
+
$catin = $this->arr2values($catids);
|
151 |
+
|
152 |
+
// use tricky double join on eav_attribute to find category related 'name' attribute using 'children' category only attr to distinguish on category entity_id
|
153 |
+
$sql = "SELECT cce.entity_id as catid,COALESCE(ccev.value,ccevd.value) as value
|
154 |
+
FROM {$this->tns["cce"]} as cce
|
155 |
+
JOIN {$this->tns["ea"]} as ea1 ON ea1.attribute_code='children'
|
156 |
+
JOIN {$this->tns["ea"]} as ea2 ON ea2.attribute_code ='name' AND ea2.entity_type_id=ea1.entity_type_id
|
157 |
+
JOIN {$this->tns["ccev"]} as ccevd ON ccevd.attribute_id=ea2.attribute_id AND ccevd.entity_id=cce.entity_id AND ccevd.store_id=0
|
158 |
+
LEFT JOIN {$this->tns["ccev"]} as ccev ON ccev.attribute_id=ea2.attribute_id AND ccev.entity_id=cce.entity_id AND ccev.store_id=?
|
159 |
+
WHERE cce.entity_id IN ($catin)
|
160 |
+
GROUP BY cce.entity_id";
|
161 |
+
$result = $this->selectAll($sql, array_merge(array($storeid), $catids));
|
162 |
+
|
163 |
+
// iterate on all names
|
164 |
+
foreach ($result as $row)
|
165 |
+
{
|
166 |
+
$catid = $row["catid"];
|
167 |
+
$cnames[$catid] = $row["value"];
|
168 |
+
}
|
169 |
+
|
170 |
+
foreach ($paths as $pinfo)
|
171 |
+
{
|
172 |
+
$sp = $pinfo["cshortpath"];
|
173 |
+
$cpids = explode("/", $sp);
|
174 |
+
$names = array();
|
175 |
+
foreach ($cpids as $cpid)
|
176 |
+
{
|
177 |
+
if (isset($cnames[$cpid]))
|
178 |
+
{
|
179 |
+
$names[] = $cnames[$cpid];
|
180 |
+
}
|
181 |
+
}
|
182 |
+
// make string with that
|
183 |
+
$namestr = implode("/", $names);
|
184 |
+
// build category url key (allow / in slugging)
|
185 |
+
$curlk = Slugger::slug($namestr, true);
|
186 |
+
|
187 |
+
// product + category url entries request
|
188 |
+
$catid = $pinfo["catid"];
|
189 |
+
$sdata = array($pid,$storeid,$catid,"product/$pid/$catid",
|
190 |
+
"catalog/product/view/id/$pid/category/$catid","$curlk/$purlk",1);
|
191 |
+
$vstr[] = "(" . $this->arr2values($sdata) . ")";
|
192 |
+
$data = array_merge($data, $sdata);
|
193 |
+
}
|
194 |
+
}
|
195 |
+
if (count($vstr) > 0)
|
196 |
+
{
|
197 |
+
$sqlprodcat = "INSERT IGNORE INTO {$this->tns["curw"]} (product_id,store_id,category_id,id_path,target_path,request_path,is_system) VALUES " .
|
198 |
+
implode(",", $vstr);
|
199 |
+
$this->insert($sqlprodcat, $data);
|
200 |
+
}
|
201 |
+
if (count($catpathlist) > 0)
|
202 |
+
{
|
203 |
+
// now insert category url rewrite
|
204 |
+
$this->buildCatUrlRewrite($catpathlist, $cnames);
|
205 |
+
}
|
206 |
+
unset($data);
|
207 |
+
unset($sdata);
|
208 |
+
unset($vstr);
|
209 |
+
}
|
210 |
+
|
211 |
+
public function buildCatUrlRewrite($catpathlist, $cnames)
|
212 |
+
{
|
213 |
+
$vstr = array();
|
214 |
+
$data = array();
|
215 |
+
foreach ($catpathlist as $storeid => $paths)
|
216 |
+
{
|
217 |
+
foreach ($paths as $pinfo)
|
218 |
+
{
|
219 |
+
$sp = $pinfo["cshortpath"];
|
220 |
+
$cpids = explode("/", $sp);
|
221 |
+
$names = array();
|
222 |
+
foreach ($cpids as $cpid)
|
223 |
+
{
|
224 |
+
if (isset($cnames[$cpid]))
|
225 |
+
{
|
226 |
+
$names[] = $cnames[$cpid];
|
227 |
+
// make string with that
|
228 |
+
$namestr = implode("/", $names);
|
229 |
+
$urlend = $this->getParam("OTFI:urlending", ".html");
|
230 |
+
// build category url key (allow / in slugging)
|
231 |
+
$curlk = Slugger::slug($namestr, true) . $urlend;
|
232 |
+
$cdata = array($storeid,$cpid,"category/$cpid","catalog/category/view/id/$cpid","$curlk",1);
|
233 |
+
$vstr[] = "(" . $this->arr2values($cdata) . ")";
|
234 |
+
$data = array_merge($data, $cdata);
|
235 |
+
}
|
236 |
+
}
|
237 |
+
}
|
238 |
+
}
|
239 |
+
if (count($vstr) > 0)
|
240 |
+
{
|
241 |
+
$sqlcat = "INSERT INTO {$this->tns["curw"]} (store_id,category_id,id_path,target_path,request_path,is_system) VALUES " .
|
242 |
+
implode(",", $vstr) . " ON DUPLICATE KEY UPDATE request_path=VALUES(`request_path`)";
|
243 |
+
$this->insert($sqlcat, $data);
|
244 |
+
}
|
245 |
+
}
|
246 |
+
|
247 |
+
public function builProductUrlRewrite($pid)
|
248 |
+
{
|
249 |
+
$sql = "SELECT ea.attribute_code,cpei.value,cpev.attribute_id,cpev.value
|
250 |
+
FROM {$this->tns["cpe"]} AS cpe
|
251 |
+
JOIN {$this->tns["ea"]} as ea ON ea.attribute_code IN ('url_key','name')
|
252 |
+
JOIN {$this->tns["cpev"]} as cpev ON cpev.entity_id=cpe.entity_id AND cpev.attribute_id=ea.attribute_id
|
253 |
+
JOIN {$this->tns["cpei"]} as cpei ON cpei.entity_id=cpe.entity_id AND cpei.attribute_id=? AND cpei.value>1
|
254 |
+
WHERE cpe.entity_id=?";
|
255 |
+
$result = $this->selectAll($sql, array($this->visinf["attribute_id"],$pid));
|
256 |
+
// nothing to build, product is not visible,return
|
257 |
+
if (count($result) == 0)
|
258 |
+
{
|
259 |
+
return;
|
260 |
+
}
|
261 |
+
// see what we get as available product attributes
|
262 |
+
foreach ($result as $row)
|
263 |
+
{
|
264 |
+
if ($row["attribute_code"] == "url_key")
|
265 |
+
{
|
266 |
+
$pburlk = nullifempty($row["value"]);
|
267 |
+
}
|
268 |
+
if ($row["attribute_code"] == "name")
|
269 |
+
{
|
270 |
+
$pname = $row["value"];
|
271 |
+
}
|
272 |
+
}
|
273 |
+
// if we've got an url key use it, otherwise , make a slug from the product name as url key
|
274 |
+
$urlend = $this->getParam("OTFI:urlending", ".html");
|
275 |
+
$purlk = (isset($pburlk) ? $pburlk : Slugger::slug($pname)) . $urlend;
|
276 |
+
|
277 |
+
// delete old "system" url rewrite entries for product
|
278 |
+
$sql = "DELETE FROM {$this->tns["curw"]} WHERE product_id=? AND is_system=1";
|
279 |
+
$this->delete($sql, $pid);
|
280 |
+
|
281 |
+
// product url index info
|
282 |
+
$produrlsql = "SELECT cpe.entity_id,cs.store_id,
|
283 |
+
CONCAT('product/',cpe.entity_id) as id_path,
|
284 |
+
CONCAT('catalog/product/view/id/',cpe.entity_id) as target_path,
|
285 |
+
? AS request_path,
|
286 |
+
1 as is_system
|
287 |
+
FROM {$this->tns["cpe"]} as cpe
|
288 |
+
JOIN {$this->tns["cpw"]} as cpw ON cpw.product_id=cpe.entity_id
|
289 |
+
JOIN {$this->tns["cs"]} as cs ON cs.website_id=cpw.website_id
|
290 |
+
JOIN {$this->tns["ccp"]} as ccp ON ccp.product_id=cpe.entity_id
|
291 |
+
JOIN {$this->tns["cce"]} as cce ON ccp.category_id=cce.entity_id
|
292 |
+
WHERE cpe.entity_id=?";
|
293 |
+
|
294 |
+
// insert lines
|
295 |
+
$sqlprod = "INSERT INTO {$this->tns["curw"]} (product_id,store_id,id_path,target_path,request_path,is_system) $produrlsql ON DUPLICATE KEY UPDATE request_path=VALUES(`request_path`)";
|
296 |
+
$this->insert($sqlprod, array($purlk,$pid));
|
297 |
+
return $purlk;
|
298 |
+
}
|
299 |
+
|
300 |
+
public function buildUrlRewrite($pid)
|
301 |
+
{
|
302 |
+
$purlk = $this->builProductUrlRewrite($pid);
|
303 |
+
if ($this->getParam("OTFI:usecatinurl"))
|
304 |
+
{
|
305 |
+
$this->buildUrlCatProdRewrite($pid, $purlk);
|
306 |
+
}
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* OBSOLETED , TO BE REWORKED LATER
|
311 |
+
*/
|
312 |
+
public function buildPriceIndex($pid)
|
313 |
+
{
|
314 |
+
$priceidx = $this->tablename("catalog_product_index_price");
|
315 |
+
$pet = $this->getProductEntityType();
|
316 |
+
$sql = "DELETE FROM $priceidx WHERE entity_id=?";
|
317 |
+
$this->delete($sql, $pid);
|
318 |
+
$cpe = $this->tablename("catalog_product_entity");
|
319 |
+
$cs = $this->tablename("core_store");
|
320 |
+
$cg = $this->tablename("customer_group");
|
321 |
+
$cped = $this->tablename("catalog_product_entity_decimal");
|
322 |
+
$ea = $this->tablename("eav_attribute");
|
323 |
+
$cpetp = $this->tablename("catalog_product_entity_tier_price");
|
324 |
+
$cpei = $this->tablename("catalog_product_entity_int");
|
325 |
+
$sql = "INSERT INTO $priceidx SELECT cped.entity_id,
|
326 |
+
cg.customer_group_id,
|
327 |
+
cs.website_id,
|
328 |
+
cpei.value as tax_class_id,
|
329 |
+
cped.value as price,
|
330 |
+
MIN(cped.value) as final_price,
|
331 |
+
MIN(cped.value) as min_price,
|
332 |
+
MIN(cped.value) as max_price,
|
333 |
+
cpetp2.value as tier_price
|
334 |
+
FROM $cpe as cpe
|
335 |
+
JOIN $cs as cs ON cs.store_id!=0
|
336 |
+
JOIN $cped as cped ON cped.store_id=cs.store_id AND cped.entity_id=cpe.entity_id
|
337 |
+
JOIN $cg as cg
|
338 |
+
JOIN $ea as ead ON ead.entity_type_id=? AND ead.attribute_code IN('price','special_price','minimal_price') AND cped.attribute_id=ead.attribute_id
|
339 |
+
JOIN $ea as eai ON eai.entity_type_id=ead.entity_type_id AND eai.attribute_code='tax_class_id'
|
340 |
+
LEFT JOIN $cpetp as cpetp ON cpetp.entity_id=cped.entity_id
|
341 |
+
LEFT JOIN $cpetp as cpetp2 ON cpetp2.entity_id=cped.entity_id AND cpetp2.customer_group_id=cg.customer_group_id
|
342 |
+
LEFT JOIN $cpei as cpei ON cpei.entity_id=cpe.entity_id AND cpei.attribute_id=eai.attribute_id
|
343 |
+
WHERE cpe.entity_id=?
|
344 |
+
GROUP by cs.website_id,cg.customer_group_id
|
345 |
+
ORDER by cg.customer_group_id,cs.website_id
|
346 |
+
";
|
347 |
+
$this->insert($sql, array($pet,$pid));
|
348 |
+
}
|
349 |
+
|
350 |
+
// To be done, find a way to avoid reindexing if not necessary
|
351 |
+
public function shouldReindex($item)
|
352 |
+
{
|
353 |
+
return count($item) > 0;
|
354 |
+
}
|
355 |
+
|
356 |
+
public function processItemAfterImport(&$item, $params = null)
|
357 |
+
{
|
358 |
+
if (count($item) > 0)
|
359 |
+
{
|
360 |
+
$this->reindexLastImported();
|
361 |
+
// if current item is not the same than previous one
|
362 |
+
if ($params["same"] == false)
|
363 |
+
{
|
364 |
+
if ($this->shouldReindex($item))
|
365 |
+
{
|
366 |
+
$this->_toindex = array("sku"=>$item["sku"],"pid"=>$params["product_id"]);
|
367 |
+
}
|
368 |
+
else
|
369 |
+
{
|
370 |
+
$this->log("Do not reindex, no indexed column changed");
|
371 |
+
}
|
372 |
+
}
|
373 |
+
}
|
374 |
+
return true;
|
375 |
+
}
|
376 |
+
|
377 |
+
// index last imported item
|
378 |
+
public function reindexLastImported()
|
379 |
+
{
|
380 |
+
if ($this->_toindex != null)
|
381 |
+
{
|
382 |
+
$pid = $this->_toindex["pid"];
|
383 |
+
$this->buildCatalogCategoryProductIndex($pid);
|
384 |
+
$this->buildUrlRewrite($pid);
|
385 |
+
$this->_toindex = null;
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
public function afterImport()
|
390 |
+
{
|
391 |
+
// reindex last item since we index one row later than the current
|
392 |
+
$this->reindexLastImported();
|
393 |
+
}
|
394 |
+
}
|
395 |
+
|
396 |
+
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/03_valuereplacer.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class ValueReplacerItemProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
protected $_rvals = array();
|
12 |
+
protected $_before = array("sku","attribute_set","type");
|
13 |
+
|
14 |
+
public function getPluginInfo()
|
15 |
+
{
|
16 |
+
return array("name"=>"Value Replacer","author"=>"Dweeves","version"=>"0.0.8a",
|
17 |
+
"url"=>$this->pluginDocUrl("Value_Replacer"));
|
18 |
+
}
|
19 |
+
|
20 |
+
public function processItemBeforeId(&$item, $params = null)
|
21 |
+
{
|
22 |
+
$cbefore = count($this->_before);
|
23 |
+
|
24 |
+
// only check for "before" compatible fields
|
25 |
+
|
26 |
+
for ($i = 0; $i < $cbefore; $i++)
|
27 |
+
{
|
28 |
+
$attname = $this->_before[$i];
|
29 |
+
if (isset($this->_rvals[$attname]))
|
30 |
+
{
|
31 |
+
$item[$attname] = $this->parseCalculatedValue($this->_rvals[$attname], $item, $params);
|
32 |
+
}
|
33 |
+
}
|
34 |
+
return true;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function processItemAfterId(&$item, $params = null)
|
38 |
+
{
|
39 |
+
foreach ($this->_rvals as $attname => $pvalue)
|
40 |
+
{
|
41 |
+
// do not reparse "before" fields
|
42 |
+
if (!in_array($attname, $this->_before))
|
43 |
+
{
|
44 |
+
$item[$attname] = $this->parseCalculatedValue($pvalue, $item, $params);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
return true;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function initHelpers()
|
51 |
+
{
|
52 |
+
$helperdir = dirname(__FILE__) . "/helper";
|
53 |
+
$files = glob($helperdir . "/*.php");
|
54 |
+
foreach ($files as $f)
|
55 |
+
{
|
56 |
+
require_once ($f);
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
public function initialize($params)
|
61 |
+
{
|
62 |
+
foreach ($params as $k => $v)
|
63 |
+
{
|
64 |
+
if (preg_match_all("/^VREP:(.*)$/", $k, $m) && $k != "VREP:columnlist")
|
65 |
+
{
|
66 |
+
$colname = rawurldecode($m[1][0]);
|
67 |
+
$this->_rvals[$colname] = $params[$k];
|
68 |
+
}
|
69 |
+
}
|
70 |
+
$this->initHelpers();
|
71 |
+
}
|
72 |
+
|
73 |
+
// auto add columns if not set
|
74 |
+
public function processColumnList(&$cols)
|
75 |
+
{
|
76 |
+
$base_cols = $cols;
|
77 |
+
$cols = array_unique(array_merge($cols, explode(",", $this->getParam("VREP:columnlist"))));
|
78 |
+
$newcols = array_diff($cols, $base_cols);
|
79 |
+
if (count($newcols) > 0)
|
80 |
+
{
|
81 |
+
$this->log("Added columns : " . implode(",", $newcols), "startup");
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getPluginParams($params)
|
86 |
+
{
|
87 |
+
$pp = array();
|
88 |
+
foreach ($params as $k => $v)
|
89 |
+
{
|
90 |
+
if (preg_match("/^VREP:.*$/", $k))
|
91 |
+
{
|
92 |
+
$pp[$k] = $v;
|
93 |
+
}
|
94 |
+
}
|
95 |
+
return $pp;
|
96 |
+
}
|
97 |
+
|
98 |
+
static public function getCategory()
|
99 |
+
{
|
100 |
+
return "Input Data Preprocessing";
|
101 |
+
}
|
102 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/helper/remapper.php
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class ValueRemapper
|
4 |
+
{
|
5 |
+
protected static $_inst;
|
6 |
+
protected $_maps = array();
|
7 |
+
protected $_cimaps = array();
|
8 |
+
protected $_curmap = null;
|
9 |
+
|
10 |
+
public function __construct()
|
11 |
+
{}
|
12 |
+
|
13 |
+
static public function getInstance()
|
14 |
+
{
|
15 |
+
if (self::$_inst == null)
|
16 |
+
{
|
17 |
+
self::$_inst = new ValueRemapper();
|
18 |
+
}
|
19 |
+
return self::$_inst;
|
20 |
+
}
|
21 |
+
|
22 |
+
public static function use_csv($csv)
|
23 |
+
{
|
24 |
+
$inst = self::getInstance();
|
25 |
+
$inst->setMap($csv);
|
26 |
+
$inst->_curmap = $csv;
|
27 |
+
return $inst;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function map($val, $ci = false)
|
31 |
+
{
|
32 |
+
$tval = trim($val);
|
33 |
+
// remapper case insensitive fix
|
34 |
+
if ($ci)
|
35 |
+
{
|
36 |
+
$tval = strtoupper($val);
|
37 |
+
$targetmap = $this->_cimaps[$this->_curmap];
|
38 |
+
}
|
39 |
+
else
|
40 |
+
{
|
41 |
+
$targetmap = $this->_maps[$this->_curmap];
|
42 |
+
}
|
43 |
+
return isset($targetmap[$tval]) ? $targetmap[$tval] : $val;
|
44 |
+
}
|
45 |
+
|
46 |
+
/*
|
47 |
+
* Map a multivalue given a separator
|
48 |
+
*/
|
49 |
+
public function mapmulti($val, $sep = ',', $ci = false)
|
50 |
+
{
|
51 |
+
$vals = explode($sep, $val);
|
52 |
+
for ($i = 0; $i < count($vals); $i++)
|
53 |
+
{
|
54 |
+
$vals[$i] = $this->map($vals[$i], $ci);
|
55 |
+
}
|
56 |
+
return implode($sep, $vals);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function setMap($csv)
|
60 |
+
{
|
61 |
+
if (!isset($this->_maps[$csv]))
|
62 |
+
{
|
63 |
+
$this->_maps[$csv] = array();
|
64 |
+
$this->_cimaps[$csv] = array();
|
65 |
+
if (file_exists($csv))
|
66 |
+
{
|
67 |
+
$lines = file($csv);
|
68 |
+
foreach ($lines as $line)
|
69 |
+
{
|
70 |
+
$kv = explode(";", trim($line));
|
71 |
+
$this->_maps[$csv][$kv[0]] = $kv[1];
|
72 |
+
$this->_cimaps[$csv][strtoupper($kv[0])] = $kv[1];
|
73 |
+
}
|
74 |
+
}
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuereplacer/options_panel.php
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin enables to change attribute
|
2 |
+
values from datasource before they are handled by magmi. enter
|
3 |
+
attributes to set new value for in replaced attributes field, separated
|
4 |
+
by commas (,) when leaving the field, new fields will be inserted for
|
5 |
+
filling new column names.</div>
|
6 |
+
<?php $clist=$this->fixListParam($this->getParam("VREP:columnlist"))?>
|
7 |
+
|
8 |
+
<ul class="formline">
|
9 |
+
<li class="label">Replaced attributes</li>
|
10 |
+
<li class="value"><input type="text" id="VREP:columnlist"
|
11 |
+
name="VREP:columnlist" size="80" value="<?php echo $clist?>"
|
12 |
+
onblur="vrep_mf.buildparamlist()"></input></li>
|
13 |
+
</ul>
|
14 |
+
<div id="VREP:columnsetup"></div>
|
15 |
+
|
16 |
+
<div class="formline ifield">
|
17 |
+
<div class="fieldhelp"></div>
|
18 |
+
<div class="fieldinfo">
|
19 |
+
<div style="height: 24px">You can use "dynamic variables" to fill
|
20 |
+
above fields.</div>
|
21 |
+
<div class="fieldsyntax" style="display: none">
|
22 |
+
<hr />
|
23 |
+
|
24 |
+
<ul>
|
25 |
+
<li>{item.[some item field]} and {{some expression}} are supported.</li>
|
26 |
+
<li>[some item field] has to be present either as datasource column
|
27 |
+
or default value setter/column mapper added column</li>
|
28 |
+
<li>examples below assume sku=sku0 & cost=8.00 & margin=15
|
29 |
+
(here margin may not even be an attribute)</li>
|
30 |
+
</ul>
|
31 |
+
<hr />
|
32 |
+
<ul>
|
33 |
+
<li><b>dynamic field Examples</b></li>
|
34 |
+
<li>with sku in the list of replaced fields, if xxx-{item.sku} for
|
35 |
+
replacing value , the sku inserted will be xxx-sku0</li>
|
36 |
+
<li>you can put any number of {item.[some item field]} references in
|
37 |
+
the replacing value</li>
|
38 |
+
</ul>
|
39 |
+
<hr />
|
40 |
+
<ul>
|
41 |
+
<li><b>Expression examples:</b></li>
|
42 |
+
<li>lets say you want to calculate cost from cost & margin</li>
|
43 |
+
<li>just put {{ {item.cost}*(1+({item.margin}/100)) }} in the
|
44 |
+
replaced value for price</li>
|
45 |
+
</ul>
|
46 |
+
<hr />
|
47 |
+
<ul>
|
48 |
+
<li><b>Advanced expressions</b></li>
|
49 |
+
<li>expressions use php eval() function, so beware of what you're
|
50 |
+
doing but it can be also very powerful as:</li>
|
51 |
+
<li>{{ substr("{item.sku}",0,4) }}</li>
|
52 |
+
</ul>
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
</div>
|
56 |
+
<script type="text/javascript">
|
57 |
+
var vr_vals=<?php echo tdarray_to_js($this,'VREP:columnlist','VREP')?>;
|
58 |
+
var vr_linetpl='<ul class="formline"><li class="label">New value for {fieldname}</li><li class="value"><input type="text" name="VREP:{fieldname.enc}" value="{value}"></input></li></ul>';
|
59 |
+
vrep_mf=new magmi_multifield('VREP:columnlist','VREP:columnsetup',vr_linetpl,vr_vals);
|
60 |
+
vrep_mf.buildparamlist();
|
61 |
+
</script>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuetrim/options_panel.php
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
<div class="plugin_description">This plugin automatically trims values
|
2 |
+
for select/multiselect attributes.</div>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/itemprocessors/valuetrim/valuetrimmer.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Class SampleItemProcessor
|
5 |
+
* @author dweeves
|
6 |
+
*
|
7 |
+
* This class is a sample for item processing
|
8 |
+
*/
|
9 |
+
class ValueTrimItemProcessor extends Magmi_ItemProcessor
|
10 |
+
{
|
11 |
+
protected $_totrim = array();
|
12 |
+
protected $_scanned = false;
|
13 |
+
|
14 |
+
public function getPluginInfo()
|
15 |
+
{
|
16 |
+
return array("name"=>"Value Trimmer for select/multiselect","author"=>"Dweeves","version"=>"0.0.3",
|
17 |
+
"url"=>$this->pluginDocUrl("Value_Trimmer_for_select/multiselect"));
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
22 |
+
*
|
23 |
+
* @param Magmi_Engine $mmi
|
24 |
+
* : reference to magmi engine instance (convenient to perform database operations)
|
25 |
+
* @param unknown_type $item
|
26 |
+
* : modifiable reference to item before import
|
27 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
28 |
+
* @return bool :
|
29 |
+
* true if you want the item to be imported after your custom processing
|
30 |
+
* false if you want to skip item import after your processing
|
31 |
+
*/
|
32 |
+
public function getTrimmableCols($item)
|
33 |
+
{
|
34 |
+
if (!$this->_scanned)
|
35 |
+
{
|
36 |
+
foreach (array_keys($item) as $col)
|
37 |
+
{
|
38 |
+
$ainfo = $this->getAttrInfo($col);
|
39 |
+
if (count($ainfo) > 0)
|
40 |
+
{
|
41 |
+
if ($ainfo["frontend_input"] == "select" || $ainfo["frontend_input"] == "multiselect")
|
42 |
+
{
|
43 |
+
$this->_totrim[$col] = $ainfo["frontend_input"];
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
47 |
+
$this->_scanned = true;
|
48 |
+
}
|
49 |
+
return $this->_totrim;
|
50 |
+
}
|
51 |
+
|
52 |
+
public function processItemBeforeId(&$item, $params = null)
|
53 |
+
{
|
54 |
+
// get list of trimmable columns
|
55 |
+
$tc = $this->getTrimmableCols($item);
|
56 |
+
foreach ($tc as $col => $mode)
|
57 |
+
{
|
58 |
+
// for select, just trim value
|
59 |
+
if ($mode == "select")
|
60 |
+
{
|
61 |
+
$item[$col] = trim($item[$col]);
|
62 |
+
}
|
63 |
+
else
|
64 |
+
// for multiselect, recompose trimmed value list
|
65 |
+
{
|
66 |
+
$sep = Magmi_Config::getInstance()->get("GLOBAL", "mutiselect_sep", ",");
|
67 |
+
$vt = explode($sep, $item[$col]);
|
68 |
+
foreach ($vt as &$v)
|
69 |
+
{
|
70 |
+
$v = trim($v);
|
71 |
+
}
|
72 |
+
$item[$col] = implode($sep, $vt);
|
73 |
+
unset($vt);
|
74 |
+
}
|
75 |
+
}
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
|
79 |
+
public function initialize($params)
|
80 |
+
{
|
81 |
+
$this->_scanned = false;
|
82 |
+
$this->_totrim = array();
|
83 |
+
return true;
|
84 |
+
}
|
85 |
+
|
86 |
+
static public function getCategory()
|
87 |
+
{
|
88 |
+
return "Input Data Preprocessing";
|
89 |
+
}
|
90 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/extra/obsolete.txt
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
itemprocessors/itemindexer/priceindexer.php
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_datasource.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Magmi_Datasource
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
* This class enables to perform input format support for ingested data
|
7 |
+
*/
|
8 |
+
require_once ("magmi_generalimport_plugin.php");
|
9 |
+
|
10 |
+
abstract class Magmi_DataSource extends Magmi_GeneralImportPlugin
|
11 |
+
{
|
12 |
+
|
13 |
+
public function getColumnNames($prescan = false)
|
14 |
+
{}
|
15 |
+
|
16 |
+
public function getRecordsCount()
|
17 |
+
{}
|
18 |
+
|
19 |
+
public function getNextRecord()
|
20 |
+
{}
|
21 |
+
|
22 |
+
public function onException($e)
|
23 |
+
{}
|
24 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_default_options_panel.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<span>Plugin has no configurable parameters</span>
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_defaultattributehandler.php
ADDED
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_DefaultAttributeItemProcessor extends Magmi_ItemProcessor
|
4 |
+
{
|
5 |
+
protected $_basecols = array("store"=>"admin","type"=>"simple");
|
6 |
+
protected $_baseattrs = array("status"=>1,"visibility"=>4,"page_layout"=>"","tax_class_id"=>"Taxable Goods");
|
7 |
+
protected $_forcedefault = array("store"=>"admin");
|
8 |
+
protected $_missingcols = array();
|
9 |
+
protected $_missingattrs = array();
|
10 |
+
|
11 |
+
/**
|
12 |
+
* (non-PHPdoc)
|
13 |
+
*
|
14 |
+
* @see Magmi_Plugin::initialize()
|
15 |
+
*/
|
16 |
+
public function initialize($params)
|
17 |
+
{
|
18 |
+
$this->registerAttributeHandler($this, array("attribute_code:.*"));
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* (non-PHPdoc)
|
23 |
+
*
|
24 |
+
* @see Magmi_Plugin::getPluginInfo()
|
25 |
+
*/
|
26 |
+
public function getPluginInfo()
|
27 |
+
{
|
28 |
+
return array("name"=>"Standard Attribute Import","author"=>"Dweeves","version"=>"1.0.6");
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* callback for column list processing
|
33 |
+
*
|
34 |
+
* @param unknown $cols
|
35 |
+
*/
|
36 |
+
public function processColumnList(&$cols)
|
37 |
+
{
|
38 |
+
// This will not change the column list
|
39 |
+
// this will only log the list of columns that will be added to newly created items
|
40 |
+
$this->_missingcols = array_diff(array_keys($this->_basecols), $cols);
|
41 |
+
$this->_missingattrs = array_diff(array_keys($this->_baseattrs), $cols);
|
42 |
+
$m = $this->getMode();
|
43 |
+
if ($m == "create" || $m == "xcreate")
|
44 |
+
{
|
45 |
+
$cols = array_merge($cols, $this->_missingcols, $this->_missingattrs);
|
46 |
+
$this->log(
|
47 |
+
"Newly created items will have default values for columns:" .
|
48 |
+
implode(",", array_merge($this->_missingcols, $this->_missingattrs)), "startup");
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* initializes extra columns if needed
|
54 |
+
*
|
55 |
+
* @param unknown $item
|
56 |
+
*/
|
57 |
+
public function initializeBaseCols(&$item)
|
58 |
+
{
|
59 |
+
foreach ($this->_missingcols as $missing)
|
60 |
+
{
|
61 |
+
$item[$missing] = $this->_basecols[$missing];
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Initialized base attributes to retrieve from a given item description
|
67 |
+
*
|
68 |
+
* @param unknown $item
|
69 |
+
*/
|
70 |
+
public function initializeBaseAttrs(&$item)
|
71 |
+
{
|
72 |
+
foreach ($this->_missingattrs as $missing)
|
73 |
+
{
|
74 |
+
$item[$missing] = $this->_baseattrs[$missing];
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* (non-PHPdoc)
|
80 |
+
*
|
81 |
+
* @see Magmi_ItemProcessor::processItemAfterId()
|
82 |
+
*/
|
83 |
+
public function processItemAfterId(&$item, $params = null)
|
84 |
+
{
|
85 |
+
if ($params["new"] == true)
|
86 |
+
{
|
87 |
+
$this->initializeBaseCols($item);
|
88 |
+
$this->initializeBaseAttrs($item);
|
89 |
+
}
|
90 |
+
// forcing default values for mandatory processing columns
|
91 |
+
foreach ($this->_forcedefault as $k => $v)
|
92 |
+
{
|
93 |
+
if (isset($item[$k]) && trim($item[$k]) == "")
|
94 |
+
{
|
95 |
+
$item[$k] = $v;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
return true;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* returns magento default value if applicable
|
103 |
+
* - item should not exist yet
|
104 |
+
* - default value should be set in magento
|
105 |
+
* - ivalue should be empty
|
106 |
+
*
|
107 |
+
* @param array $attrdesc
|
108 |
+
* : attribute description table
|
109 |
+
* @param mixed $ivalue
|
110 |
+
* : input value
|
111 |
+
* @return magento default value or NULL if not applicable
|
112 |
+
*/
|
113 |
+
public function getDefaultValue($attrdesc, $ivalue)
|
114 |
+
{
|
115 |
+
$exists = $this->currentItemExists();
|
116 |
+
// check for new item default value in DB for new items
|
117 |
+
if (!$exists && isset($attrdesc["default_value"]) && !empty($attrdesc["default_value"]) && empty($ivalue))
|
118 |
+
{
|
119 |
+
return $attrdesc["default_value"];
|
120 |
+
}
|
121 |
+
return null;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* attribute handler for Decimal attributes
|
126 |
+
*
|
127 |
+
* @param int $pid
|
128 |
+
* : product id
|
129 |
+
* @param array $item
|
130 |
+
* : item to inges
|
131 |
+
* @param int $storeid
|
132 |
+
* : store for attribute value storage
|
133 |
+
* @param int $attrcode
|
134 |
+
* : attribute code
|
135 |
+
* @param array $attrdesc
|
136 |
+
* : attribute metadata
|
137 |
+
* @param mixed $ivalue
|
138 |
+
* : input value to import
|
139 |
+
* @return new decimal value to set
|
140 |
+
*/
|
141 |
+
public function handleDecimalAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
142 |
+
{
|
143 |
+
$dval = $this->getDefaultValue($attrdesc, $ivalue);
|
144 |
+
if ($dval !== null)
|
145 |
+
{
|
146 |
+
return $dval;
|
147 |
+
}
|
148 |
+
// force convert decimal separator to dot
|
149 |
+
$ivalue = str_replace(",", ".", $ivalue);
|
150 |
+
$ovalue = deleteifempty($ivalue);
|
151 |
+
return $ovalue;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* attribute handler for DateTime attributes
|
156 |
+
*
|
157 |
+
* @param int $pid
|
158 |
+
* : product id
|
159 |
+
* @param array $item
|
160 |
+
* : item to inges
|
161 |
+
* @param int $storeid
|
162 |
+
* : store for attribute value storage
|
163 |
+
* @param int $attrcode
|
164 |
+
* : attribute code
|
165 |
+
* @param array $attrdesc
|
166 |
+
* : attribute metadata
|
167 |
+
* @param mixed $ivalue
|
168 |
+
* : input value to import
|
169 |
+
* @return new datetime value to set
|
170 |
+
*/
|
171 |
+
public function handleDatetimeAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
172 |
+
{
|
173 |
+
$dval = $this->getDefaultValue($attrdesc, $ivalue);
|
174 |
+
if ($dval !== null)
|
175 |
+
{
|
176 |
+
return $dval;
|
177 |
+
}
|
178 |
+
$ovalue = deleteifempty(trim($ivalue));
|
179 |
+
// Handle european date format or other common separators
|
180 |
+
if (preg_match("|(\d{1,2})\D(\d{1,2})\D(\d{4})\s*(\d{2}:\d{2}:\d{2})?|", $ovalue, $matches))
|
181 |
+
{
|
182 |
+
$hms = count($matches) > 4 ? $matches[4] : "";
|
183 |
+
$ovalue = trim(sprintf("%4d-%2d-%2d %s", $matches[3], $matches[2], $matches[1], $hms));
|
184 |
+
}
|
185 |
+
return $ovalue;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* attribute handler for Text attributes
|
190 |
+
*
|
191 |
+
* @param int $pid
|
192 |
+
* : product id
|
193 |
+
* @param array $item
|
194 |
+
* : item to inges
|
195 |
+
* @param int $storeid
|
196 |
+
* : store for attribute value storage
|
197 |
+
* @param int $attrcode
|
198 |
+
* : attribute code
|
199 |
+
* @param array $attrdesc
|
200 |
+
* : attribute metadata
|
201 |
+
* @param mixed $ivalue
|
202 |
+
* : input value to import
|
203 |
+
* @return new text value to set
|
204 |
+
*/
|
205 |
+
public function handleTextAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
206 |
+
{
|
207 |
+
$dval = $this->getDefaultValue($attrdesc, $ivalue);
|
208 |
+
if ($dval !== null)
|
209 |
+
{
|
210 |
+
return $dval;
|
211 |
+
}
|
212 |
+
$ovalue = deleteifempty($ivalue);
|
213 |
+
return $ovalue;
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* check if a value is integer
|
218 |
+
*
|
219 |
+
* @param mixed $value
|
220 |
+
* @return true if integer, false if not
|
221 |
+
*/
|
222 |
+
public function checkInt($value)
|
223 |
+
{
|
224 |
+
return is_int($value) || (is_string($value) && is_numeric($value) && (int) $value == $value);
|
225 |
+
}
|
226 |
+
|
227 |
+
/**
|
228 |
+
* attribute handler for Int typed attributes
|
229 |
+
*
|
230 |
+
* @param int $pid
|
231 |
+
* : product id
|
232 |
+
* @param array $item
|
233 |
+
* : item to inges
|
234 |
+
* @param int $storeid
|
235 |
+
* : store for attribute value storage
|
236 |
+
* @param int $attrcode
|
237 |
+
* : attribute code
|
238 |
+
* @param array $attrdesc
|
239 |
+
* : attribute metadata
|
240 |
+
* @param mixed $ivalue
|
241 |
+
* : input value to import
|
242 |
+
* @return new int value to set
|
243 |
+
*
|
244 |
+
* Many attributes are int typed, so we need to handle all cases like :
|
245 |
+
* - select
|
246 |
+
* - tax id
|
247 |
+
* - boolean
|
248 |
+
* - status
|
249 |
+
* - visibility
|
250 |
+
*/
|
251 |
+
public function handleIntAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
252 |
+
{
|
253 |
+
$ovalue = $ivalue;
|
254 |
+
// default value exists, return it
|
255 |
+
$dval = $this->getDefaultValue($attrdesc, $ivalue);
|
256 |
+
if ($dval !== null)
|
257 |
+
{
|
258 |
+
return intval($dval);
|
259 |
+
}
|
260 |
+
|
261 |
+
$attid = $attrdesc["attribute_id"];
|
262 |
+
// if we've got a select type value
|
263 |
+
if ($attrdesc["frontend_input"] == "select")
|
264 |
+
{
|
265 |
+
// we need to identify its type since some have no options
|
266 |
+
switch ($attrdesc["source_model"])
|
267 |
+
{
|
268 |
+
// if its status, default to 1 (Enabled) if not correcly mapped
|
269 |
+
case "catalog/product_status":
|
270 |
+
if (!$this->checkInt($ivalue))
|
271 |
+
{
|
272 |
+
$ovalue = 1;
|
273 |
+
}
|
274 |
+
break;
|
275 |
+
// do not create options for boolean values tagged as select ,default to 0 if not correcly mapped
|
276 |
+
case "eav/entity_attribute_source_boolean":
|
277 |
+
if (!$this->checkInt($ivalue))
|
278 |
+
{
|
279 |
+
$ovalue = 0;
|
280 |
+
}
|
281 |
+
break;
|
282 |
+
// if visibility no options either,default to 4 if not correctly mapped
|
283 |
+
case "catalog/product_visibility":
|
284 |
+
if (!$this->checkInt($ivalue))
|
285 |
+
{
|
286 |
+
$ovalue = 4;
|
287 |
+
}
|
288 |
+
|
289 |
+
break;
|
290 |
+
// if it's tax_class, get tax class id from item value
|
291 |
+
case "tax/class_source_product":
|
292 |
+
$ovalue = $this->getTaxClassId($ivalue);
|
293 |
+
break;
|
294 |
+
// otherwise, standard option behavior
|
295 |
+
// get option id for value, create it if does not already exist
|
296 |
+
// do not insert if empty
|
297 |
+
default:
|
298 |
+
$exists = $this->currentItemExists();
|
299 |
+
if ($ivalue == "" && $exists)
|
300 |
+
{
|
301 |
+
return "__MAGMI_DELETE__";
|
302 |
+
}
|
303 |
+
$oids = $this->getOptionIds($attid, $storeid, array($ivalue));
|
304 |
+
$ovalue = $oids[0];
|
305 |
+
unset($oids);
|
306 |
+
break;
|
307 |
+
}
|
308 |
+
}
|
309 |
+
return $ovalue;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* attribute handler for "url_key" attribute
|
314 |
+
*
|
315 |
+
* @param int $pid
|
316 |
+
* : product id
|
317 |
+
* @param array $item
|
318 |
+
* : item to inges
|
319 |
+
* @param int $storeid
|
320 |
+
* : store for attribute value storage
|
321 |
+
* @param int $attrcode
|
322 |
+
* : attribute code
|
323 |
+
* @param array $attrdesc
|
324 |
+
* : attribute metadata
|
325 |
+
* @param mixed $ivalue
|
326 |
+
* : input value to import
|
327 |
+
* @return new int value to set
|
328 |
+
*
|
329 |
+
*/
|
330 |
+
public function handleUrl_keyAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
331 |
+
{
|
332 |
+
$cpev = $this->tablename("catalog_product_entity_varchar");
|
333 |
+
// find conflicting url keys
|
334 |
+
$urlk = trim($ivalue);
|
335 |
+
$exists = $this->currentItemExists();
|
336 |
+
$lst = array();
|
337 |
+
if ($urlk == "" && $exists)
|
338 |
+
{
|
339 |
+
return "__MAGMI_DELETE__";
|
340 |
+
}
|
341 |
+
// for existing product, check if we have already a value matching the current pattern
|
342 |
+
if ($exists)
|
343 |
+
{
|
344 |
+
$sql = "SELECT value FROM $cpev WHERE attribute_id=? AND entity_id=? AND value REGEXP ?";
|
345 |
+
$eurl = $this->selectone($sql, array($attrdesc["attribute_id"],$pid,$urlk . "(-\d+)?"), "value");
|
346 |
+
// we match wanted pattern, try finding conflicts with our current one
|
347 |
+
if ($eurl)
|
348 |
+
{
|
349 |
+
$urlk = $eurl;
|
350 |
+
$sql = "SELECT * FROM $cpev WHERE attribute_id=? AND entity_id!=? AND value=?";
|
351 |
+
$umatch = $urlk;
|
352 |
+
}
|
353 |
+
// no current value, so try inserting into target pattern list
|
354 |
+
else
|
355 |
+
{
|
356 |
+
|
357 |
+
$sql = "SELECT * FROM $cpev WHERE attribute_id=? AND entity_id!=? AND value REGEXP ?";
|
358 |
+
$umatch = $urlk . "(-\d+)?";
|
359 |
+
}
|
360 |
+
$lst = $this->selectAll($sql, array($attrdesc["attribute_id"],$pid,$umatch));
|
361 |
+
}
|
362 |
+
|
363 |
+
// all conflicting url keys
|
364 |
+
if (count($lst) > 0)
|
365 |
+
{
|
366 |
+
$urlk = $urlk . "-" . count($lst);
|
367 |
+
}
|
368 |
+
return $urlk;
|
369 |
+
}
|
370 |
+
|
371 |
+
/**
|
372 |
+
* attribute handler for Varchar typed attributes
|
373 |
+
*
|
374 |
+
* @param int $pid
|
375 |
+
* : product id
|
376 |
+
* @param array $item
|
377 |
+
* : item to inges
|
378 |
+
* @param int $storeid
|
379 |
+
* : store for attribute value storage
|
380 |
+
* @param int $attrcode
|
381 |
+
* : attribute code
|
382 |
+
* @param array $attrdesc
|
383 |
+
* : attribute metadata
|
384 |
+
* @param mixed $ivalue
|
385 |
+
* : input value to import
|
386 |
+
* @return new int value to set
|
387 |
+
*
|
388 |
+
* Special case for multiselect
|
389 |
+
*/
|
390 |
+
public function handleVarcharAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
|
391 |
+
{
|
392 |
+
$exists = $this->currentItemExists();
|
393 |
+
// Check store specific value & empty & new item => ignore
|
394 |
+
if ($storeid !== 0 && empty($ivalue) && !$exists)
|
395 |
+
{
|
396 |
+
return false;
|
397 |
+
}
|
398 |
+
// item exists , empty value, remove value, back to admin
|
399 |
+
if ($ivalue == "" && $exists)
|
400 |
+
{
|
401 |
+
return "__MAGMI_DELETE__";
|
402 |
+
}
|
403 |
+
// default value exists, return it
|
404 |
+
$dval = $this->getDefaultValue($attrdesc, $ivalue);
|
405 |
+
if ($dval !== null)
|
406 |
+
{
|
407 |
+
return $dval;
|
408 |
+
}
|
409 |
+
|
410 |
+
$ovalue = $ivalue;
|
411 |
+
$attid = $attrdesc["attribute_id"];
|
412 |
+
// --- Contribution From mennos , optimized by dweeves ----
|
413 |
+
// Added to support multiple select attributes
|
414 |
+
// (as far as i could figure out) always stored as varchars
|
415 |
+
// if it's a multiselect value
|
416 |
+
if ($attrdesc["frontend_input"] == "multiselect")
|
417 |
+
{
|
418 |
+
// if empty delete entry
|
419 |
+
if ($ivalue == "")
|
420 |
+
{
|
421 |
+
return "__MAGMI_DELETE__";
|
422 |
+
}
|
423 |
+
// magento uses "," as separator for different multiselect values
|
424 |
+
$sep = Magmi_Config::getInstance()->get("GLOBAL", "multiselect_sep", ",");
|
425 |
+
$multiselectvalues = explode($sep, $ivalue);
|
426 |
+
$oids = $this->getOptionIds($attid, $storeid, $multiselectvalues);
|
427 |
+
$ovalue = implode(",", $oids);
|
428 |
+
unset($oids);
|
429 |
+
}
|
430 |
+
|
431 |
+
return $ovalue;
|
432 |
+
}
|
433 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_generalimport_plugin.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("magmi_plugin.php");
|
3 |
+
|
4 |
+
abstract class Magmi_GeneralImportPlugin extends Magmi_Plugin
|
5 |
+
{
|
6 |
+
|
7 |
+
public function beforeImport()
|
8 |
+
{
|
9 |
+
return true;
|
10 |
+
}
|
11 |
+
|
12 |
+
public function afterImport()
|
13 |
+
{
|
14 |
+
return true;
|
15 |
+
}
|
16 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_item_processor.php
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class CustomItemProcessor
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
* This class enables to perform custom modifications on item
|
7 |
+
*
|
8 |
+
* class principle:
|
9 |
+
* methods should be called processItemXxx where Xxx is an import step of the Magmi_ProductImportEngine
|
10 |
+
*
|
11 |
+
* all processItemXxx methods are optional, you need only to define methods you need to implement
|
12 |
+
*
|
13 |
+
* processItemXxx signature are always the same
|
14 |
+
*
|
15 |
+
*
|
16 |
+
* processItemXxx($mmi,&$item,$params=null) where
|
17 |
+
*
|
18 |
+
* $mmi : reference to Magmi_Engine instance
|
19 |
+
* &$item : array reference to item
|
20 |
+
* $params : step dependent array, may be null
|
21 |
+
*
|
22 |
+
* processItemXxx method always return a boolean value , return false if you want to break mmi processing for item
|
23 |
+
*
|
24 |
+
* current available import steps:
|
25 |
+
* beforeId => method processItemBeforeId , called before item is identified, just after loading csv values for item
|
26 |
+
* $params : null
|
27 |
+
*
|
28 |
+
*
|
29 |
+
* afterId => method processItemAfterId , called after item is identified or created in magento
|
30 |
+
* $params : array("product_id"=><magento product id>)
|
31 |
+
*
|
32 |
+
* exception => method processItemException , called when mmi processing caused an exception (even customItemProcessor thrown exception)
|
33 |
+
*$params : array("exception"=><exception instance thrown>)
|
34 |
+
*
|
35 |
+
*
|
36 |
+
*/
|
37 |
+
require_once("magmi_generalimport_plugin.php");
|
38 |
+
abstract class Magmi_ItemProcessor extends Magmi_GeneralImportPlugin
|
39 |
+
{
|
40 |
+
/**
|
41 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
42 |
+
* @param MagentoMassImporter $mmi : reference to mass importer (convenient to perform database operations)
|
43 |
+
* @param unknown_type $item : modifiable reference to item before import
|
44 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
45 |
+
* @return bool :
|
46 |
+
* true if you want the item to be imported after your custom processing
|
47 |
+
* false if you want to skip item import after your processing
|
48 |
+
*/
|
49 |
+
|
50 |
+
|
51 |
+
public function processItemBeforeId(&$item,$params=null)
|
52 |
+
{
|
53 |
+
/* example code 1 */
|
54 |
+
/* i've added some non item attribute values in my csv (cp_id,cp_price) but
|
55 |
+
* these values are meant to be inserted into a custom module table
|
56 |
+
* so , i get the following code (commented)
|
57 |
+
*/
|
58 |
+
|
59 |
+
/*
|
60 |
+
//if my special column cp_id exists
|
61 |
+
if(isset($item['cp_id']))
|
62 |
+
{
|
63 |
+
//if its value is not empty
|
64 |
+
if($item['cp_id']!="")
|
65 |
+
{
|
66 |
+
//ask mmi for custom module table name (takes into account table prefix
|
67 |
+
$tname=$mmi->tablename("book_categoryprice");
|
68 |
+
//parameterized sql for insert (ignore doubles)
|
69 |
+
$sql="INSERT IGNORE INTO $tname (cp_id,price) VALUES (?,?)";
|
70 |
+
$data=array($item["cp_id"],$item["cp_price"]);
|
71 |
+
//ask mmi to perform insert
|
72 |
+
$mmi->insert($sql,$data);
|
73 |
+
}
|
74 |
+
//remove my special columns from item
|
75 |
+
unset($item["cp_id"]);
|
76 |
+
unset($item["cp_price"]);
|
77 |
+
}*/
|
78 |
+
|
79 |
+
/** example code 2 **/
|
80 |
+
/*
|
81 |
+
* //if we have qty column & are in create mode & reset, do not import items with 0 qty
|
82 |
+
if(isset($item['qty']) && $item['qty']==0 && $mmi->mode=="create" && $mmi->reset)
|
83 |
+
{
|
84 |
+
return false;
|
85 |
+
}
|
86 |
+
* /
|
87 |
+
*/
|
88 |
+
//return true , enable item processing
|
89 |
+
return true;
|
90 |
+
}
|
91 |
+
|
92 |
+
public function processItemAfterId(&$item,$params=null)
|
93 |
+
{
|
94 |
+
return true;
|
95 |
+
}
|
96 |
+
|
97 |
+
/*
|
98 |
+
public function processItemException($mmi,&$item,$params=null)
|
99 |
+
{
|
100 |
+
|
101 |
+
}*/
|
102 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_plugin.php
ADDED
@@ -0,0 +1,337 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once ("magmi_config.php");
|
3 |
+
require_once ("magmi_mixin.php");
|
4 |
+
|
5 |
+
class Magmi_PluginConfig extends ProfileBasedConfig
|
6 |
+
{
|
7 |
+
protected $_prefix;
|
8 |
+
protected $_conffile;
|
9 |
+
|
10 |
+
public function __construct($pname, $profile = null)
|
11 |
+
{
|
12 |
+
$this->_prefix = $pname;
|
13 |
+
parent::__construct("$this->_prefix.conf", $profile);
|
14 |
+
}
|
15 |
+
|
16 |
+
public function getConfDir()
|
17 |
+
{
|
18 |
+
return dirname($this->_confname);
|
19 |
+
}
|
20 |
+
|
21 |
+
public function load($name = null)
|
22 |
+
{
|
23 |
+
$cname = ($name == null ? $this->_confname : $name);
|
24 |
+
if (file_exists($cname))
|
25 |
+
{
|
26 |
+
parent::load($cname);
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getIniStruct($arr)
|
31 |
+
{
|
32 |
+
$conf = array();
|
33 |
+
foreach ($arr as $k => $v)
|
34 |
+
{
|
35 |
+
$k = $this->_prefix . ":" . $k;
|
36 |
+
list($section,$value) = explode(":", $k, 2);
|
37 |
+
if (!isset($conf[$section]))
|
38 |
+
{
|
39 |
+
$conf[$section] = array();
|
40 |
+
}
|
41 |
+
$conf[$section][$value] = $v;
|
42 |
+
}
|
43 |
+
return $conf;
|
44 |
+
}
|
45 |
+
|
46 |
+
public function getConfig()
|
47 |
+
{
|
48 |
+
return parent::getsection($this->_prefix);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
class Magmi_PluginOptionsPanel
|
53 |
+
{
|
54 |
+
private $_plugin;
|
55 |
+
private $_defaulthtml = "";
|
56 |
+
private $_file = null;
|
57 |
+
|
58 |
+
public function __construct($pinst, $file = null)
|
59 |
+
{
|
60 |
+
$this->_plugin = $pinst;
|
61 |
+
$this->_file = ($file == null ? "options_panel.php" : $file);
|
62 |
+
$this->initDefaultHtml();
|
63 |
+
}
|
64 |
+
|
65 |
+
public function getFile()
|
66 |
+
{
|
67 |
+
return $this->_file;
|
68 |
+
}
|
69 |
+
|
70 |
+
public final function initDefaultHtml()
|
71 |
+
{
|
72 |
+
$panelfile = dirname(__FILE__) . "/magmi_default_options_panel.php";
|
73 |
+
ob_start();
|
74 |
+
require ($panelfile);
|
75 |
+
$this->_defaulthtml = ob_get_contents();
|
76 |
+
ob_end_clean();
|
77 |
+
}
|
78 |
+
|
79 |
+
public function getHtml()
|
80 |
+
{
|
81 |
+
$plugin = $this->_plugin;
|
82 |
+
$pdir = Magmi_PluginHelper::getInstance()->getPluginDir($this->_plugin);
|
83 |
+
$panelfile = "$pdir/" . $this->getFile();
|
84 |
+
$content = "";
|
85 |
+
if (!file_exists($panelfile))
|
86 |
+
{
|
87 |
+
$content = $this->_defaulthtml;
|
88 |
+
}
|
89 |
+
else
|
90 |
+
{
|
91 |
+
ob_start();
|
92 |
+
require ($panelfile);
|
93 |
+
$content = ob_get_contents();
|
94 |
+
ob_end_clean();
|
95 |
+
}
|
96 |
+
return $content;
|
97 |
+
}
|
98 |
+
|
99 |
+
public function __call($data, $arg)
|
100 |
+
{
|
101 |
+
return call_user_func_array(array($this->_plugin,$data), $arg);
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
abstract class Magmi_Plugin extends Magmi_Mixin
|
106 |
+
{
|
107 |
+
protected $_class;
|
108 |
+
protected $_plugintype;
|
109 |
+
protected $_plugindir;
|
110 |
+
protected $_config;
|
111 |
+
protected $_magmiconfig;
|
112 |
+
protected $_pluginmeta;
|
113 |
+
|
114 |
+
public function __construct()
|
115 |
+
{}
|
116 |
+
|
117 |
+
public function pluginDocUrl($urlk)
|
118 |
+
{
|
119 |
+
return "http://wiki.magmi.org/index.php?title=" . $urlk;
|
120 |
+
}
|
121 |
+
|
122 |
+
public function getParam($pname, $default = null)
|
123 |
+
{
|
124 |
+
return (isset($this->_params[$pname]) && $this->_params[$pname] != "") ? $this->_params[$pname] : $default;
|
125 |
+
}
|
126 |
+
|
127 |
+
public function setParam($pname, $value)
|
128 |
+
{
|
129 |
+
$this->_params[$pname] = $value;
|
130 |
+
}
|
131 |
+
|
132 |
+
public function fixListParam($pvalue)
|
133 |
+
{
|
134 |
+
$iarr = explode(",", $pvalue);
|
135 |
+
$oarr = array();
|
136 |
+
foreach ($iarr as $v)
|
137 |
+
{
|
138 |
+
if ($v != "")
|
139 |
+
{
|
140 |
+
$oarr[] = $v;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
$val = implode(",", $oarr);
|
144 |
+
unset($iarr);
|
145 |
+
unset($oarr);
|
146 |
+
return $val;
|
147 |
+
}
|
148 |
+
|
149 |
+
public function getPluginParamNames()
|
150 |
+
{
|
151 |
+
return array();
|
152 |
+
}
|
153 |
+
|
154 |
+
public function getPluginInfo()
|
155 |
+
{
|
156 |
+
return array("name"=>$this->getPluginName(),"version"=>$this->getPluginVersion(),
|
157 |
+
"author"=>$this->getPluginAuthor(),"url"=>$this->getPluginUrl());
|
158 |
+
}
|
159 |
+
|
160 |
+
public function getPluginUrl()
|
161 |
+
{
|
162 |
+
return null;
|
163 |
+
}
|
164 |
+
|
165 |
+
public function getPluginVersion()
|
166 |
+
{
|
167 |
+
return null;
|
168 |
+
}
|
169 |
+
|
170 |
+
public function getPluginName()
|
171 |
+
{
|
172 |
+
return null;
|
173 |
+
}
|
174 |
+
|
175 |
+
public function getPluginAuthor()
|
176 |
+
{
|
177 |
+
return null;
|
178 |
+
}
|
179 |
+
|
180 |
+
public function log($data, $type = 'std', $useprefix = true)
|
181 |
+
{
|
182 |
+
$pinf = $this->getPluginInfo();
|
183 |
+
if ($useprefix)
|
184 |
+
{
|
185 |
+
$data = "{$pinf["name"]} v{$pinf["version"]} - " . $data;
|
186 |
+
}
|
187 |
+
$this->_caller_log($data, "plugin;$this->_class;$type");
|
188 |
+
}
|
189 |
+
|
190 |
+
public function pluginHello()
|
191 |
+
{
|
192 |
+
$info = $this->getPluginInfo();
|
193 |
+
$hello = array(!isset($info["name"]) ? "" : $info["name"]);
|
194 |
+
$hello[] = !isset($info["version"]) ? "" : $info["version"];
|
195 |
+
$hello[] = !isset($info["author"]) ? "" : $info["author"];
|
196 |
+
$hello[] = !isset($info["url"]) ? "" : $info["url"];
|
197 |
+
$hellostr = implode("-", $hello);
|
198 |
+
$base = get_parent_class($this);
|
199 |
+
$this->log("$hellostr ", "pluginhello", false);
|
200 |
+
}
|
201 |
+
|
202 |
+
public function initialize($params)
|
203 |
+
{}
|
204 |
+
|
205 |
+
public function getConfig()
|
206 |
+
{
|
207 |
+
return $this->_config;
|
208 |
+
}
|
209 |
+
|
210 |
+
public function getMagmiConfig()
|
211 |
+
{
|
212 |
+
return $this->_magmiconfig;
|
213 |
+
}
|
214 |
+
|
215 |
+
public final function pluginInit($mmi, $meta, $params = null, $doinit = true, $profile = null)
|
216 |
+
{
|
217 |
+
$this->bind($mmi);
|
218 |
+
$this->_pluginmeta = $meta;
|
219 |
+
$this->_class = get_class($this);
|
220 |
+
$this->_config = new Magmi_PluginConfig(get_class($this), $profile);
|
221 |
+
$this->_config->load();
|
222 |
+
$this->_magmiconfig = Magmi_Config::getInstance();
|
223 |
+
|
224 |
+
$this->_params = ($params != null ? array_merge($this->_config->getConfig(), $params) : $this->_config->getConfig());
|
225 |
+
|
226 |
+
if (isset($mmi))
|
227 |
+
{
|
228 |
+
$this->pluginHello();
|
229 |
+
}
|
230 |
+
|
231 |
+
if ($doinit)
|
232 |
+
{
|
233 |
+
$this->initialize($this->_params);
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
public function getPluginParamsNoCurrent($params)
|
238 |
+
{
|
239 |
+
$arr = array();
|
240 |
+
$paramkeys = $this->getPluginParamNames();
|
241 |
+
foreach ($paramkeys as $pk)
|
242 |
+
{
|
243 |
+
if (isset($params[$pk]))
|
244 |
+
{
|
245 |
+
$arr[$pk] = $params[$pk];
|
246 |
+
}
|
247 |
+
else
|
248 |
+
{
|
249 |
+
$arr[$pk] = 0;
|
250 |
+
}
|
251 |
+
}
|
252 |
+
return $arr;
|
253 |
+
}
|
254 |
+
|
255 |
+
public function getPluginParams($params)
|
256 |
+
{
|
257 |
+
$arr = array();
|
258 |
+
$paramkeys = $this->getPluginParamNames();
|
259 |
+
foreach ($paramkeys as $pk)
|
260 |
+
{
|
261 |
+
if (isset($params[$pk]))
|
262 |
+
{
|
263 |
+
$arr[$pk] = $params[$pk];
|
264 |
+
}
|
265 |
+
else
|
266 |
+
{
|
267 |
+
if (isset($this->_params[$pk]))
|
268 |
+
{
|
269 |
+
$arr[$pk] = $this->_params[$pk];
|
270 |
+
}
|
271 |
+
}
|
272 |
+
}
|
273 |
+
return $arr;
|
274 |
+
}
|
275 |
+
|
276 |
+
public function persistParams($plist)
|
277 |
+
{
|
278 |
+
if (count($plist) > 0)
|
279 |
+
{
|
280 |
+
$this->_config->setPropsFromFlatArray($plist);
|
281 |
+
return $this->_config->save();
|
282 |
+
}
|
283 |
+
return true;
|
284 |
+
}
|
285 |
+
|
286 |
+
public function getOptionsPanel($file = null)
|
287 |
+
{
|
288 |
+
return new Magmi_PluginOptionsPanel($this, $file);
|
289 |
+
}
|
290 |
+
|
291 |
+
public function getShortDescription()
|
292 |
+
{
|
293 |
+
$panel = $this->getOptionsPanel()->getHtml();
|
294 |
+
$info = null;
|
295 |
+
if (preg_match('|<div class="plugin_description">(.*?)</div>|smi', $panel, $match))
|
296 |
+
{
|
297 |
+
|
298 |
+
$info = $match[1];
|
299 |
+
$delims = array(".",":");
|
300 |
+
foreach ($delims as $delim)
|
301 |
+
{
|
302 |
+
$p = strpos($info, $delim);
|
303 |
+
if ($p !== false)
|
304 |
+
{
|
305 |
+
$info = substr($info, 0, $p);
|
306 |
+
break;
|
307 |
+
}
|
308 |
+
}
|
309 |
+
}
|
310 |
+
return $info;
|
311 |
+
}
|
312 |
+
|
313 |
+
static public function getCategory()
|
314 |
+
{
|
315 |
+
return "common";
|
316 |
+
}
|
317 |
+
|
318 |
+
public function getPluginDir()
|
319 |
+
{
|
320 |
+
return $this->_pluginmeta["dir"];
|
321 |
+
}
|
322 |
+
|
323 |
+
public function getPluginMeta()
|
324 |
+
{
|
325 |
+
return $this->_pluginmeta;
|
326 |
+
}
|
327 |
+
|
328 |
+
public function getPluginClass()
|
329 |
+
{
|
330 |
+
return $this->_class;
|
331 |
+
}
|
332 |
+
|
333 |
+
public function isRunnable()
|
334 |
+
{
|
335 |
+
return array(true,"");
|
336 |
+
}
|
337 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/plugins/inc/magmi_utility_plugin.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Magmi_UtilityPlugin extends Magmi_Plugin
|
4 |
+
{
|
5 |
+
|
6 |
+
public function runUtility()
|
7 |
+
{
|
8 |
+
// Put Running code
|
9 |
+
}
|
10 |
+
|
11 |
+
public function getWarning()
|
12 |
+
{
|
13 |
+
return null;
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Osf/IngramMicro/lib/magmi/state/magmistate
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
idle
|
app/code/community/Osf/IngramMicro/lib/magmi/state/progress.txt
ADDED
File without changes
|
app/code/community/Osf/IngramMicro/lib/magmi/state/timings.txt
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
TIMING CATEGORY:db
|
3 |
+
--------------------------------
|
4 |
+
Phase:beforeImport
|
5 |
+
- Class:Magmi_ProductImportEngine :0.01 - Class:Magmi_OptimizerPlugin :0.01
|
6 |
+
Phase:indb
|
7 |
+
- Class:Magmi_ProductImportEngine :0.21 - Class:CategoryImporter :0.21
|
8 |
+
Phase:startImport
|
9 |
+
|
10 |
+
Phase:processColumnList
|
11 |
+
- Class:Magmi_ProductImportEngine :0.01
|
12 |
+
Phase:processItemBeforeId
|
13 |
+
|
14 |
+
Phase:processItemAfterId
|
15 |
+
|
16 |
+
Phase:processItemAfterImport
|
17 |
+
|
18 |
+
Phase:endImport
|
19 |
+
|
20 |
+
Phase:afterImport
|
21 |
+
|
22 |
+
TIMING CATEGORY:global
|
23 |
+
--------------------------------
|
24 |
+
Phase:beforeImport
|
25 |
+
- Class:Magmi_ProductImportEngine :0.01 - Class:Magmi_OptimizerPlugin :0.01
|
26 |
+
Phase:startImport
|
27 |
+
|
28 |
+
Phase:processColumnList
|
29 |
+
- Class:Magmi_ProductImportEngine :0.01
|
30 |
+
Phase:processItemBeforeId
|
31 |
+
|
32 |
+
Phase:processItemAfterId
|
33 |
+
|
34 |
+
Phase:processItemAfterImport
|
35 |
+
|
36 |
+
Phase:endImport
|
37 |
+
|
38 |
+
Phase:afterImport
|
39 |
+
|
40 |
+
TIMING CATEGORY:line
|
41 |
+
--------------------------------
|
42 |
+
Phase:processItemBeforeId
|
43 |
+
|
44 |
+
Phase:processItemAfterId
|
45 |
+
|
46 |
+
Phase:processItemAfterImport
|
47 |
+
|
48 |
+
Phase:endImport
|
49 |
+
|
50 |
+
Phase:afterImport
|
app/code/community/Osf/IngramMicro/lib/magmi/state/trace.txt
ADDED
File without changes
|
app/code/community/Osf/IngramMicro/sql/osf_ingrammicro_setup/install-0.0.1.php
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
$installer = $this;
|
4 |
+
$installer->startSetup();
|
5 |
+
|
6 |
+
//Create queue table to store ingrammicro failed request for retry.
|
7 |
+
$installer->getConnection()->dropTable($installer->getTable('osf_ingrammicro_queue'));
|
8 |
+
$table = $installer->getConnection()
|
9 |
+
->newTable($installer->getTable('osf_ingrammicro_queue'))
|
10 |
+
->addColumn('queue_id', Varien_Db_Ddl_Table::TYPE_INTEGER, 11, array(
|
11 |
+
'identity' => true,
|
12 |
+
'unsigned' => true,
|
13 |
+
'nullable' => false,
|
14 |
+
'primary' => true,
|
15 |
+
)
|
16 |
+
)
|
17 |
+
->addColumn('order_id', Varien_Db_Ddl_Table::TYPE_INTEGER, 11, array(
|
18 |
+
'nullable' => false
|
19 |
+
)
|
20 |
+
)
|
21 |
+
->addColumn('po_id', Varien_Db_Ddl_Table::TYPE_INTEGER, 11)
|
22 |
+
->addColumn('order_xml', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
|
23 |
+
'nullable' => false
|
24 |
+
)
|
25 |
+
)
|
26 |
+
->addColumn('retry', Varien_Db_Ddl_Table::TYPE_INTEGER, 2)
|
27 |
+
->addColumn('prev_error', Varien_Db_Ddl_Table::TYPE_TEXT);
|
28 |
+
|
29 |
+
$installer->getConnection()->createTable($table);
|
30 |
+
|
31 |
+
//Create a table to store category mapping
|
32 |
+
$installer->getConnection()->dropTable($installer->getTable('osf_ingrammicro_catmap'));
|
33 |
+
$table = $installer->getConnection()
|
34 |
+
->newTable($installer->getTable('osf_ingrammicro_catmap'))
|
35 |
+
->addColumn('catmap_id', Varien_Db_Ddl_Table::TYPE_INTEGER, 11, array(
|
36 |
+
'identity' => true,
|
37 |
+
'unsigned' => true,
|
38 |
+
'nullable' => false,
|
39 |
+
'primary' => true,
|
40 |
+
)
|
41 |
+
)
|
42 |
+
->addColumn('ingrammicro_category', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
|
43 |
+
'nullable' => false
|
44 |
+
)
|
45 |
+
)
|
46 |
+
->addColumn('magento_category', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
|
47 |
+
'nullable' => false
|
48 |
+
)
|
49 |
+
);
|
50 |
+
$installer->getConnection()->createTable($table);
|
51 |
+
|
52 |
+
//Add new product attributes
|
53 |
+
$attr_installer = Mage::getResourceModel('catalog/setup', 'catalog_setup');
|
54 |
+
|
55 |
+
//Create new Vendor attribute
|
56 |
+
$attr_installer->addAttribute('catalog_product', 'osf_product_vendor', array(
|
57 |
+
'type' => 'varchar',
|
58 |
+
'backend' => '',
|
59 |
+
'frontend' => '',
|
60 |
+
'label' => 'Vendor',
|
61 |
+
'input' => 'text',
|
62 |
+
'class' => '',
|
63 |
+
'source' => 'catalog/product_attribute_source_layout',
|
64 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
65 |
+
'visible' => true,
|
66 |
+
'required' => false,
|
67 |
+
'user_defined' => false,
|
68 |
+
'default' => '',
|
69 |
+
'searchable' => false,
|
70 |
+
'filterable' => false,
|
71 |
+
'comparable' => false,
|
72 |
+
'visible_on_front' => false,
|
73 |
+
'unique' => false,
|
74 |
+
'group' => 'General'
|
75 |
+
));
|
76 |
+
|
77 |
+
//Create new Cost attribute
|
78 |
+
$attr_installer->addAttribute('catalog_product', 'osf_product_cost', array(
|
79 |
+
'type' => 'varchar',
|
80 |
+
'backend' => '',
|
81 |
+
'frontend' => '',
|
82 |
+
'label' => 'Cost',
|
83 |
+
'input' => 'text',
|
84 |
+
'class' => '',
|
85 |
+
'source' => 'catalog/product_attribute_source_layout',
|
86 |
+
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
87 |
+
'visible' => true,
|
88 |
+
'required' => false,
|
89 |
+
'user_defined' => false,
|
90 |
+
'default' => '',
|
91 |
+
'searchable' => false,
|
92 |
+
'filterable' => false,
|
93 |
+
'comparable' => false,
|
94 |
+
'visible_on_front' => false,
|
95 |
+
'unique' => false,
|
96 |
+
'group' => 'General'
|
97 |
+
));
|
98 |
+
|
99 |
+
$installer->endSetup();
|
app/design/adminhtml/default/default/template/osf/ingrammicro/system/config/button.phtml
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<?php echo $this->getButtonHtml() ?>
|
app/etc/modules/Osf_IngramMicro.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Osf_IngramMicro>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Osf_IngramMicro>
|
8 |
+
</modules>
|
9 |
+
</config>
|
package.xml
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>OSF_Integrator_for_IngramMicro</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://www.osf-commerce.com/magento-products-lite-software-license-agreement">End User License Agreement (EULA)</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Automated flow for IngramMicro integration from product import to ship notification</summary>
|
10 |
+
<description>The integrator will create a bridge between Magento and IngramMicro and will allow the automation of importing products, placing orders and receiving shipping notification.</description>
|
11 |
+
<notes>1.0.0</notes>
|
12 |
+
<authors><author><name>OSF Global</name><user>OSF_Global</user><email>chris.hooven@osf-global.com</email></author></authors>
|
13 |
+
<date>2015-11-11</date>
|
14 |
+
<time>10:54:22</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="Osf"><dir name="IngramMicro"><dir name="Block"><dir name="Adminhtml"><dir name="Shipments"><file name="Grid.php" hash="90a9883b4d34f62bbb7edbbb0313d821"/><dir name="Renderer"><file name="Status.php" hash="00289fc379b98cf0150acb74a959255b"/></dir></dir><file name="Shipments.php" hash="fab8aa9b392feb2bb3178da702cbc93c"/><dir name="System"><dir name="Config"><dir name="Frontend"><file name="Button.php" hash="abca04bd5608478088e7a9d54f4c611f"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Connect.php" hash="24b9438a70c2e8b0d7736424e51307d7"/><file name="Data.php" hash="49c68986223288df1eeb8af523c24aea"/><file name="Error.php" hash="ee81b6d42780591e04cc27e07b3e664a"/><file name="Ftp.php" hash="7882046b675ec5a75440cdc450580089"/></dir><file name="LICENSE.txt" hash="279935a07ba225ee0b2199830ddb61b7"/><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Backend"><file name="Catmap.php" hash="8b7bfcb87b1a4139d241a9bb14db3670"/></dir></dir></dir></dir><file name="Callback.php" hash="40897daa43c8d000ac1a582a50b650a9"/><file name="Catmap.php" hash="6996c5f0af7b4db5be2c123d824723f7"/><file name="Import.php" hash="23eb198851054c3c7e6891a5f0b40ca0"/><file name="Observer.php" hash="6ec33db9c0b050e120468ea7444ac111"/><file name="Order.php" hash="dba7fcec3f420b61ef950c5c8b92afad"/><file name="Queue.php" hash="bd1fd5db3c6bc836b8634ec040913a24"/><dir name="Resource"><dir name="Catmap"><file name="Collection.php" hash="318422d75b1c659351ce16bd0cf6635b"/></dir><file name="Catmap.php" hash="b18a9fd87fa5d1729fbf593d57d8836e"/><dir name="Queue"><file name="Collection.php" hash="aa0609c53a3d1f4c415182013541993a"/></dir><file name="Queue.php" hash="08baae9474276f1def3901f9b813dc76"/></dir><file name="Shipnotice.php" hash="bde45481a136696577fb6c473d5a0b10"/><file name="Source.php" hash="480e6caa1eebbc17ad21e8bf0566c5fd"/></dir><dir name="controllers"><file name="CallbackController.php" hash="e9527fcd4875df939c83f074010f6fca"/><file name="IndexController.php" hash="a3af0459e577e33ffbd4d4da433cc634"/></dir><dir name="etc"><file name="config.xml" hash="90e9640e35e3a2a2d0e904ac1c8e3efb"/><file name="system.xml" hash="e3e9b7d813b92733a01d016713a37f61"/></dir><dir name="lib"><dir name="magmi"><dir name="conf"><dir name="Ingrammicro"><file name="CategoryImporter.conf" hash="5c3e33ed9b67624672126b92882eaa73"/><file name="plugins.conf" hash="e6519fcee4d2728395d033df9ba84125"/></dir></dir><dir name="engines"><file name="magmi_productimportengine.php" hash="7066c271ced64c2cf67031e390247de7"/><file name="magmi_utilityengine.php" hash="7f067952d55311366478c612414c6631"/></dir><dir name="inc"><file name="dbhelper.class.php" hash="94409c26f0c0028a37dc14e0c84cf1a8"/><file name="fshelper.php" hash="21e0af81fee60df5b57b3f6e2627f132"/><file name="license.txt" hash="d69f02f4db9d64af32ac1a390d2a9574"/><file name="magmi_config.php" hash="987ec1cfb8675d5021a82feb789382f3"/><file name="magmi_defs.php" hash="dd8dc3e28ad013f72d96bd70cdaa172a"/><file name="magmi_engine.php" hash="87f7b2f6f28a87ad396d615a3822034d"/><file name="magmi_loggers.php" hash="136899bc06778c453131cb31e2728b4f"/><file name="magmi_mixin.php" hash="81160f5763dad16cc24b24befa2b9006"/><file name="magmi_pluginhelper.php" hash="7b4473bf363c531a55685fb0a1384ca1"/><file name="magmi_statemanager.php" hash="ac263e171783d012e346bc4a055d5fe5"/><file name="magmi_utils.php" hash="116b76c5138b46880dd4610b8f4df4ba"/><file name="magmi_valueparser.php" hash="a7278234dbba18aaa1d95eb2affdd701"/><file name="magmi_version.php" hash="43990cba40a2ae4ef4d7c26014dd5a0e"/><file name="properties.php" hash="9760558afed0628cc77a998176aa4479"/><file name="remotefilegetter.php" hash="fd8ac3bbf7c6c9c81817943affb1fefa"/><file name="timecounter.php" hash="9129bcc5a6c3775b6ad67752ae6177ad"/></dir><dir name="integration"><dir name="inc"><file name="magmi_datapump.php" hash="30a9158507970f4de6c768e0ed435c4c"/><file name="magmi_datapumpdatasource.php" hash="2c53fc5ed713ac33985f9a21d35a463d"/><file name="productimport_datapump.php" hash="8aa57b96a086980d85beb7a64ddbebbd"/><file name="pumpfactory.ini" hash="b4beac3e561fcf91a416eb52c76ce4e3"/></dir></dir><dir name="plugins"><dir name="base"><dir name="general"><dir name="optimizer"><file name="magmi_optimizer_plugin.php" hash="b281ad179395bc0268f2f707d5d3aec8"/></dir><dir name="reindex"><file name="magmi_reindexing_plugin.php" hash="fd93bce1a34cbede2c9e14a120bfd3d9"/><file name="options_panel.php" hash="679a5734ebae9f78784dc41f70e81091"/></dir></dir><dir name="itemprocessors"><dir name="columnmapper"><file name="000_columnmapper.php" hash="6a6319cdcd901dbe71b0647af7da4066"/><file name="options_panel.php" hash="34a80720a222e56fe93a09711ec45c0b"/></dir><dir name="defaultvalues"><file name="00_default_values.php" hash="54a78a56e903f93b384c6aa2e3bf73bb"/><file name="options_panel.php" hash="0969daa0f962643ac8f29c768c47a42b"/></dir><dir name="genericmapper"><file name="02_genericmapper.php" hash="2ea9614850dfb8e4abbc70aaa6f194b2"/><dir name="mappings"><dir name="default"><file name="__common__.csv" hash="dc827d5ffcabc221f6a9f31b7243131e"/><file name="backorders.csv" hash="ed3e51ef942051705c60f13d62fa87c6"/><file name="country_of_manufacture.csv" hash="e7127d7c0efdadfc342d473a582b014d"/><file name="msrp_display_actual_price_type.csv" hash="baadba2fda05c60d7c951e5b1dd71663"/><file name="msrp_enabled.csv" hash="a6f428cbbfcae861814dd221691048eb"/><file name="options_container.csv" hash="bb84f94e68900c1aafc66ce2c2461d06"/><file name="page_layout.csv" hash="0f6ac4af46d4090cb22497d172bad2f8"/><file name="status.csv" hash="dc5569042656c4163fea1cd74e8ed6d8"/><file name="tax_class_id.csv" hash="af2b19dd979a0b2687d4c7d770a454f9"/><file name="visibility.csv" hash="462fe1effcdb1ab3942677a011019f15"/></dir></dir><file name="options_panel.php" hash="80b72a8e69565645d6693e19f6f528b0"/></dir><dir name="importlimiter"><file name="01_importlimiter.php" hash="409021fbca5d3daf05f300f248d6ac75"/><file name="options_panel.php" hash="f7a8fb87d5f3e25e49c0b0db2198d852"/></dir><dir name="productdeleter"><file name="options_panel.php" hash="1f892375905523d7c2de3d3a12277982"/><file name="productdeleter.php" hash="6c726a42aa14cdad8c3e98c5ec90b327"/></dir><dir name="skufinder"><file name="001_skufinder.php" hash="a5102da1e8c459f2205fb151c177b133"/><file name="options_panel.php" hash="61e2df0dd9dbe17aa8ceb26925cd6aa5"/></dir></dir></dir><dir name="extra"><dir name="itemprocessors"><dir name="categories"><file name="categoryimport.php" hash="37bb8f156389e9df77d897f674025790"/><file name="options_panel.php" hash="d1e3c6ac7aad5c9903b9c1806a9b27ab"/></dir><dir name="customoptions"><file name="options_panel.php" hash="cb170b6febd4f89d37d0cf94c669c415"/><file name="pablo_customoptions.php" hash="61c87a9de84c5ddff5cd848447f3c667"/></dir><dir name="downloadable"><file name="downloadableprocessor.php" hash="97abc5b2b741d1c7431d38c078ed39d9"/><file name="options_panel.php" hash="e92ca7007d261fd3075371fdeb9eee9f"/></dir><dir name="imageprocessor"><file name="imageitattributeemprocessor.php" hash="9fbe8191d6220e3a38c62124389b4391"/><file name="options_panel.php" hash="6c2c15de53978198bcb9c44806661035"/></dir><dir name="itemindexer"><file name="options_panel.php" hash="bad523edf62dbf69d717df0e155096b4"/><file name="otfindexer.php" hash="733090472a67622aac805c1d6b23caba"/></dir><dir name="valuereplacer"><file name="03_valuereplacer.php" hash="b232c5c1caa4269fc12bd558ed441439"/><dir name="helper"><file name="remapper.php" hash="1247c973a4446aa765c3c97ad1ef481f"/></dir><file name="options_panel.php" hash="46093fb00f1a3d5793729386ef692f6d"/></dir><dir name="valuetrim"><file name="options_panel.php" hash="aa01db3219e7261da815b6c4a93c6592"/><file name="valuetrimmer.php" hash="52b3d04d830b1c763e877fc3a0f22d36"/></dir></dir><file name="obsolete.txt" hash="605e6dae72012017068005ca95cfb362"/></dir><dir name="inc"><file name="magmi_datasource.php" hash="174841315143e16ca73493babb9d27b5"/><file name="magmi_default_options_panel.php" hash="b35c690a790c77b97124c3bd395b176d"/><file name="magmi_defaultattributehandler.php" hash="f9fbf6c7d7925b7df55c73bae186df2f"/><file name="magmi_generalimport_plugin.php" hash="b45f85bbe04c142f9525cb7ffd82e65f"/><file name="magmi_item_processor.php" hash="1bd368a6970940206724284a299f028b"/><file name="magmi_plugin.php" hash="ab5093604a01e49d152076e4d8b1447a"/><file name="magmi_utility_plugin.php" hash="33760af242dcc0796f9595e9809aae06"/></dir></dir><dir name="state"><file name="magmistate" hash="ec2f993aec2c27fc750119ab17b16cdb"/><file name="progress.txt" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="timings.txt" hash="47ed5d57f09ed7678d663b4f5e72a307"/><file name="trace.txt" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></dir></dir><dir name="sql"><dir name="osf_ingrammicro_setup"><file name="install-0.0.1.php" hash="bd79cff7869306d62cc7ff363ba84752"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="osf"><dir name="ingrammicro"><dir name="system"><dir name="config"><file name="button.phtml" hash="fb5ab610c535e7a268195d806abbe0bd"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Osf_IngramMicro.xml" hash="0901151738c906b724968bf413112a88"/></dir></target></contents>
|
16 |
+
<compatible/>
|
17 |
+
<dependencies><required><php><min>5.4.0</min><max>5.6.14</max></php></required></dependencies>
|
18 |
+
</package>
|