Version Notes
First public release
Download this release
Release Info
Developer | Fabrizio Balliano |
Extension | magento-full-catalog-translate |
Version | 0.2.0 |
Comparing to | |
See all releases |
Version 0.2.0
- app/code/community/Fballiano/FullCatalogTranslate/Helper/Data.php +45 -0
- app/code/community/Fballiano/FullCatalogTranslate/etc/adminhtml.xml +22 -0
- app/code/community/Fballiano/FullCatalogTranslate/etc/config.xml +30 -0
- app/code/community/Fballiano/FullCatalogTranslate/etc/system.xml +45 -0
- app/code/community/Fballiano/FullCatalogTranslate/sql/fballiano_fullcatalogtranslate_setup/install-0.1.0.php +52 -0
- app/etc/modules/Fballiano_FullCatalogTranslate.xml +12 -0
- lib/Magmi/ReleaseNotes.txt +67 -0
- lib/Magmi/conf/magmi.ini +2 -0
- lib/Magmi/conf/plugins.conf +0 -0
- lib/Magmi/engines/magmi_productimportengine.php +1678 -0
- lib/Magmi/engines/magmi_utilityengine.php +84 -0
- lib/Magmi/inc/dbhelper.class.php +593 -0
- lib/Magmi/inc/dbhelper.class.php~ +589 -0
- lib/Magmi/inc/fshelper.php +370 -0
- lib/Magmi/inc/license.txt +19 -0
- lib/Magmi/inc/magmi_config.php +278 -0
- lib/Magmi/inc/magmi_csvreader.php +243 -0
- lib/Magmi/inc/magmi_defs.php +10 -0
- lib/Magmi/inc/magmi_engine.php +453 -0
- lib/Magmi/inc/magmi_loggers.php +53 -0
- lib/Magmi/inc/magmi_mixin.php +44 -0
- lib/Magmi/inc/magmi_pluginhelper.php +202 -0
- lib/Magmi/inc/magmi_postinstall.php +41 -0
- lib/Magmi/inc/magmi_statemanager.php +74 -0
- lib/Magmi/inc/magmi_utils.php +149 -0
- lib/Magmi/inc/magmi_version.php +5 -0
- lib/Magmi/inc/properties.php +202 -0
- lib/Magmi/integration/inc/magmi_datapump.php +37 -0
- lib/Magmi/integration/inc/magmi_datapumpdatasource.php +18 -0
- lib/Magmi/integration/inc/productimport_datapump.php +84 -0
- lib/Magmi/integration/inc/pumpfactory.ini +2 -0
- lib/Magmi/integration/samples/sample.php +117 -0
- lib/Magmi/integration/samples/sample2_configurables.php +79 -0
- lib/Magmi/plugins/base/datasources/__magento/magmi_magentodatasource.php +90 -0
- lib/Magmi/plugins/base/datasources/__magento/options_panel.php +6 -0
- lib/Magmi/plugins/base/datasources/csv/csvds_filelist.php +17 -0
- lib/Magmi/plugins/base/datasources/csv/magmi_csvdatasource.php +274 -0
- lib/Magmi/plugins/base/datasources/csv/options_panel.php +142 -0
- lib/Magmi/plugins/base/datasources/genericsql/mysql_options.php +28 -0
- lib/Magmi/plugins/base/datasources/genericsql/options_panel.php +45 -0
- lib/Magmi/plugins/base/datasources/genericsql/other_options.php +15 -0
- lib/Magmi/plugins/base/datasources/genericsql/sql_datasource.php +138 -0
- lib/Magmi/plugins/base/general/emailreport/emailreport.php +133 -0
- lib/Magmi/plugins/base/general/emailreport/options_panel.php +29 -0
- lib/Magmi/plugins/base/general/importurl/importurl_plugin.php +15 -0
- lib/Magmi/plugins/base/general/importurl/options_panel.php +63 -0
- lib/Magmi/plugins/base/general/optimizer/magmi_optimizer_plugin.php +42 -0
- lib/Magmi/plugins/base/general/reindex/magmi_reindexing_plugin.php +117 -0
- lib/Magmi/plugins/base/general/reindex/options_panel.php +49 -0
- lib/Magmi/plugins/base/itemprocessors/columnmapper/000_columnmapper.php +115 -0
- lib/Magmi/plugins/base/itemprocessors/columnmapper/options_panel.php +22 -0
- lib/Magmi/plugins/base/itemprocessors/configurables/magmi_configurableprocessor.php +368 -0
- lib/Magmi/plugins/base/itemprocessors/configurables/options_panel.php +34 -0
- lib/Magmi/plugins/base/itemprocessors/defaultvalues/00_default_values.php +100 -0
- lib/Magmi/plugins/base/itemprocessors/defaultvalues/options_panel.php +22 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/02_genericmapper.php +123 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/__common__.csv +2 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/options_container.csv +2 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/page_layout.csv +6 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/status.csv +2 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/visibility.csv +4 -0
- lib/Magmi/plugins/base/itemprocessors/genericmapper/options_panel.php +7 -0
- lib/Magmi/plugins/base/itemprocessors/grouped/alpine_groupedprocessor.php +227 -0
- lib/Magmi/plugins/base/itemprocessors/grouped/options_panel.php +60 -0
- lib/Magmi/plugins/base/itemprocessors/importlimiter/01_importlimiter.php +172 -0
- lib/Magmi/plugins/base/itemprocessors/importlimiter/options_panel.php +48 -0
- lib/Magmi/plugins/base/itemprocessors/productdeleter/options_panel.php +9 -0
- lib/Magmi/plugins/base/itemprocessors/productdeleter/productdeleter.php +60 -0
- lib/Magmi/plugins/base/itemprocessors/related/related_products.php +301 -0
- lib/Magmi/plugins/base/itemprocessors/skufinder/001_skufinder.php +95 -0
- lib/Magmi/plugins/base/itemprocessors/skufinder/options_panel.php +13 -0
- lib/Magmi/plugins/base/itemprocessors/upcross_sell/crossupsell_products.php +279 -0
- lib/Magmi/plugins/inc/magmi_datasource.php +30 -0
- lib/Magmi/plugins/inc/magmi_default_options_panel.php +1 -0
- lib/Magmi/plugins/inc/magmi_defaultattributehandler.php +218 -0
- lib/Magmi/plugins/inc/magmi_generalimport_plugin.php +15 -0
- lib/Magmi/plugins/inc/magmi_item_processor.php +102 -0
- lib/Magmi/plugins/inc/magmi_plugin.php +346 -0
- lib/Magmi/plugins/inc/magmi_utility_plugin.php +13 -0
- package.xml +36 -0
- shell/fballiano_full_catalog_translate.php +143 -0
app/code/community/Fballiano/FullCatalogTranslate/Helper/Data.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* FBalliano
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
*
|
12 |
+
* DISCLAIMER
|
13 |
+
*
|
14 |
+
* Do not edit or add to this file if you wish to upgrade this Module to
|
15 |
+
* newer versions in the future.
|
16 |
+
*
|
17 |
+
* @category FBalliano
|
18 |
+
* @package FBalliano_FullCatalogTranslate
|
19 |
+
* @copyright Copyright (c) 2014 Fabrizio Balliano (http://fabrizioballiano.it)
|
20 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
21 |
+
*/
|
22 |
+
class Fballiano_FullCatalogTranslate_Helper_Data extends Mage_Core_Helper_Abstract
|
23 |
+
{
|
24 |
+
/**
|
25 |
+
* @return array
|
26 |
+
*/
|
27 |
+
public function getAttributesToTranslate()
|
28 |
+
{
|
29 |
+
$attributes = Mage::getStoreConfig("fballiano_full_catalog_translate/general/attributes_to_translate");
|
30 |
+
$attributes = explode(",", $attributes);
|
31 |
+
foreach ($attributes as $k=>$v) {
|
32 |
+
$attributes[$k] = trim($v);
|
33 |
+
}
|
34 |
+
|
35 |
+
return $attributes;
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return string
|
40 |
+
*/
|
41 |
+
public function getApiKey()
|
42 |
+
{
|
43 |
+
return Mage::getStoreConfig("fballiano_full_catalog_translate/google_translate/api_key");
|
44 |
+
}
|
45 |
+
}
|
app/code/community/Fballiano/FullCatalogTranslate/etc/adminhtml.xml
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<acl>
|
4 |
+
<resources>
|
5 |
+
<admin>
|
6 |
+
<children>
|
7 |
+
<system>
|
8 |
+
<children>
|
9 |
+
<config>
|
10 |
+
<children>
|
11 |
+
<fballiano_full_catalog_translate>
|
12 |
+
<title>FBalliano Full Catalog Translate</title>
|
13 |
+
</fballiano_full_catalog_translate>
|
14 |
+
</children>
|
15 |
+
</config>
|
16 |
+
</children>
|
17 |
+
</system>
|
18 |
+
</children>
|
19 |
+
</admin>
|
20 |
+
</resources>
|
21 |
+
</acl>
|
22 |
+
</config>
|
app/code/community/Fballiano/FullCatalogTranslate/etc/config.xml
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Fballiano_FullCatalogTranslate>
|
5 |
+
<version>0.2.0</version>
|
6 |
+
</Fballiano_FullCatalogTranslate>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<helpers>
|
10 |
+
<fballiano_fullcatalogtranslate>
|
11 |
+
<class>Fballiano_FullCatalogTranslate_Helper</class>
|
12 |
+
</fballiano_fullcatalogtranslate>
|
13 |
+
</helpers>
|
14 |
+
<resources>
|
15 |
+
<fballiano_fullcatalogtranslate_setup>
|
16 |
+
<setup>
|
17 |
+
<module>Fballiano_FullCatalogTranslate</module>
|
18 |
+
<class>Mage_Catalog_Model_Resource_Setup</class>
|
19 |
+
</setup>
|
20 |
+
</fballiano_fullcatalogtranslate_setup>
|
21 |
+
</resources>
|
22 |
+
</global>
|
23 |
+
<default>
|
24 |
+
<fballiano_full_catalog_translate>
|
25 |
+
<general>
|
26 |
+
<attributes_to_translate>name, short_description, description, meta_title, meta_keyword, meta_description</attributes_to_translate>
|
27 |
+
</general>
|
28 |
+
</fballiano_full_catalog_translate>
|
29 |
+
</default>
|
30 |
+
</config>
|
app/code/community/Fballiano/FullCatalogTranslate/etc/system.xml
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<sections>
|
4 |
+
<fballiano_full_catalog_translate>
|
5 |
+
<tab>service</tab>
|
6 |
+
<label>Fballiano Full Catalog Translate</label>
|
7 |
+
<show_in_default>1</show_in_default>
|
8 |
+
<show_in_website>0</show_in_website>
|
9 |
+
<show_in_store>0</show_in_store>
|
10 |
+
<groups>
|
11 |
+
<general>
|
12 |
+
<label>General</label>
|
13 |
+
<show_in_default>1</show_in_default>
|
14 |
+
<show_in_website>0</show_in_website>
|
15 |
+
<show_in_store>0</show_in_store>
|
16 |
+
<sort_order>10</sort_order>
|
17 |
+
<fields>
|
18 |
+
<attributes_to_translate>
|
19 |
+
<label>Attributes to translate</label>
|
20 |
+
<show_in_default>1</show_in_default>
|
21 |
+
<show_in_website>0</show_in_website>
|
22 |
+
<show_in_store>0</show_in_store>
|
23 |
+
<comment>Comma separated list of attribute codes, only these attributes will be translated.</comment>
|
24 |
+
</attributes_to_translate>
|
25 |
+
</fields>
|
26 |
+
</general>
|
27 |
+
<google_translate>
|
28 |
+
<label>Google Translate</label>
|
29 |
+
<show_in_default>1</show_in_default>
|
30 |
+
<show_in_website>0</show_in_website>
|
31 |
+
<show_in_store>0</show_in_store>
|
32 |
+
<sort_order>20</sort_order>
|
33 |
+
<fields>
|
34 |
+
<api_key>
|
35 |
+
<label>API key</label>
|
36 |
+
<show_in_default>1</show_in_default>
|
37 |
+
<show_in_website>0</show_in_website>
|
38 |
+
<show_in_store>0</show_in_store>
|
39 |
+
</api_key>
|
40 |
+
</fields>
|
41 |
+
</google_translate>
|
42 |
+
</groups>
|
43 |
+
</fballiano_full_catalog_translate>
|
44 |
+
</sections>
|
45 |
+
</config>
|
app/code/community/Fballiano/FullCatalogTranslate/sql/fballiano_fullcatalogtranslate_setup/install-0.1.0.php
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* FBalliano
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
*
|
12 |
+
* DISCLAIMER
|
13 |
+
*
|
14 |
+
* Do not edit or add to this file if you wish to upgrade this Module to
|
15 |
+
* newer versions in the future.
|
16 |
+
*
|
17 |
+
* @category FBalliano
|
18 |
+
* @package FBalliano_FullCatalogTranslate
|
19 |
+
* @copyright Copyright (c) 2014 Fabrizio Balliano (http://fabrizioballiano.it)
|
20 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
21 |
+
*/
|
22 |
+
|
23 |
+
/* @var $installer Mage_Catalog_Model_Resource_Setup */
|
24 |
+
$installer = $this;
|
25 |
+
$installer->startSetup();
|
26 |
+
|
27 |
+
//$installer->removeAttribute(Mage_Catalog_Model_Product::ENTITY, "fb_translate");
|
28 |
+
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, "fb_translate", array(
|
29 |
+
"group" => "General",
|
30 |
+
"type" => "int",
|
31 |
+
"default" => "0",
|
32 |
+
"label" => "Translate automatically?",
|
33 |
+
"note"=> "Should this product be translated automatically when the store admin decides so?",
|
34 |
+
"input" => "select",
|
35 |
+
'source' => 'eav/entity_attribute_source_boolean',
|
36 |
+
"global" => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
|
37 |
+
"backend" => "",
|
38 |
+
"frontend" => "",
|
39 |
+
"is_configurable" => false,
|
40 |
+
"required" => false,
|
41 |
+
'searchable' => false,
|
42 |
+
'filterable' => false,
|
43 |
+
'comparable' => false,
|
44 |
+
'visible_on_front' => false,
|
45 |
+
'visible_in_advanced_search' => false,
|
46 |
+
'used_in_product_listing' => false,
|
47 |
+
'unique' => false,
|
48 |
+
'apply_to' => ''
|
49 |
+
)
|
50 |
+
);
|
51 |
+
|
52 |
+
$installer->endSetup();
|
app/etc/modules/Fballiano_FullCatalogTranslate.xml
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Fballiano_FullCatalogTranslate>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
<depends>
|
8 |
+
<Mage_Catalog/>
|
9 |
+
</depends>
|
10 |
+
</Fballiano_FullCatalogTranslate>
|
11 |
+
</modules>
|
12 |
+
</config>
|
lib/Magmi/ReleaseNotes.txt
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
-------------------------------------------------
|
2 |
+
- RELEASE NOTES FOR MAGMI 0.7.18beta1 -
|
3 |
+
-------------------------------------------------
|
4 |
+
|
5 |
+
|
6 |
+
##########
|
7 |
+
#Bugfix
|
8 |
+
#########
|
9 |
+
- fixed case insensitive matching for options
|
10 |
+
|
11 |
+
|
12 |
+
##########
|
13 |
+
#Core
|
14 |
+
##########
|
15 |
+
|
16 |
+
|
17 |
+
* ProductImportEngine
|
18 |
+
- added support for category item positioning
|
19 |
+
- better behaviour on unmatched category id in category_ids (if not existing, warning instead of exception)
|
20 |
+
- autodefaulting of store column to "admin" if omitted
|
21 |
+
|
22 |
+
* Magmi_config
|
23 |
+
- support for alternate global configuration files
|
24 |
+
|
25 |
+
* Magmi_cli
|
26 |
+
- support for profile chaining in magmi.cli.php
|
27 |
+
- magmi.cli.php could be now more easily integrated as include in other scripts.
|
28 |
+
|
29 |
+
* Magmi_utils
|
30 |
+
- added utility functions to detect remote urls
|
31 |
+
|
32 |
+
############
|
33 |
+
# UI
|
34 |
+
############
|
35 |
+
|
36 |
+
- fixed cache sensivity of magmi run from UI
|
37 |
+
- use of google CDN url for prototype.js lib
|
38 |
+
|
39 |
+
#########
|
40 |
+
#Plugins
|
41 |
+
#########
|
42 |
+
|
43 |
+
Base:
|
44 |
+
------
|
45 |
+
|
46 |
+
* Remote Agent:
|
47 |
+
Enable connecting to remote magento installs (put ftp://user:pass@host/magento_base_dir) as magento base directory
|
48 |
+
Enable to perform remote filesystem operations
|
49 |
+
need DB connectivity between magento host & magmi host.
|
50 |
+
|
51 |
+
*Grouped Products:
|
52 |
+
- added support for any type of subproducts
|
53 |
+
|
54 |
+
* CSV Datasource
|
55 |
+
|
56 |
+
Extra
|
57 |
+
-----
|
58 |
+
|
59 |
+
* Categories
|
60 |
+
- added support for multiple root assignment in a single line
|
61 |
+
- added support for tree separator escaping
|
62 |
+
- added support for item position in each branch of the tree
|
63 |
+
|
64 |
+
Utilities
|
65 |
+
---------
|
66 |
+
|
67 |
+
Mass Option Remapper : enable to remap select attribute values using input csv..
|
lib/Magmi/conf/magmi.ini
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
[GLOBAL]
|
2 |
+
step = "0.5"
|
lib/Magmi/conf/plugins.conf
ADDED
File without changes
|
lib/Magmi/engines/magmi_productimportengine.php
ADDED
@@ -0,0 +1,1678 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
15 |
+
/**
|
16 |
+
*
|
17 |
+
* Magmi Product Import engine class
|
18 |
+
* This class handle product import
|
19 |
+
* @author dweeves
|
20 |
+
*
|
21 |
+
*/
|
22 |
+
class Magmi_ProductImportEngine extends Magmi_Engine
|
23 |
+
{
|
24 |
+
|
25 |
+
public $attrinfo=array();
|
26 |
+
public $attrbytype=array();
|
27 |
+
public $store_ids=array();
|
28 |
+
public $status_id=array();
|
29 |
+
public $attribute_sets=array();
|
30 |
+
public $prod_etype;
|
31 |
+
public $default_asid;
|
32 |
+
public $sidcache=array();
|
33 |
+
public $mode="update";
|
34 |
+
private $_attributehandlers;
|
35 |
+
private $_current_row;
|
36 |
+
private $_optidcache=null;
|
37 |
+
private $_curitemids=array("sku"=>null);
|
38 |
+
private $_dstore=array();
|
39 |
+
private $_same;
|
40 |
+
private $_currentpid;
|
41 |
+
private $_extra_attrs;
|
42 |
+
private $_profile;
|
43 |
+
private $_sid_wsscope=array();
|
44 |
+
private $_sid_sscope=array();
|
45 |
+
private $_prodcols=array();
|
46 |
+
private $_stockcols=array();
|
47 |
+
private $_skustats=array();
|
48 |
+
|
49 |
+
public function addExtraAttribute($attr)
|
50 |
+
{
|
51 |
+
$attinfo=$this->attrinfo[$attr];
|
52 |
+
$this->_extra_attrs[$attinfo["backend_type"]]["data"][]=$attinfo;
|
53 |
+
|
54 |
+
}
|
55 |
+
/**
|
56 |
+
* constructor
|
57 |
+
* @param string $conffile : configuration .ini filename
|
58 |
+
*/
|
59 |
+
public function __construct()
|
60 |
+
{
|
61 |
+
|
62 |
+
$this->setBuiltinPluginClasses("itemprocessors",dirname(dirname(__FILE__))."/plugins/inc/magmi_defaultattributehandler.php::Magmi_DefaultAttributeItemProcessor");
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
public function getSkuStats()
|
67 |
+
{
|
68 |
+
return $this->_skustats;
|
69 |
+
}
|
70 |
+
|
71 |
+
public function getImportMode()
|
72 |
+
{
|
73 |
+
return $this->mode;
|
74 |
+
}
|
75 |
+
/**
|
76 |
+
* (non-PHPdoc)
|
77 |
+
* @see Magmi_Engine::getEngineInfo()
|
78 |
+
*/
|
79 |
+
public function getEngineInfo()
|
80 |
+
{
|
81 |
+
return array("name"=>"Magmi Product Import Engine","version"=>"1.7.1","author"=>"dweeves");
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* load properties
|
86 |
+
* @param string $conf : configuration .ini filename
|
87 |
+
*/
|
88 |
+
|
89 |
+
|
90 |
+
|
91 |
+
|
92 |
+
public function initProdType()
|
93 |
+
{
|
94 |
+
$tname=$this->tablename("eav_entity_type");
|
95 |
+
$this->prod_etype=$this->selectone("SELECT entity_type_id FROM $tname WHERE entity_type_code=?","catalog_product","entity_type_id");
|
96 |
+
$this->default_asid=$this->getAttributeSetId('Default');
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
|
101 |
+
public function getPluginFamilies()
|
102 |
+
{
|
103 |
+
return array("datasources","general","itemprocessors");
|
104 |
+
}
|
105 |
+
|
106 |
+
public function registerAttributeHandler($ahinst,$attdeflist)
|
107 |
+
{
|
108 |
+
foreach($attdeflist as $attdef)
|
109 |
+
{
|
110 |
+
$ad=explode(":",$attdef);
|
111 |
+
if(count($ad)!=2)
|
112 |
+
{
|
113 |
+
$this->log("Invalid registration string ($attdef) :".get_class($ahinst),"warning");
|
114 |
+
}
|
115 |
+
else
|
116 |
+
{
|
117 |
+
$this->_attributehandlers[$attdef]=$ahinst;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
|
124 |
+
|
125 |
+
/**
|
126 |
+
*
|
127 |
+
* Return list of store codes that share the same website than the stores passed as parameter
|
128 |
+
* @param string $scodes comma separated list of store view codes
|
129 |
+
*/
|
130 |
+
public function getStoreIdsForWebsiteScope($scodes)
|
131 |
+
{
|
132 |
+
if(!isset($this->_sid_wsscope[$scodes]))
|
133 |
+
{
|
134 |
+
$this->_sid_wsscope[$scodes]=array();
|
135 |
+
$wscarr=csl2arr($scodes);
|
136 |
+
$qcolstr=$this->arr2values($wscarr);
|
137 |
+
$cs=$this->tablename("core_store");
|
138 |
+
$sql="SELECT csdep.store_id FROM $cs as csmain
|
139 |
+
JOIN $cs as csdep ON csdep.website_id=csmain.website_id
|
140 |
+
WHERE csmain.code IN ($qcolstr) ";
|
141 |
+
$sidrows=$this->selectAll($sql,$wscarr);
|
142 |
+
foreach($sidrows as $sidrow)
|
143 |
+
{
|
144 |
+
$this->_sid_wsscope[$scodes][]=$sidrow["store_id"];
|
145 |
+
}
|
146 |
+
}
|
147 |
+
return $this->_sid_wsscope[$scodes];
|
148 |
+
}
|
149 |
+
|
150 |
+
public function getStoreIdsForStoreScope($scodes)
|
151 |
+
{
|
152 |
+
if(!isset($this->_sid_sscope[$scodes]))
|
153 |
+
{
|
154 |
+
$this->_sid_sscope[$scodes]=array();
|
155 |
+
$scarr=csl2arr($scodes);
|
156 |
+
$qcolstr=$this->arr2values($scarr);
|
157 |
+
$cs=$this->tablename("core_store");
|
158 |
+
$sql="SELECT csmain.store_id from $cs as csmain WHERE csmain.code IN ($qcolstr)";
|
159 |
+
$sidrows=$this->selectAll($sql,$scarr);
|
160 |
+
foreach($sidrows as $sidrow)
|
161 |
+
{
|
162 |
+
$this->_sid_sscope[$scodes][]=$sidrow["store_id"];
|
163 |
+
}
|
164 |
+
|
165 |
+
}
|
166 |
+
return $this->_sid_sscope[$scodes];
|
167 |
+
}
|
168 |
+
|
169 |
+
|
170 |
+
/**
|
171 |
+
* returns mode
|
172 |
+
*/
|
173 |
+
public function getMode()
|
174 |
+
{
|
175 |
+
return $this->mode;
|
176 |
+
}
|
177 |
+
|
178 |
+
public function getProdCols()
|
179 |
+
{
|
180 |
+
if(count($this->_prodcols)==0)
|
181 |
+
{
|
182 |
+
$sql='DESCRIBE '.$this->tablename('catalog_product_entity');
|
183 |
+
$rows=$this->selectAll($sql);
|
184 |
+
foreach($rows as $row)
|
185 |
+
{
|
186 |
+
$this->_prodcols[]=$row['Field'];
|
187 |
+
}
|
188 |
+
}
|
189 |
+
return $this->_prodcols;
|
190 |
+
}
|
191 |
+
|
192 |
+
public function getStockCols()
|
193 |
+
{
|
194 |
+
if(count($this->_stockcols)==0)
|
195 |
+
{
|
196 |
+
$sql='DESCRIBE '.$this->tablename('cataloginventory_stock_item');
|
197 |
+
$rows=$this->selectAll($sql);
|
198 |
+
foreach($rows as $row)
|
199 |
+
{
|
200 |
+
$this->_stockcols[]=$row['Field'];
|
201 |
+
}
|
202 |
+
}
|
203 |
+
return $this->_stockcols;
|
204 |
+
}
|
205 |
+
/**
|
206 |
+
* Initialize attribute infos to be used during import
|
207 |
+
* @param array $cols : array of attribute names
|
208 |
+
*/
|
209 |
+
public function checkRequired($cols)
|
210 |
+
{
|
211 |
+
$eav_attr=$this->tablename("eav_attribute");
|
212 |
+
$sql="SELECT attribute_code FROM $eav_attr WHERE is_required=1
|
213 |
+
AND frontend_input!='' AND frontend_label!='' AND entity_type_id=?";
|
214 |
+
$required=$this->selectAll($sql,$this->prod_etype);
|
215 |
+
$reqcols=array();
|
216 |
+
foreach($required as $line)
|
217 |
+
{
|
218 |
+
$reqcols[]=$line["attribute_code"];
|
219 |
+
}
|
220 |
+
$required=array_diff($reqcols,$cols);
|
221 |
+
return $required;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
*
|
226 |
+
* gets attribute metadata from DB and put it in attribute metadata caches
|
227 |
+
* @param array $cols list of attribute codes to get metadata from
|
228 |
+
* if in this list, some values are not attribute code, no metadata will be cached.
|
229 |
+
*/
|
230 |
+
public function initAttrInfos($cols)
|
231 |
+
{
|
232 |
+
if($this->prod_etype==null)
|
233 |
+
{
|
234 |
+
//Find product entity type
|
235 |
+
$tname=$this->tablename("eav_entity_type");
|
236 |
+
$this->prod_etype=$this->selectone("SELECT entity_type_id FROM $tname WHERE entity_type_code=?","catalog_product","entity_type_id");
|
237 |
+
}
|
238 |
+
|
239 |
+
$toscan=array_values(array_diff($cols,array_keys($this->attrinfo)));
|
240 |
+
if(count($toscan)>0)
|
241 |
+
{
|
242 |
+
//create statement parameter string ?,?,?.....
|
243 |
+
$qcolstr=$this->arr2values($toscan);
|
244 |
+
|
245 |
+
$tname=$this->tablename("eav_attribute");
|
246 |
+
if($this->getMagentoVersion()!="1.3.x")
|
247 |
+
{
|
248 |
+
$extra=$this->tablename("catalog_eav_attribute");
|
249 |
+
//SQL for selecting attribute properties for all wanted attributes
|
250 |
+
$sql="SELECT `$tname`.*,$extra.is_global FROM `$tname`
|
251 |
+
LEFT JOIN $extra ON $tname.attribute_id=$extra.attribute_id
|
252 |
+
WHERE ($tname.attribute_code IN ($qcolstr)) AND (entity_type_id=?)";
|
253 |
+
}
|
254 |
+
else
|
255 |
+
{
|
256 |
+
$sql="SELECT `$tname`.* FROM `$tname` WHERE ($tname.attribute_code IN ($qcolstr)) AND (entity_type_id=?)";
|
257 |
+
}
|
258 |
+
$toscan[]=$this->prod_etype;
|
259 |
+
$result=$this->selectAll($sql,$toscan);
|
260 |
+
|
261 |
+
$attrinfs=array();
|
262 |
+
//create an attribute code based array for the wanted columns
|
263 |
+
foreach($result as $r)
|
264 |
+
{
|
265 |
+
$attrinfs[$r["attribute_code"]]=$r;
|
266 |
+
}
|
267 |
+
unset($result);
|
268 |
+
|
269 |
+
//create a backend_type based array for the wanted columns
|
270 |
+
//this will greatly help for optimizing inserts when creating attributes
|
271 |
+
//since eav_ model for attributes has one table per backend type
|
272 |
+
foreach($attrinfs as $k=>$a)
|
273 |
+
{
|
274 |
+
//do not index attributes that are not in header (media_gallery may have been inserted for other purposes)
|
275 |
+
if(!in_array($k,$cols))
|
276 |
+
{
|
277 |
+
continue;
|
278 |
+
}
|
279 |
+
$bt=$a["backend_type"];
|
280 |
+
if(!isset($this->attrbytype[$bt]))
|
281 |
+
{
|
282 |
+
$this->attrbytype[$bt]=array("data"=>array());
|
283 |
+
}
|
284 |
+
$this->attrbytype[$bt]["data"][]=$a;
|
285 |
+
}
|
286 |
+
//now add a fast index in the attrbytype array to store id list in a comma separated form
|
287 |
+
foreach($this->attrbytype as $bt=>$test)
|
288 |
+
{
|
289 |
+
$idlist;
|
290 |
+
foreach($test["data"] as $it)
|
291 |
+
{
|
292 |
+
$idlist[]=$it["attribute_id"];
|
293 |
+
}
|
294 |
+
$this->attrbytype[$bt]["ids"]=implode(",",$idlist);
|
295 |
+
}
|
296 |
+
$this->attrinfo=array_merge($this->attrinfo,$attrinfs);
|
297 |
+
}
|
298 |
+
$notattribs=array_diff($cols,array_keys($this->attrinfo));
|
299 |
+
foreach($notattribs as $k)
|
300 |
+
{
|
301 |
+
$this->attrinfo[$k]=null;
|
302 |
+
}
|
303 |
+
/*now we have 2 index arrays
|
304 |
+
1. $this->attrinfo which has the following structure:
|
305 |
+
key : attribute_code
|
306 |
+
value : attribute_properties
|
307 |
+
2. $this->attrbytype which has the following structure:
|
308 |
+
key : attribute backend type
|
309 |
+
value : array of :
|
310 |
+
data => array of attribute_properties ,one for each attribute that match
|
311 |
+
the backend type
|
312 |
+
ids => list of attribute ids of the backend type */
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
*
|
317 |
+
* retrieves attribute metadata
|
318 |
+
* @param string $attcode attribute code
|
319 |
+
* @param boolean $lookup if set, this will try to get info from DB otherwise will get from cache and may return null if not cached
|
320 |
+
* @return array attribute metadata info
|
321 |
+
*/
|
322 |
+
public function getAttrInfo($attcode,$lookup=true)
|
323 |
+
{
|
324 |
+
$attrinf=isset($this->attrinfo[$attcode])?$this->attrinfo[$attcode]:null;
|
325 |
+
if($attrinf==null && $lookup)
|
326 |
+
{
|
327 |
+
$this->initAttrInfos(array($attcode));
|
328 |
+
|
329 |
+
}
|
330 |
+
if(count($this->attrinfo[$attcode])==0)
|
331 |
+
{
|
332 |
+
|
333 |
+
$attrinf=null;
|
334 |
+
unset($this->attrinfo[$attcode]);
|
335 |
+
}
|
336 |
+
else
|
337 |
+
{
|
338 |
+
$attrinf=$this->attrinfo[$attcode];
|
339 |
+
}
|
340 |
+
return $attrinf;
|
341 |
+
}
|
342 |
+
|
343 |
+
/**
|
344 |
+
* retrieves attribute set id for a given attribute set name
|
345 |
+
* @param string $asname : attribute set name
|
346 |
+
*/
|
347 |
+
public function getAttributeSetId($asname)
|
348 |
+
{
|
349 |
+
|
350 |
+
if(!isset($this->attribute_sets[$asname]))
|
351 |
+
{
|
352 |
+
$tname=$this->tablename("eav_attribute_set");
|
353 |
+
$asid=$this->selectone(
|
354 |
+
"SELECT attribute_set_id FROM $tname WHERE attribute_set_name=? AND entity_type_id=?",
|
355 |
+
array($asname,$this->prod_etype),
|
356 |
+
'attribute_set_id');
|
357 |
+
$this->attribute_sets[$asname]=$asid;
|
358 |
+
}
|
359 |
+
return $this->attribute_sets[$asname];
|
360 |
+
}
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Retrieves product id for a given sku
|
364 |
+
* @param string $sku : sku of product to get id for
|
365 |
+
*/
|
366 |
+
public function getProductIds($sku)
|
367 |
+
{
|
368 |
+
$tname=$this->tablename("catalog_product_entity");
|
369 |
+
$result=$this->selectAll(
|
370 |
+
"SELECT sku,entity_id as pid,attribute_set_id as asid FROM $tname WHERE sku=?",
|
371 |
+
$sku);
|
372 |
+
if(count($result)>0)
|
373 |
+
{
|
374 |
+
return $result[0];
|
375 |
+
}
|
376 |
+
else
|
377 |
+
{
|
378 |
+
return false;
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* creates a product in magento database
|
384 |
+
* @param array $item: product attributes as array with key:attribute name,value:attribute value
|
385 |
+
* @param int $asid : attribute set id for values
|
386 |
+
* @return : product id for newly created product
|
387 |
+
*/
|
388 |
+
public function createProduct($item,$asid)
|
389 |
+
{
|
390 |
+
//force item type if not exists
|
391 |
+
if(!isset($item["type"]))
|
392 |
+
{
|
393 |
+
$item["type"]="simple";
|
394 |
+
}
|
395 |
+
$tname=$this->tablename('catalog_product_entity');
|
396 |
+
$item['type_id']=$item['type'];
|
397 |
+
$item['attribute_set_id']=$asid;
|
398 |
+
$item['entity_type_id']=$this->prod_etype;
|
399 |
+
$item['created_at']=strftime("%Y-%m-%d %H:%M:%S");
|
400 |
+
$item['updated_at']=strftime("%Y-%m-%d %H:%M:%S");
|
401 |
+
$columns=array_intersect(array_keys($item), $this->getProdCols());
|
402 |
+
$values=$this->filterkvarr($item, $columns);
|
403 |
+
$sql="INSERT INTO `$tname` (".implode(",",$columns).") VALUES (".$this->arr2values($columns).")";
|
404 |
+
$lastid=$this->insert($sql,array_values($values));
|
405 |
+
return $lastid;
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Updateds product update time
|
410 |
+
* @param unknown_type $pid : entity_id of product
|
411 |
+
*/
|
412 |
+
public function touchProduct($pid)
|
413 |
+
{
|
414 |
+
$tname=$this->tablename('catalog_product_entity');
|
415 |
+
$this->update("UPDATE $tname SET updated_at=? WHERE entity_id=?",array(strftime("%Y-%m-%d %H:%M:%S"),$pid));
|
416 |
+
}
|
417 |
+
|
418 |
+
/**
|
419 |
+
* Get Option id for select attributes based on value
|
420 |
+
* @param int $attid : attribute id to find option id from value
|
421 |
+
* @param mixed $optval : value to get option id for
|
422 |
+
* @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
|
423 |
+
*/
|
424 |
+
public function getOptionsFromValues($attid,$store_id,$optvals)
|
425 |
+
{
|
426 |
+
$ovstr=substr(str_repeat("?,",count($optvals)),0,-1);
|
427 |
+
$t1=$this->tablename('eav_attribute_option');
|
428 |
+
$t2=$this->tablename('eav_attribute_option_value');
|
429 |
+
$sql="SELECT optvals.option_id as opvs,optvals.value FROM $t2 as optvals";
|
430 |
+
$sql.=" JOIN $t1 as opt ON opt.option_id=optvals.option_id AND opt.attribute_id=?";
|
431 |
+
$sql.=" WHERE optvals.store_id=? AND BINARY optvals.value IN ($ovstr)";
|
432 |
+
return $this->selectAll($sql,array_merge(array($attid,$store_id),$optvals));
|
433 |
+
}
|
434 |
+
|
435 |
+
|
436 |
+
/* create a new option entry for an attribute */
|
437 |
+
public function createOption($attid)
|
438 |
+
{
|
439 |
+
$t=$this->tablename('eav_attribute_option');
|
440 |
+
$optid=$this->insert("INSERT INTO $t (attribute_id) VALUES (?)",$attid);
|
441 |
+
return $optid;
|
442 |
+
}
|
443 |
+
/**
|
444 |
+
* Creates a new option value for an option entry for a store
|
445 |
+
* @param int $optid : option entry id
|
446 |
+
* @param int $store_id : store id to add value for
|
447 |
+
* @param mixed $optval : new option value to add
|
448 |
+
* @return : option id for new created value
|
449 |
+
*/
|
450 |
+
public function createOptionValue($optid,$store_id,$optval)
|
451 |
+
{
|
452 |
+
$t=$this->tablename('eav_attribute_option_value');
|
453 |
+
$optval_id=$this->insert("INSERT INTO $t (option_id,store_id,value) VALUES (?,?,?)",array($optid,$store_id,$optval));
|
454 |
+
return $optval_id;
|
455 |
+
}
|
456 |
+
|
457 |
+
|
458 |
+
public function getOptionIds($attid,$storeid,$values)
|
459 |
+
{
|
460 |
+
$optids=array();
|
461 |
+
$svalues=array();
|
462 |
+
$avalues=array();
|
463 |
+
//Matching refstore value
|
464 |
+
foreach($values as $val)
|
465 |
+
{
|
466 |
+
if(preg_match("|^(.*)::\[(.*)\]$|",$val,$matches))
|
467 |
+
{
|
468 |
+
$svalues[]=$matches[2];
|
469 |
+
$avalues[]=$matches[1];
|
470 |
+
}
|
471 |
+
else
|
472 |
+
{
|
473 |
+
$svalues[]=$val;
|
474 |
+
$avalues[]=$val;
|
475 |
+
}
|
476 |
+
}
|
477 |
+
$existing=$this->getOptionsFromValues($attid,0,$avalues);
|
478 |
+
$exvals=array();
|
479 |
+
foreach($existing as $optdesc)
|
480 |
+
{
|
481 |
+
$exvals[]=$optdesc["value"];
|
482 |
+
}
|
483 |
+
$new=array_merge(array_diff($avalues,$exvals));
|
484 |
+
if($storeid==0)
|
485 |
+
{
|
486 |
+
foreach($new as $nval)
|
487 |
+
{
|
488 |
+
$row=array("opvs"=>$this->createOption($attid),"value"=>$nval);
|
489 |
+
$this->createOptionValue($row["opvs"],$storeid,$nval);
|
490 |
+
$existing[]=$row;
|
491 |
+
}
|
492 |
+
$this->cacheOptIds($attid,$existing);
|
493 |
+
|
494 |
+
}
|
495 |
+
else
|
496 |
+
{
|
497 |
+
|
498 |
+
$brows=$this->getCachedOptIds($attid);
|
499 |
+
if(count($brows)==0)
|
500 |
+
{
|
501 |
+
$existing=$this->getOptionsFromValues($attid,0,$avalues);
|
502 |
+
$new=array_merge(array_diff($avalues,$exvals));
|
503 |
+
foreach($new as $nval)
|
504 |
+
{
|
505 |
+
$row=array("opvs"=>$this->createOption($attid),"value"=>$nval);
|
506 |
+
$this->createOptionValue($row["opvs"],$storeid,$nval);
|
507 |
+
$existing[]=$row;
|
508 |
+
}
|
509 |
+
$this->cacheOptIds($attid,$existing);
|
510 |
+
$brows=$this->getCachedOptIds($attid);
|
511 |
+
}
|
512 |
+
foreach($existing as $ex)
|
513 |
+
{
|
514 |
+
array_shift($brows);
|
515 |
+
}
|
516 |
+
for($i=0;$i<count($new);$i++)
|
517 |
+
{
|
518 |
+
$row=$brows[$i];
|
519 |
+
if(!isset($row["opvs"]))
|
520 |
+
{
|
521 |
+
$row["opvs"]=$this->createOption($attid);
|
522 |
+
$this->createOptionValue($row["opvs"],0,$new[$i]);
|
523 |
+
}
|
524 |
+
$this->createOptionValue($row["opvs"],$storeid,$new[$i]);
|
525 |
+
$existing[]=$row;
|
526 |
+
}
|
527 |
+
}
|
528 |
+
$optids=array();
|
529 |
+
foreach($existing as $row)
|
530 |
+
{
|
531 |
+
$optids[]=$row["opvs"];
|
532 |
+
}
|
533 |
+
unset($existing);
|
534 |
+
unset($exvals);
|
535 |
+
return $optids;
|
536 |
+
|
537 |
+
}
|
538 |
+
|
539 |
+
public function cacheOptIds($attid,$row)
|
540 |
+
{
|
541 |
+
$this->_optidcache[$attid]=$row;
|
542 |
+
}
|
543 |
+
|
544 |
+
public function getCachedOptIds($attid)
|
545 |
+
{
|
546 |
+
if(isset($this->_optidcache[$attid]))
|
547 |
+
{
|
548 |
+
return $this->_optidcache[$attid];
|
549 |
+
}
|
550 |
+
else
|
551 |
+
{
|
552 |
+
return null;
|
553 |
+
}
|
554 |
+
}
|
555 |
+
|
556 |
+
|
557 |
+
/**
|
558 |
+
* returns tax class id for a given tax class value
|
559 |
+
* @param $tcvalue : tax class value
|
560 |
+
*/
|
561 |
+
public function getTaxClassId($tcvalue)
|
562 |
+
{
|
563 |
+
$t=$this->tablename('tax_class');
|
564 |
+
$txid=$this->selectone("SELECT class_id FROM $t WHERE class_name=?",array($tcvalue),"class_id");
|
565 |
+
//bugfix for tax class id, if not found set it to none
|
566 |
+
if(!isset($txid))
|
567 |
+
{
|
568 |
+
$txid=0;
|
569 |
+
}
|
570 |
+
return $txid;
|
571 |
+
}
|
572 |
+
|
573 |
+
public function parseCalculatedValue($pvalue,$item,$params)
|
574 |
+
{
|
575 |
+
$matches=array();
|
576 |
+
$ik=array_keys($item);
|
577 |
+
$rep="";
|
578 |
+
|
579 |
+
//replace base item values
|
580 |
+
while(preg_match("|\{item\.(.*?)\}|",$pvalue,$matches))
|
581 |
+
{
|
582 |
+
foreach($matches as $match)
|
583 |
+
{
|
584 |
+
if($match!=$matches[0])
|
585 |
+
{
|
586 |
+
if(in_array($match,$ik))
|
587 |
+
{
|
588 |
+
$rep='$item["'.$match.'"]';
|
589 |
+
}
|
590 |
+
else
|
591 |
+
{
|
592 |
+
$rep="";
|
593 |
+
}
|
594 |
+
$pvalue=str_replace($matches[0],$rep,$pvalue);
|
595 |
+
}
|
596 |
+
}
|
597 |
+
}
|
598 |
+
unset($matches);
|
599 |
+
//replac meta
|
600 |
+
$meta=$params;
|
601 |
+
|
602 |
+
|
603 |
+
while(preg_match("|\{meta\.(.*?)\}|",$pvalue,$matches))
|
604 |
+
{
|
605 |
+
foreach($matches as $match)
|
606 |
+
{
|
607 |
+
if($match!=$matches[0])
|
608 |
+
{
|
609 |
+
if(in_array($match,$ik))
|
610 |
+
{
|
611 |
+
$rep='$meta["'.$match.'"]';
|
612 |
+
}
|
613 |
+
else
|
614 |
+
{
|
615 |
+
$rep="";
|
616 |
+
}
|
617 |
+
$pvalue=str_replace($matches[0],$rep,$pvalue);
|
618 |
+
}
|
619 |
+
}
|
620 |
+
}
|
621 |
+
unset($matches);
|
622 |
+
|
623 |
+
|
624 |
+
//replacing expr values
|
625 |
+
while(preg_match("|\{\{\s*(.*?)\s*\}\}|",$pvalue,$matches))
|
626 |
+
{
|
627 |
+
foreach($matches as $match)
|
628 |
+
{
|
629 |
+
if($match!=$matches[0])
|
630 |
+
{
|
631 |
+
$code=trim($match);
|
632 |
+
//settiing meta values
|
633 |
+
$meta=$params;
|
634 |
+
$rep=eval("return ($code);");
|
635 |
+
//escape potential "{{xxx}}" values in interpreted target
|
636 |
+
//so that they won't be reparsed in next round
|
637 |
+
$rep=preg_replace("|\{\{\s*(.*?)\s*\}\}|", "____$1____", $rep);
|
638 |
+
$pvalue=str_replace($matches[0],$rep,$pvalue);
|
639 |
+
}
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
//unescape matches
|
644 |
+
$pvalue=preg_replace("|____(.*?)____|",'{{$1}}',$pvalue);
|
645 |
+
//replacing single values not in complex values
|
646 |
+
while(preg_match('|\$item\["(.*?)"\]|',$pvalue,$matches))
|
647 |
+
{
|
648 |
+
foreach($matches as $match)
|
649 |
+
{
|
650 |
+
if($match!=$matches[0])
|
651 |
+
{
|
652 |
+
if(in_array($match,$ik))
|
653 |
+
{
|
654 |
+
$rep=$item[$match];
|
655 |
+
}
|
656 |
+
else
|
657 |
+
{
|
658 |
+
$rep="";
|
659 |
+
}
|
660 |
+
$pvalue=str_replace($matches[0],$rep,$pvalue);
|
661 |
+
}
|
662 |
+
}
|
663 |
+
}
|
664 |
+
|
665 |
+
unset($matches);
|
666 |
+
return $pvalue;
|
667 |
+
}
|
668 |
+
|
669 |
+
/**
|
670 |
+
*
|
671 |
+
* Return affected store ids for a given item given an attribute scope
|
672 |
+
* @param array $item : item to get store for scope
|
673 |
+
* @param string $scope : scope to get stores from.
|
674 |
+
*/
|
675 |
+
public function getItemStoreIds($item,$scope=0)
|
676 |
+
{
|
677 |
+
if(!isset($item['store']))
|
678 |
+
{
|
679 |
+
$item['store']="admin";
|
680 |
+
}
|
681 |
+
switch($scope){
|
682 |
+
//global scope
|
683 |
+
case 1:
|
684 |
+
$bstore_ids=$this->getStoreIdsForStoreScope("admin");
|
685 |
+
break;
|
686 |
+
//store scope
|
687 |
+
case 0:
|
688 |
+
$bstore_ids=$this->getStoreIdsForStoreScope($item["store"]);
|
689 |
+
break;
|
690 |
+
//website scope
|
691 |
+
case 2:
|
692 |
+
$bstore_ids=$this->getStoreIdsForWebsiteScope($item["store"]);
|
693 |
+
break;
|
694 |
+
}
|
695 |
+
|
696 |
+
$itemstores=array_unique(array_merge($this->_dstore,$bstore_ids));
|
697 |
+
sort($itemstores);
|
698 |
+
return $itemstores;
|
699 |
+
}
|
700 |
+
|
701 |
+
/**
|
702 |
+
* Create product attribute from values for a given product id
|
703 |
+
* @param $pid : product id to create attribute values for
|
704 |
+
* @param $item : attribute values in an array indexed by attribute_code
|
705 |
+
*/
|
706 |
+
public function createAttributes($pid,&$item,$attmap,$isnew)
|
707 |
+
{
|
708 |
+
/**
|
709 |
+
* get all store ids
|
710 |
+
*/
|
711 |
+
$this->_extra_attrs=array();
|
712 |
+
/* now is the interesring part */
|
713 |
+
/* iterate on attribute backend type index */
|
714 |
+
foreach($attmap as $tp=>$a)
|
715 |
+
{
|
716 |
+
/* for static types, do not insert into attribute tables */
|
717 |
+
if($tp=="static")
|
718 |
+
{
|
719 |
+
continue;
|
720 |
+
}
|
721 |
+
|
722 |
+
//table name for backend type data
|
723 |
+
$cpet=$this->tablename("catalog_product_entity_$tp");
|
724 |
+
//data table for inserts
|
725 |
+
$data=array();
|
726 |
+
//inserts to perform on backend type eav
|
727 |
+
$inserts=array();
|
728 |
+
//deletes to perform on backend type eav
|
729 |
+
$deletes=array();
|
730 |
+
|
731 |
+
//use reflection to find special handlers
|
732 |
+
$typehandler="handle".ucfirst($tp)."Attribute";
|
733 |
+
//iterate on all attribute descriptions for the given backend type
|
734 |
+
foreach($a["data"] as $attrdesc)
|
735 |
+
{
|
736 |
+
//get attribute id
|
737 |
+
$attid=$attrdesc["attribute_id"];
|
738 |
+
//get attribute value in the item to insert based on code
|
739 |
+
$atthandler="handle".ucfirst($attrdesc["attribute_code"])."Attribute";
|
740 |
+
$attrcode=$attrdesc["attribute_code"];
|
741 |
+
//if the attribute code is no more in item (plugins may have come into the way), continue
|
742 |
+
if(!in_array($attrcode,array_keys($item)))
|
743 |
+
{
|
744 |
+
continue;
|
745 |
+
}
|
746 |
+
//get the item value
|
747 |
+
$ivalue=$item[$attrcode];
|
748 |
+
//get item store id for the current attribute
|
749 |
+
$store_ids=$this->getItemStoreIds($item,$attrdesc["is_global"]);
|
750 |
+
|
751 |
+
|
752 |
+
//do not handle empty generic int values in create mode
|
753 |
+
if($ivalue=="" && $this->mode!="update" && $tp=="int")
|
754 |
+
{
|
755 |
+
continue;
|
756 |
+
}
|
757 |
+
//for all store ids
|
758 |
+
foreach($store_ids as $store_id)
|
759 |
+
{
|
760 |
+
|
761 |
+
//base output value to be inserted = base source value
|
762 |
+
$ovalue=$ivalue;
|
763 |
+
//check for attribute handlers for current attribute
|
764 |
+
foreach($this->_attributehandlers as $match=>$ah)
|
765 |
+
{
|
766 |
+
$matchinfo=explode(":",$match);
|
767 |
+
$mtype=$matchinfo[0];
|
768 |
+
$mtest=$matchinfo[1];
|
769 |
+
unset($matchinfo);
|
770 |
+
unset($hvalue);
|
771 |
+
if(preg_match("/$mtest/",$attrdesc[$mtype]))
|
772 |
+
{
|
773 |
+
//if there is a specific handler for attribute, use it
|
774 |
+
if(method_exists($ah,$atthandler))
|
775 |
+
{
|
776 |
+
$hvalue=$ah->$atthandler($pid,$item,$store_id,$attrcode,$attrdesc,$ivalue);
|
777 |
+
}
|
778 |
+
else
|
779 |
+
//use generic type attribute
|
780 |
+
if(method_exists($ah,$typehandler))
|
781 |
+
{
|
782 |
+
$hvalue=$ah->$typehandler($pid,$item,$store_id,$attrcode,$attrdesc,$ivalue);
|
783 |
+
}
|
784 |
+
//if handlers returned a value that is not "__MAGMI_UNHANDLED__" , we have our output value
|
785 |
+
if(isset($hvalue) && $hvalue!="__MAGMI_UNHANDLED__")
|
786 |
+
{
|
787 |
+
$ovalue=$hvalue;
|
788 |
+
break;
|
789 |
+
}
|
790 |
+
}
|
791 |
+
}
|
792 |
+
//if __MAGMI_UNHANDLED__ ,don't insert anything
|
793 |
+
if($ovalue=="__MAGMI_UNHANDLED__")
|
794 |
+
{
|
795 |
+
$ovalue=false;
|
796 |
+
}
|
797 |
+
//if handled value is a "DELETE"
|
798 |
+
if($ovalue=="__MAGMI_DELETE__")
|
799 |
+
{
|
800 |
+
$deletes[]=$attid;
|
801 |
+
}
|
802 |
+
else
|
803 |
+
//if we have something to do with this value
|
804 |
+
if($ovalue!==false)
|
805 |
+
{
|
806 |
+
|
807 |
+
$data[]=$this->prod_etype;
|
808 |
+
$data[]=$attid;
|
809 |
+
$data[]=$store_id;
|
810 |
+
$data[]=$pid;
|
811 |
+
$data[]=$ovalue;
|
812 |
+
$insstr="(?,?,?,?,?)";
|
813 |
+
$inserts[]=$insstr;
|
814 |
+
}
|
815 |
+
|
816 |
+
//if one of the store in the list is admin
|
817 |
+
if($store_id==0)
|
818 |
+
{
|
819 |
+
$sids=$store_ids;
|
820 |
+
//remove all values bound to the other stores for this attribute,so that they default to "use admin value"
|
821 |
+
array_shift($sids);
|
822 |
+
if(count($sids)>0)
|
823 |
+
{
|
824 |
+
$sidlist=implode(",",$sids);
|
825 |
+
$ddata=array($this->prod_etype,$attid,$pid);
|
826 |
+
$sql="DELETE FROM $cpet WHERE entity_type_id=? AND attribute_id=? AND store_id IN ($sidlist) AND entity_id=?";
|
827 |
+
$this->delete($sql,$ddata);
|
828 |
+
unset($ddata);
|
829 |
+
}
|
830 |
+
unset($sids);
|
831 |
+
break;
|
832 |
+
}
|
833 |
+
}
|
834 |
+
}
|
835 |
+
|
836 |
+
|
837 |
+
|
838 |
+
if(!empty($inserts))
|
839 |
+
{
|
840 |
+
//now perform insert for all values of the the current backend type in one
|
841 |
+
//single insert
|
842 |
+
$sql="INSERT INTO $cpet
|
843 |
+
(`entity_type_id`, `attribute_id`, `store_id`, `entity_id`, `value`)
|
844 |
+
VALUES ";
|
845 |
+
$sql.=implode(",",$inserts);
|
846 |
+
//this one taken from mysql log analysis of magento import
|
847 |
+
//smart one :)
|
848 |
+
$sql.=" ON DUPLICATE KEY UPDATE `value`=VALUES(`value`)";
|
849 |
+
$this->insert($sql,$data);
|
850 |
+
}
|
851 |
+
|
852 |
+
if(!empty($deletes))
|
853 |
+
{
|
854 |
+
$sidlist=implode(",",$store_ids);
|
855 |
+
$attidlist=implode(",",$deletes);
|
856 |
+
$sql="DELETE FROM $cpet WHERE entity_type_id=? AND attribute_id IN ($attidlist) AND store_id IN ($sidlist) AND entity_id=?";
|
857 |
+
$this->delete($sql,array($this->prod_etype,$pid));
|
858 |
+
}
|
859 |
+
|
860 |
+
if(empty($deletes) && empty($inserts) && $isnew)
|
861 |
+
{
|
862 |
+
if(!$this->_same)
|
863 |
+
{
|
864 |
+
$this->log("No $tp Attributes created for sku ".$item["sku"],"warning");
|
865 |
+
}
|
866 |
+
}
|
867 |
+
unset($store_ids);
|
868 |
+
unset($data);
|
869 |
+
unset($inserts);
|
870 |
+
unset($deletes);
|
871 |
+
}
|
872 |
+
return $this->_extra_attrs;
|
873 |
+
}
|
874 |
+
|
875 |
+
|
876 |
+
|
877 |
+
/**
|
878 |
+
* update product stock
|
879 |
+
* @param int $pid : product id
|
880 |
+
* @param array $item : attribute values for product indexed by attribute_code
|
881 |
+
*/
|
882 |
+
public function updateStock($pid,$item,$isnew)
|
883 |
+
{
|
884 |
+
|
885 |
+
$scols=$this->getStockCols();
|
886 |
+
#take only stock columns that are in item
|
887 |
+
$itstockcols=array_intersect(array_keys($item),$scols);
|
888 |
+
#no stock columns set, item exists, no stock update needed.
|
889 |
+
if(count($itstockcols)==0 && !$isnew)
|
890 |
+
{
|
891 |
+
return;
|
892 |
+
}
|
893 |
+
$csit=$this->tablename("cataloginventory_stock_item");
|
894 |
+
$css=$this->tablename("cataloginventory_stock_status");
|
895 |
+
#calculate is_in_stock flag
|
896 |
+
if(isset($item["qty"]))
|
897 |
+
{
|
898 |
+
if(!isset($item["manage_stock"]))
|
899 |
+
{
|
900 |
+
$item["manage_stock"]=1;
|
901 |
+
$item["use_config_manage_stock"]=0;
|
902 |
+
}
|
903 |
+
|
904 |
+
$mqty=(isset($item["min_qty"])?$item["min_qty"]:0);
|
905 |
+
$is_in_stock=isset($item["is_in_stock"])?$item["is_in_stock"]:($item["qty"]>$mqty?1:0);
|
906 |
+
if(!$is_in_stock && $item["qty"]>$mqty)
|
907 |
+
{
|
908 |
+
$is_in_stock=1;
|
909 |
+
}
|
910 |
+
$item["is_in_stock"]=$is_in_stock;
|
911 |
+
}
|
912 |
+
#take only stock columns that are in item after item update
|
913 |
+
$common=array_intersect(array_keys($item),$scols);
|
914 |
+
|
915 |
+
#create stock item line if needed
|
916 |
+
$stock_id=(isset($item["stock_id"])?$item["stock_id"]:1);
|
917 |
+
$sql="INSERT IGNORE INTO `$csit` (product_id,stock_id) VALUES (?,?)";
|
918 |
+
$this->insert($sql,array($pid,$stock_id));
|
919 |
+
|
920 |
+
if(count($common)>0)
|
921 |
+
{
|
922 |
+
$cols=$this->arr2columns($common);
|
923 |
+
$stockvals=$this->filterkvarr($item,$common);
|
924 |
+
|
925 |
+
#fill with values
|
926 |
+
$svstr=$this->arr2update($stockvals);
|
927 |
+
if(isset($item["qty"]))
|
928 |
+
{
|
929 |
+
$relqty=NULL;
|
930 |
+
//test for relative qty
|
931 |
+
if($item["qty"][0]=="+" || $item["qty"][0]=="-")
|
932 |
+
{
|
933 |
+
$relqty=getRelative($item["qty"]);
|
934 |
+
}
|
935 |
+
//if relative qty
|
936 |
+
if($relqty!=NULL)
|
937 |
+
{
|
938 |
+
//update UPDATE statement value affectation
|
939 |
+
$svstr=preg_replace("/(^|,)qty=\?/","$1qty=qty$relqty?",$svstr);
|
940 |
+
$stockvals["qty"]=$item["qty"];
|
941 |
+
$svstr=str_replace("is_in_stock=?","is_in_stock=(qty>min_qty)",$svstr);
|
942 |
+
unset($stockvals["is_in_stock"]);
|
943 |
+
}
|
944 |
+
}
|
945 |
+
$sql="UPDATE `$csit` SET $svstr WHERE product_id=? AND stock_id=?";
|
946 |
+
$this->update($sql,array_merge(array_values($stockvals),array($pid,$stock_id)));
|
947 |
+
}
|
948 |
+
|
949 |
+
$data=array();
|
950 |
+
$wsids=$this->getItemWebsites($item);
|
951 |
+
$csscols=array("website_id","product_id","stock_id","qty","stock_status");
|
952 |
+
$cssvals=$this->filterkvarr($item,$csscols);
|
953 |
+
$stock_id=(isset($cssvals["stock_id"])?$cssvals["stock_id"]:1);
|
954 |
+
$stock_status=(isset($cssvals["stock_status"])?$cssvals["stock_status"]:1);
|
955 |
+
//new auto synchro on lat inserted stock item values for stock status.
|
956 |
+
//also works for multiple stock ids.
|
957 |
+
$sql="INSERT INTO `$css` SELECT csit.product_id,ws.website_id,cis.stock_id,csit.qty,? as stock_status
|
958 |
+
FROM `$csit` as csit
|
959 |
+
JOIN ".$this->tablename("core_website")." as ws ON ws.website_id IN (".$this->arr2values($wsids).")
|
960 |
+
JOIN ".$this->tablename("cataloginventory_stock")." as cis ON cis.stock_id=?
|
961 |
+
WHERE product_id=?
|
962 |
+
ON DUPLICATE KEY UPDATE stock_status=VALUES(`stock_status`),qty=VALUES(`qty`)";
|
963 |
+
$data[]=$stock_status;
|
964 |
+
$data=array_merge($data,$wsids);
|
965 |
+
$data[]=$stock_id;
|
966 |
+
$data[]=$pid;
|
967 |
+
$this->insert($sql,$data);
|
968 |
+
unset($data);
|
969 |
+
}
|
970 |
+
/**
|
971 |
+
* assign categories for a given product id from values
|
972 |
+
* categories should already be created & csv values should be as the ones
|
973 |
+
* given in the magento export (ie: comma separated ids, minus 1,2)
|
974 |
+
* @param int $pid : product id
|
975 |
+
* @param array $item : attribute values for product indexed by attribute_code
|
976 |
+
*/
|
977 |
+
public function assignCategories($pid,$item)
|
978 |
+
{
|
979 |
+
$cce=$this->tablename("catalog_category_entity");
|
980 |
+
$ccpt=$this->tablename("catalog_category_product");
|
981 |
+
#handle assignment reset
|
982 |
+
if(!isset($item["category_reset"]) || $item["category_reset"]==1)
|
983 |
+
{
|
984 |
+
$sql="DELETE $ccpt.*
|
985 |
+
FROM $ccpt
|
986 |
+
JOIN $cce ON $cce.entity_id=$ccpt.category_id
|
987 |
+
WHERE product_id=?";
|
988 |
+
$this->delete($sql,$pid);
|
989 |
+
}
|
990 |
+
|
991 |
+
|
992 |
+
$inserts=array();
|
993 |
+
$data=array();
|
994 |
+
$cdata=array();
|
995 |
+
$ddata=array();
|
996 |
+
$cpos=array();
|
997 |
+
$catids=csl2arr($item["category_ids"]);
|
998 |
+
|
999 |
+
//find positive category assignments
|
1000 |
+
|
1001 |
+
foreach($catids as $catdef)
|
1002 |
+
{
|
1003 |
+
$a=explode("::",$catdef);
|
1004 |
+
$catid=$a[0];
|
1005 |
+
$catpos=(count($a)>1?$a[1]:"0");
|
1006 |
+
$rel=getRelative($catid);
|
1007 |
+
if($rel=="-")
|
1008 |
+
{
|
1009 |
+
$ddata[]=$catid;
|
1010 |
+
}
|
1011 |
+
else
|
1012 |
+
{
|
1013 |
+
$cdata[]=$catid;
|
1014 |
+
$cpos[]=$catpos;
|
1015 |
+
}
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
//get all "real ids"
|
1019 |
+
$rcatids=$this->selectAll("SELECT cce.entity_id as id FROM $cce as cce WHERE cce.entity_id IN (".$this->arr2values($cdata).")",$cdata);
|
1020 |
+
$vcatids=array();
|
1021 |
+
foreach($rcatids as $rcatrow)
|
1022 |
+
{
|
1023 |
+
$vcatids[]=$rcatrow['id'];
|
1024 |
+
}
|
1025 |
+
//now get the diff
|
1026 |
+
$diff=array_diff($cdata,$vcatids);
|
1027 |
+
//if there are some, warning
|
1028 |
+
if(count($diff)>0)
|
1029 |
+
{
|
1030 |
+
$this->log('Invalid category ids found for sku '.$item['sku'].":".implode(",",$diff),"warning");
|
1031 |
+
}
|
1032 |
+
|
1033 |
+
$cdata=$vcatids;
|
1034 |
+
if(count($cdata)==0)
|
1035 |
+
{
|
1036 |
+
$this->log('No valid categories found, skip category assingment for sku '.$item['sku'],"warning");
|
1037 |
+
}
|
1038 |
+
|
1039 |
+
#now we have verified ids
|
1040 |
+
for($i=0;$i<count($cdata);$i++)
|
1041 |
+
{
|
1042 |
+
$inserts[]="(?,?,?)";
|
1043 |
+
$data[]=$cdata[$i];
|
1044 |
+
$data[]=$pid;
|
1045 |
+
$data[]=$cpos[$i];
|
1046 |
+
}
|
1047 |
+
|
1048 |
+
#peform deletion of removed category affectation
|
1049 |
+
if(count($ddata)>0)
|
1050 |
+
{
|
1051 |
+
$sql="DELETE FROM $ccpt WHERE category_id IN (".$this->arr2values($ddata).") AND product_id=?";
|
1052 |
+
$ddata[]=$pid;
|
1053 |
+
$this->delete($sql,$ddata);
|
1054 |
+
unset($ddata);
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
|
1058 |
+
|
1059 |
+
#create new category assignment for products, if multi store with repeated ids
|
1060 |
+
#ignore duplicates
|
1061 |
+
if(count($inserts)>0)
|
1062 |
+
{
|
1063 |
+
$sql="INSERT INTO $ccpt (`category_id`,`product_id`,`position`)
|
1064 |
+
VALUES ";
|
1065 |
+
$sql.=implode(",",$inserts);
|
1066 |
+
$sql.="ON DUPLICATE KEY UPDATE position=VALUES(`position`)";
|
1067 |
+
$this->insert($sql,$data);
|
1068 |
+
unset($data);
|
1069 |
+
}
|
1070 |
+
unset($deletes);
|
1071 |
+
unset($inserts);
|
1072 |
+
}
|
1073 |
+
|
1074 |
+
|
1075 |
+
public function getItemWebsites($item,$default=false)
|
1076 |
+
{
|
1077 |
+
if(!isset($item['store']))
|
1078 |
+
{
|
1079 |
+
$item['store']="admin";
|
1080 |
+
}
|
1081 |
+
$k=$item["store"];
|
1082 |
+
|
1083 |
+
if(!isset($this->_wsids[$k]))
|
1084 |
+
{
|
1085 |
+
$this->_wsids[$k]=array();
|
1086 |
+
$cs=$this->tablename("core_store");
|
1087 |
+
if(trim($k)!="admin")
|
1088 |
+
{
|
1089 |
+
$scodes=csl2arr($k);
|
1090 |
+
$qcolstr=$this->arr2values($scodes);
|
1091 |
+
$rows=$this->selectAll("SELECT website_id FROM $cs WHERE code IN ($qcolstr) AND store_id!=0 GROUP BY website_id",$scodes);
|
1092 |
+
}
|
1093 |
+
else
|
1094 |
+
{
|
1095 |
+
$rows=$this->selectAll("SELECT website_id FROM $cs WHERE store_id!=0 GROUP BY website_id ");
|
1096 |
+
}
|
1097 |
+
foreach($rows as $row)
|
1098 |
+
{
|
1099 |
+
$this->_wsids[$k][]=$row['website_id'];
|
1100 |
+
}
|
1101 |
+
}
|
1102 |
+
return $this->_wsids[$k];
|
1103 |
+
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
/**
|
1107 |
+
* set website of product if not exists
|
1108 |
+
* @param int $pid : product id
|
1109 |
+
* @param array $item : attribute values for product indexed by attribute_code
|
1110 |
+
*/
|
1111 |
+
public function updateWebSites($pid,$item)
|
1112 |
+
{
|
1113 |
+
$wsids=$this->getItemWebsites($item);
|
1114 |
+
$qcolstr=$this->arr2values($wsids);
|
1115 |
+
$cpst=$this->tablename("catalog_product_website");
|
1116 |
+
$cws=$this->tablename("core_website");
|
1117 |
+
//associate product with all websites in a single multi insert (use ignore to avoid duplicates)
|
1118 |
+
$sql="INSERT IGNORE INTO `$cpst` (`product_id`, `website_id`) SELECT ?,website_id FROM $cws WHERE website_id IN ($qcolstr)";
|
1119 |
+
$this->insert($sql,array_merge(array($pid),$wsids));
|
1120 |
+
}
|
1121 |
+
|
1122 |
+
|
1123 |
+
|
1124 |
+
public function clearOptCache()
|
1125 |
+
{
|
1126 |
+
unset($this->_optidcache);
|
1127 |
+
$this->_optidcache=array();
|
1128 |
+
}
|
1129 |
+
|
1130 |
+
public function onNewSku($sku,$existing)
|
1131 |
+
{
|
1132 |
+
$this->clearOptCache();
|
1133 |
+
//only assign values to store 0 by default in create mode for new sku
|
1134 |
+
//for store related options
|
1135 |
+
if(!$existing)
|
1136 |
+
{
|
1137 |
+
$this->_dstore=array(0);
|
1138 |
+
}
|
1139 |
+
else
|
1140 |
+
{
|
1141 |
+
$this->_dstore=array();
|
1142 |
+
}
|
1143 |
+
$this->_same=false;
|
1144 |
+
}
|
1145 |
+
|
1146 |
+
public function onSameSku($sku)
|
1147 |
+
{
|
1148 |
+
unset($this->_dstore);
|
1149 |
+
$this->_dstore=array();
|
1150 |
+
$this->_same=true;
|
1151 |
+
}
|
1152 |
+
|
1153 |
+
|
1154 |
+
public function getItemIds($item)
|
1155 |
+
{
|
1156 |
+
$sku=$item["sku"];
|
1157 |
+
if($sku!=$this->_curitemids["sku"])
|
1158 |
+
{
|
1159 |
+
//try to find item ids in db
|
1160 |
+
$cids=$this->getProductIds($sku);
|
1161 |
+
if($cids!==false)
|
1162 |
+
{
|
1163 |
+
//if found use it
|
1164 |
+
$this->_curitemids=$cids;
|
1165 |
+
}
|
1166 |
+
else
|
1167 |
+
{
|
1168 |
+
//only sku & attribute set id from datasource otherwise.
|
1169 |
+
$this->_curitemids=array("pid"=>null,"sku"=>$sku,"asid"=>isset($item["attribute_set"])?$this->getAttributeSetId($item["attribute_set"]):$this->default_asid);
|
1170 |
+
}
|
1171 |
+
//do not reset values for existing if non admin
|
1172 |
+
$this->onNewSku($sku,($cids!==false));
|
1173 |
+
unset($cids);
|
1174 |
+
}
|
1175 |
+
else
|
1176 |
+
{
|
1177 |
+
$this->onSameSku($sku);
|
1178 |
+
}
|
1179 |
+
return $this->_curitemids;
|
1180 |
+
}
|
1181 |
+
|
1182 |
+
public function handleIgnore(&$item)
|
1183 |
+
{
|
1184 |
+
//filter __MAGMI_IGNORE__ COLUMNS
|
1185 |
+
foreach($item as $k=>$v)
|
1186 |
+
{
|
1187 |
+
if($v=="__MAGMI_IGNORE__")
|
1188 |
+
{
|
1189 |
+
unset($item[$k]);
|
1190 |
+
}
|
1191 |
+
}
|
1192 |
+
}
|
1193 |
+
public function findItemStores($pid)
|
1194 |
+
{
|
1195 |
+
$sql="SELECT cs.code FROM ".$this->tablename("catalog_product_website")." AS cpw".
|
1196 |
+
" JOIN ".$this->tablename("core_store")." as cs ON cs.website_id=cpw.website_id".
|
1197 |
+
" WHERE cpw.product_id=?";
|
1198 |
+
$result=$this->selectAll($sql,array($pid));
|
1199 |
+
$scodes=array();
|
1200 |
+
foreach($result as $row)
|
1201 |
+
{
|
1202 |
+
$scodes[]=$row["code"];
|
1203 |
+
}
|
1204 |
+
return implode(",",$scodes);
|
1205 |
+
}
|
1206 |
+
|
1207 |
+
public function checkItemStores($scodes)
|
1208 |
+
{
|
1209 |
+
if($scodes=="admin")
|
1210 |
+
{
|
1211 |
+
return $scodes;
|
1212 |
+
}
|
1213 |
+
|
1214 |
+
$scarr=explode(",",$scodes);
|
1215 |
+
trimarray($scarr);
|
1216 |
+
$rscode=array();
|
1217 |
+
$sql="SELECT code FROM ".$this->tablename("core_store")." WHERE code IN (".$this->arr2values($scarr).")";
|
1218 |
+
$result=$this->selectAll($sql,$scarr);
|
1219 |
+
$rscodes=array();
|
1220 |
+
foreach($result as $row)
|
1221 |
+
{
|
1222 |
+
$rscodes[]=$row["code"];
|
1223 |
+
}
|
1224 |
+
$diff=array_diff($scarr, $rscodes);
|
1225 |
+
$out="";
|
1226 |
+
if(count($diff)>0)
|
1227 |
+
{
|
1228 |
+
$out="Invalid store code(s) found:".implode(",",$diff);
|
1229 |
+
}
|
1230 |
+
if($out!="")
|
1231 |
+
{
|
1232 |
+
if(count($rscodes)==0)
|
1233 |
+
{
|
1234 |
+
$out.=", NO VALID STORE FOUND";
|
1235 |
+
}
|
1236 |
+
$this->log($out,"warning");
|
1237 |
+
}
|
1238 |
+
|
1239 |
+
return implode(",",$rscodes);
|
1240 |
+
}
|
1241 |
+
|
1242 |
+
public function checkstore(&$item,$pid,$isnew)
|
1243 |
+
{
|
1244 |
+
//we have store column set , just check
|
1245 |
+
if(isset($item["store"]) && trim($item["store"])!="")
|
1246 |
+
{
|
1247 |
+
$scodes=$this->checkItemStores($item["store"]);
|
1248 |
+
}
|
1249 |
+
else
|
1250 |
+
{
|
1251 |
+
$scodes="admin";
|
1252 |
+
}
|
1253 |
+
if($scodes=="")
|
1254 |
+
{
|
1255 |
+
return false;
|
1256 |
+
}
|
1257 |
+
$item["store"]=$scodes;
|
1258 |
+
return true;
|
1259 |
+
}
|
1260 |
+
/**
|
1261 |
+
* full import workflow for item
|
1262 |
+
* @param array $item : attribute values for product indexed by attribute_code
|
1263 |
+
*/
|
1264 |
+
public function importItem($item)
|
1265 |
+
{
|
1266 |
+
|
1267 |
+
$this->handleIgnore($item);
|
1268 |
+
if(Magmi_StateManager::getState()=="canceled")
|
1269 |
+
{
|
1270 |
+
exit();
|
1271 |
+
}
|
1272 |
+
//first step
|
1273 |
+
|
1274 |
+
if(!$this->callPlugins("itemprocessors","processItemBeforeId",$item))
|
1275 |
+
{
|
1276 |
+
return false;
|
1277 |
+
}
|
1278 |
+
|
1279 |
+
//check if sku has been reset
|
1280 |
+
if(!isset($item["sku"]) || trim($item["sku"])=='')
|
1281 |
+
{
|
1282 |
+
$this->log('No sku info found for record #'.$this->_current_row,"error");
|
1283 |
+
return false;
|
1284 |
+
}
|
1285 |
+
//handle "computed" ignored columns
|
1286 |
+
$this->handleIgnore($item);
|
1287 |
+
//get Item identifiers in magento
|
1288 |
+
$itemids=$this->getItemIds($item);
|
1289 |
+
|
1290 |
+
//extract product id & attribute set id
|
1291 |
+
$pid=$itemids["pid"];
|
1292 |
+
$asid=$itemids["asid"];
|
1293 |
+
|
1294 |
+
$isnew=false;
|
1295 |
+
if(isset($pid) && $this->mode=="xcreate")
|
1296 |
+
{
|
1297 |
+
$this->log("skipping existing sku:{$item["sku"]} - xcreate mode set","skip");
|
1298 |
+
return false;
|
1299 |
+
}
|
1300 |
+
|
1301 |
+
if(!isset($pid))
|
1302 |
+
{
|
1303 |
+
|
1304 |
+
if($this->mode!=='update')
|
1305 |
+
{
|
1306 |
+
if(!isset($asid))
|
1307 |
+
{
|
1308 |
+
$this->log("cannot create product sku:{$item["sku"]}, no attribute_set defined","error");
|
1309 |
+
return false;
|
1310 |
+
}
|
1311 |
+
$pid=$this->createProduct($item,$asid);
|
1312 |
+
$this->_curitemids["pid"]=$pid;
|
1313 |
+
$isnew=true;
|
1314 |
+
}
|
1315 |
+
else
|
1316 |
+
{
|
1317 |
+
//mode is update, do nothing
|
1318 |
+
$this->log("skipping unknown sku:{$item["sku"]} - update mode set","skip");
|
1319 |
+
return false;
|
1320 |
+
}
|
1321 |
+
}
|
1322 |
+
else
|
1323 |
+
{
|
1324 |
+
$this->updateProduct($item,$pid);
|
1325 |
+
}
|
1326 |
+
|
1327 |
+
try
|
1328 |
+
{
|
1329 |
+
if(!$this->callPlugins("itemprocessors","processItemAfterId",$item,array("product_id"=>$pid,"new"=>$isnew,"same"=>$this->_same,"asid"=>$asid)))
|
1330 |
+
{
|
1331 |
+
return false;
|
1332 |
+
}
|
1333 |
+
|
1334 |
+
|
1335 |
+
|
1336 |
+
if(count($item)==0)
|
1337 |
+
{
|
1338 |
+
return true;
|
1339 |
+
}
|
1340 |
+
//handle "computed" ignored columns from afterImport
|
1341 |
+
$this->handleIgnore($item);
|
1342 |
+
|
1343 |
+
if(!$this->checkstore($item,$pid,$isnew))
|
1344 |
+
{
|
1345 |
+
$this->log("invalid store value, skipping item sku:".$item["sku"]);
|
1346 |
+
return false;
|
1347 |
+
}
|
1348 |
+
//create new ones
|
1349 |
+
$attrmap=$this->attrbytype;
|
1350 |
+
do
|
1351 |
+
{
|
1352 |
+
$attrmap=$this->createAttributes($pid,$item,$attrmap,$isnew);
|
1353 |
+
}
|
1354 |
+
while(count($attrmap)>0);
|
1355 |
+
|
1356 |
+
if(!testempty($item,"category_ids"))
|
1357 |
+
{
|
1358 |
+
//assign categories
|
1359 |
+
$this->assignCategories($pid,$item);
|
1360 |
+
}
|
1361 |
+
|
1362 |
+
//update websites
|
1363 |
+
if($this->mode!="update")
|
1364 |
+
{
|
1365 |
+
$this->updateWebSites($pid,$item);
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
if(!$this->_same)
|
1369 |
+
{
|
1370 |
+
//update stock
|
1371 |
+
$this->updateStock($pid,$item,$isnew);
|
1372 |
+
}
|
1373 |
+
|
1374 |
+
$this->touchProduct($pid);
|
1375 |
+
//ok,we're done
|
1376 |
+
if(!$this->callPlugins("itemprocessors","processItemAfterImport",$item,array("product_id"=>$pid,"new"=>$isnew,"same"=>$this->_same)))
|
1377 |
+
{
|
1378 |
+
return false;
|
1379 |
+
}
|
1380 |
+
}
|
1381 |
+
catch(Exception $e)
|
1382 |
+
{
|
1383 |
+
$this->callPlugins(array("itemprocessors"),"processItemException",$item,array("exception"=>$e));
|
1384 |
+
$this->logException($e,$this->_laststmt->queryString);
|
1385 |
+
throw $e;
|
1386 |
+
}
|
1387 |
+
return true;
|
1388 |
+
}
|
1389 |
+
|
1390 |
+
public function getProperties()
|
1391 |
+
{
|
1392 |
+
return $this->_props;
|
1393 |
+
}
|
1394 |
+
|
1395 |
+
/**
|
1396 |
+
* count lines of csv file
|
1397 |
+
* @param string $csvfile filename
|
1398 |
+
*/
|
1399 |
+
public function lookup()
|
1400 |
+
{
|
1401 |
+
$t0=microtime(true);
|
1402 |
+
$this->log("Performing Datasouce Lookup...","startup");
|
1403 |
+
|
1404 |
+
$count=$this->datasource->getRecordsCount();
|
1405 |
+
$t1=microtime(true);
|
1406 |
+
$time=$t1-$t0;
|
1407 |
+
$this->log("$count:$time","lookup");
|
1408 |
+
$this->log("Found $count records, took $time sec","startup");
|
1409 |
+
|
1410 |
+
return $count;
|
1411 |
+
}
|
1412 |
+
|
1413 |
+
|
1414 |
+
|
1415 |
+
public function updateProduct($item,$pid)
|
1416 |
+
{
|
1417 |
+
$tname=$this->tablename('catalog_product_entity');
|
1418 |
+
if(isset($item['type']))
|
1419 |
+
{
|
1420 |
+
$item['type_id']=$item['type'];
|
1421 |
+
}
|
1422 |
+
$item['entity_type_id']=$this->prod_etype;
|
1423 |
+
$item['updated_at']=strftime("%Y-%m-%d %H:%M:%S");
|
1424 |
+
$columns=array_intersect(array_keys($item), $this->getProdCols());
|
1425 |
+
$values=$this->filterkvarr($item, $columns);
|
1426 |
+
|
1427 |
+
$sql="UPDATE `$tname` SET ".$this->arr2update($values). " WHERE entity_id=?";
|
1428 |
+
|
1429 |
+
$this->update($sql,array_merge(array_values($values),array($pid)));
|
1430 |
+
|
1431 |
+
}
|
1432 |
+
|
1433 |
+
public function getProductEntityType()
|
1434 |
+
{
|
1435 |
+
return $this->prod_etype;
|
1436 |
+
}
|
1437 |
+
|
1438 |
+
public function getCurrentRow()
|
1439 |
+
{
|
1440 |
+
return $this->_current_row;
|
1441 |
+
}
|
1442 |
+
|
1443 |
+
public function setCurrentRow($cnum)
|
1444 |
+
{
|
1445 |
+
$this->_current_row=$cnum;
|
1446 |
+
}
|
1447 |
+
|
1448 |
+
public function isLastItem($item)
|
1449 |
+
{
|
1450 |
+
return isset($item["__MAGMI_LAST__"]);
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
public function setLastItem(&$item)
|
1454 |
+
{
|
1455 |
+
$item["__MAGMI_LAST__"]=1;
|
1456 |
+
}
|
1457 |
+
|
1458 |
+
public function engineInit($params)
|
1459 |
+
{
|
1460 |
+
$this->_profile=$this->getParam($params,"profile","default");
|
1461 |
+
//create an instance of local magento directory handler
|
1462 |
+
//this instance will autoregister in factory
|
1463 |
+
$mdh=new LocalMagentoDirHandler(Magmi_Config::getInstance()->getMagentoDir());
|
1464 |
+
|
1465 |
+
$this->initPlugins($this->_profile);
|
1466 |
+
$this->mode=$this->getParam($params,"mode","update");
|
1467 |
+
|
1468 |
+
}
|
1469 |
+
|
1470 |
+
|
1471 |
+
public function reportStats($nrow,&$tstart,&$tdiff,&$lastdbtime,&$lastrec)
|
1472 |
+
{
|
1473 |
+
$tend=microtime(true);
|
1474 |
+
$this->log($nrow." - ".($tend-$tstart)." - ".($tend-$tdiff),"itime");
|
1475 |
+
$this->log($this->_nreq." - ".($this->_indbtime)." - ".($this->_indbtime-$lastdbtime)." - ".($this->_nreq-$lastrec),"dbtime");
|
1476 |
+
$lastrec=$this->_nreq;
|
1477 |
+
$lastdbtime=$this->_indbtime;
|
1478 |
+
$tdiff=microtime(true);
|
1479 |
+
}
|
1480 |
+
|
1481 |
+
|
1482 |
+
|
1483 |
+
public function initImport($params)
|
1484 |
+
{
|
1485 |
+
$this->log("MAGMI by dweeves - version:".Magmi_Version::$version,"title");
|
1486 |
+
$this->log("Import Profile:$this->_profile","startup");
|
1487 |
+
$this->log("Import Mode:$this->mode","startup");
|
1488 |
+
$this->log("step:".$this->getProp("GLOBAL","step",0.5)."%","step");
|
1489 |
+
//intialize store id cache
|
1490 |
+
$this->connectToMagento();
|
1491 |
+
try
|
1492 |
+
{
|
1493 |
+
$this->initProdType();
|
1494 |
+
$this->createPlugins($this->_profile,$params);
|
1495 |
+
$this->_registerPluginLoopCallback("processItemAfterId", "onPluginProcessedItemAfterId");
|
1496 |
+
$this->callPlugins("datasources,itemprocessors","startImport");
|
1497 |
+
$this->resetSkuStats();
|
1498 |
+
}
|
1499 |
+
catch(Exception $e)
|
1500 |
+
{
|
1501 |
+
$this->disconnectFromMagento();
|
1502 |
+
}
|
1503 |
+
}
|
1504 |
+
|
1505 |
+
public function onPluginProcessedItemAfterId($plinst,&$item,$plresult)
|
1506 |
+
{
|
1507 |
+
$this->handleIgnore($item);
|
1508 |
+
}
|
1509 |
+
|
1510 |
+
public function exitImport()
|
1511 |
+
{
|
1512 |
+
$this->callPlugins("datasources,general,itemprocessors","endImport");
|
1513 |
+
$this->callPlugins("datasources,general,itemprocessors","afterImport");
|
1514 |
+
$this->disconnectFromMagento();
|
1515 |
+
}
|
1516 |
+
|
1517 |
+
public function updateSkuStats($res)
|
1518 |
+
{
|
1519 |
+
if(!$this->_same)
|
1520 |
+
{
|
1521 |
+
$this->_skustats["nsku"]++;
|
1522 |
+
if($res["ok"])
|
1523 |
+
{
|
1524 |
+
$this->_skustats["ok"]++;
|
1525 |
+
}
|
1526 |
+
else
|
1527 |
+
{
|
1528 |
+
$this->_skustats["ko"]++;
|
1529 |
+
}
|
1530 |
+
}
|
1531 |
+
}
|
1532 |
+
public function getDataSource()
|
1533 |
+
{
|
1534 |
+
return $this->getPluginInstance("datasources");
|
1535 |
+
|
1536 |
+
}
|
1537 |
+
|
1538 |
+
public function processDataSourceLine($item,$rstep,&$tstart,&$tdiff,&$lastdbtime,&$lastrec)
|
1539 |
+
{
|
1540 |
+
//counter
|
1541 |
+
$res=array("ok"=>0,"last"=>0);
|
1542 |
+
$this->_current_row++;
|
1543 |
+
if($this->_current_row%$rstep==0)
|
1544 |
+
{
|
1545 |
+
$this->reportStats($this->_current_row,$tstart,$tdiff,$lastdbtime,$lastrec);
|
1546 |
+
}
|
1547 |
+
try
|
1548 |
+
{
|
1549 |
+
if(is_array($item) && count($item)>0)
|
1550 |
+
{
|
1551 |
+
//import item
|
1552 |
+
$this->beginTransaction();
|
1553 |
+
$importedok=$this->importItem($item);
|
1554 |
+
if($importedok)
|
1555 |
+
{
|
1556 |
+
$res["ok"]=true;
|
1557 |
+
$this->commitTransaction();
|
1558 |
+
}
|
1559 |
+
else
|
1560 |
+
{
|
1561 |
+
$res["ok"]=false;
|
1562 |
+
$this->rollbackTransaction();
|
1563 |
+
|
1564 |
+
}
|
1565 |
+
}
|
1566 |
+
else
|
1567 |
+
{
|
1568 |
+
$this->log("ERROR - RECORD #$this->_current_row - INVALID RECORD","error");
|
1569 |
+
}
|
1570 |
+
//intermediary measurement
|
1571 |
+
|
1572 |
+
}
|
1573 |
+
catch(Exception $e)
|
1574 |
+
{
|
1575 |
+
$this->rollbackTransaction();
|
1576 |
+
$res["ok"]=false;
|
1577 |
+
$this->logException($e,"ERROR ON RECORD #$this->_current_row");
|
1578 |
+
}
|
1579 |
+
if($this->isLastItem($item))
|
1580 |
+
{
|
1581 |
+
unset($item);
|
1582 |
+
$res["last"]=1;
|
1583 |
+
}
|
1584 |
+
|
1585 |
+
unset($item);
|
1586 |
+
$this->updateSkuStats($res);
|
1587 |
+
|
1588 |
+
return $res;
|
1589 |
+
|
1590 |
+
}
|
1591 |
+
|
1592 |
+
public function resetSkuStats()
|
1593 |
+
{
|
1594 |
+
$this->_skustats=array("nsku"=>0,"ok"=>0,"ko"=>0);
|
1595 |
+
}
|
1596 |
+
|
1597 |
+
|
1598 |
+
public function engineRun($params,$forcebuiltin=array())
|
1599 |
+
{
|
1600 |
+
|
1601 |
+
$this->log("Import Profile:$this->_profile","startup");
|
1602 |
+
$this->log("Import Mode:$this->mode","startup");
|
1603 |
+
$this->log("step:".$this->getProp("GLOBAL","step",0.5)."%","step");
|
1604 |
+
$this->createPlugins($this->_profile,$params);
|
1605 |
+
$this->datasource=$this->getDataSource();
|
1606 |
+
$this->callPlugins("datasources,general","beforeImport");
|
1607 |
+
$nitems=$this->lookup();
|
1608 |
+
Magmi_StateManager::setState("running");
|
1609 |
+
//if some rows found
|
1610 |
+
if($nitems>0)
|
1611 |
+
{
|
1612 |
+
$this->resetSkuStats();
|
1613 |
+
//intialize store id cache
|
1614 |
+
$this->callPlugins("datasources,itemprocessors","startImport");
|
1615 |
+
//initializing item processors
|
1616 |
+
$cols=$this->datasource->getColumnNames();
|
1617 |
+
$this->log(count($cols),"columns");
|
1618 |
+
$this->callPlugins("itemprocessors","processColumnList",$cols);
|
1619 |
+
$this->log("Ajusted processed columns:".count($cols),"startup");
|
1620 |
+
$this->initProdType();
|
1621 |
+
//initialize attribute infos & indexes from column names
|
1622 |
+
if($this->mode!="update")
|
1623 |
+
{
|
1624 |
+
$this->checkRequired($cols);
|
1625 |
+
}
|
1626 |
+
$this->initAttrInfos(array_values($cols));
|
1627 |
+
//counter
|
1628 |
+
$this->_current_row=0;
|
1629 |
+
//start time
|
1630 |
+
$tstart=microtime(true);
|
1631 |
+
//differential
|
1632 |
+
$tdiff=$tstart;
|
1633 |
+
//intermediary report step
|
1634 |
+
$this->initDbqStats();
|
1635 |
+
$pstep=$this->getProp("GLOBAL","step",0.5);
|
1636 |
+
$rstep=ceil(($nitems*$pstep)/100);
|
1637 |
+
//read each line
|
1638 |
+
$lastrec=0;
|
1639 |
+
$lastdbtime=0;
|
1640 |
+
while(($item=$this->datasource->getNextRecord())!==false)
|
1641 |
+
{
|
1642 |
+
$res=$this->processDataSourceLine($item, $rstep,$tstart,$tdiff,$lastdbtime,$lastrec);
|
1643 |
+
//break on "forced" last
|
1644 |
+
if($res["last"])
|
1645 |
+
{
|
1646 |
+
break;
|
1647 |
+
}
|
1648 |
+
}
|
1649 |
+
$this->callPlugins("datasources,general,itemprocessors","endImport");
|
1650 |
+
$this->reportStats($this->_current_row,$tstart,$tdiff,$lastdbtime,$lastrec);
|
1651 |
+
$this->log("Skus imported OK:".$this->_skustats["ok"]."/".$this->_skustats["nsku"],"info");
|
1652 |
+
if($this->_skustats["ko"]>0)
|
1653 |
+
{
|
1654 |
+
$this->log("Skus imported KO:".$this->_skustats["ko"]."/".$this->_skustats["nsku"],"warning");
|
1655 |
+
}
|
1656 |
+
}
|
1657 |
+
else
|
1658 |
+
{
|
1659 |
+
$this->log("No Records returned by datasource","warning");
|
1660 |
+
}
|
1661 |
+
$this->callPlugins("datasources,general,itemprocessors","afterImport");
|
1662 |
+
|
1663 |
+
$this->log("Import Ended","end");
|
1664 |
+
Magmi_StateManager::setState("idle");
|
1665 |
+
}
|
1666 |
+
|
1667 |
+
public function onEngineException($e)
|
1668 |
+
{
|
1669 |
+
if(isset($this->datasource))
|
1670 |
+
{
|
1671 |
+
$this->datasource->onException($e);
|
1672 |
+
}
|
1673 |
+
$this->log("Import Ended","end");
|
1674 |
+
|
1675 |
+
Magmi_StateManager::setState("idle");
|
1676 |
+
}
|
1677 |
+
|
1678 |
+
}
|
lib/Magmi/engines/magmi_utilityengine.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
17 |
+
/* Magmi ProductImporter is now a Magmi_Engine instance */
|
18 |
+
class Magmi_UtilityEngine extends Magmi_Engine
|
19 |
+
{
|
20 |
+
|
21 |
+
/**
|
22 |
+
* constructor
|
23 |
+
* @param string $conffile : configuration .ini filename
|
24 |
+
*/
|
25 |
+
public function __construct()
|
26 |
+
{
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getEnabledPluginClasses($profile)
|
30 |
+
{
|
31 |
+
$clist=Magmi_PluginHelper::getInstance("main")->getPluginsInfo("utilities","class");
|
32 |
+
return $clist;
|
33 |
+
}
|
34 |
+
|
35 |
+
public function getEngineInfo()
|
36 |
+
{
|
37 |
+
return array("name"=>"Magmi Utilities Engine","version"=>"1.0.1","author"=>"dweeves");
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* load properties
|
42 |
+
* @param string $conf : configuration .ini filename
|
43 |
+
*/
|
44 |
+
|
45 |
+
public function getPluginFamilies()
|
46 |
+
{
|
47 |
+
return array("utilities");
|
48 |
+
}
|
49 |
+
|
50 |
+
public function engineInit($params)
|
51 |
+
{
|
52 |
+
$this->initPlugins(null);
|
53 |
+
}
|
54 |
+
|
55 |
+
public function engineRun($params)
|
56 |
+
{
|
57 |
+
$this->log("Magento Mass Importer by dweeves - version:".Magmi_Version::$version,"title");
|
58 |
+
//initialize db connectivity
|
59 |
+
Magmi_StateManager::setState("running");
|
60 |
+
//force only one class to run
|
61 |
+
$this->_pluginclasses=array("utilities"=>array($params["pluginclass"]));
|
62 |
+
|
63 |
+
$this->createPlugins("__utilities__",$params);
|
64 |
+
foreach($this->_activeplugins["utilities"] as $pinst)
|
65 |
+
{
|
66 |
+
try
|
67 |
+
{
|
68 |
+
$pinst->runUtility();
|
69 |
+
}
|
70 |
+
catch(Exception $e)
|
71 |
+
{
|
72 |
+
$this->logException($e);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
Magmi_StateManager::setState("idle");
|
77 |
+
}
|
78 |
+
|
79 |
+
public function onEngineException($e)
|
80 |
+
{
|
81 |
+
Magmi_StateManager::setState("idle");
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
lib/Magmi/inc/dbhelper.class.php
ADDED
@@ -0,0 +1,593 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
class DBHelper
|
10 |
+
{
|
11 |
+
protected $_db;
|
12 |
+
protected $_debug;
|
13 |
+
protected $_laststmt;
|
14 |
+
protected $_use_stmt_cache=true;
|
15 |
+
protected $_nreq;
|
16 |
+
protected $_indbtime;
|
17 |
+
protected $_intrans=false;
|
18 |
+
protected $prepared=array();
|
19 |
+
/**
|
20 |
+
* Intializes database connection
|
21 |
+
* @param string $host : hostname
|
22 |
+
* @param string $dbname : database name
|
23 |
+
* @param string $user : username
|
24 |
+
* @param string $pass : password
|
25 |
+
* @param bool $debug : debug mode
|
26 |
+
*/
|
27 |
+
public function initDb($host,$dbname,$user,$pass,$port=3306,$socket="/tmp/mysql.sock",$conntype="net",$debug=false)
|
28 |
+
{
|
29 |
+
//intialize connection with PDO
|
30 |
+
//fix by Mr Lei for UTF8 special chars
|
31 |
+
if($conntype=="net")
|
32 |
+
{
|
33 |
+
$pdostr="mysql:host=$host;port=$port;dbname=$dbname;charset=utf8";
|
34 |
+
}
|
35 |
+
else
|
36 |
+
{
|
37 |
+
$pdostr="mysql:unix_socket=$socket;dbname=$dbname;charset=utf8";
|
38 |
+
}
|
39 |
+
|
40 |
+
//FB: patch for magento
|
41 |
+
$this->_db = Mage::getSingleton('core/resource')->getConnection('core_write')->getConnection();
|
42 |
+
/*
|
43 |
+
$this->_db=new PDO($pdostr, $user, $pass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
|
44 |
+
//use exception error mode
|
45 |
+
$this->_db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
|
46 |
+
$this->_db->setAttribute(PDO::ATTR_ORACLE_NULLS ,PDO::NULL_NATURAL);
|
47 |
+
$this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC);
|
48 |
+
*/
|
49 |
+
|
50 |
+
//set database debug mode to trace if necessary
|
51 |
+
$this->_debug=$debug;
|
52 |
+
$this->prepared=array();
|
53 |
+
|
54 |
+
}
|
55 |
+
/**
|
56 |
+
*
|
57 |
+
* store output in some debug file
|
58 |
+
* @param unknown_type $data
|
59 |
+
*/
|
60 |
+
public function logdebug($data)
|
61 |
+
{
|
62 |
+
if($this->_debug)
|
63 |
+
{
|
64 |
+
$f=fopen($this->_debugfile,"a");
|
65 |
+
fwrite($f,microtime());
|
66 |
+
fwrite($f,$data);
|
67 |
+
fwrite($f,"\n");
|
68 |
+
fclose($f);
|
69 |
+
}
|
70 |
+
}
|
71 |
+
/**
|
72 |
+
*
|
73 |
+
* Sets or unsets the usage of internal prepared statement cache for reuse
|
74 |
+
* @param boolean $uc true:use cache,false:do not use cache
|
75 |
+
*/
|
76 |
+
public function usestmtcache($uc)
|
77 |
+
{
|
78 |
+
$this->_use_stmt_cache=$uc;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* releases database connection
|
83 |
+
*/
|
84 |
+
public function exitDb()
|
85 |
+
{
|
86 |
+
//clear PDO resource
|
87 |
+
$this->_db=NULL;
|
88 |
+
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
*
|
93 |
+
* Helper method to try to guess mysql socket based on some tricky phpinfo analysis
|
94 |
+
* @throws Exception if something got wrong during detection
|
95 |
+
*/
|
96 |
+
public static function getMysqlSocket()
|
97 |
+
{
|
98 |
+
$mysqlsock="";
|
99 |
+
$old_track = ini_set('track_errors', '1');
|
100 |
+
try
|
101 |
+
{
|
102 |
+
$mysqlsock=ini_get("mysql.default_socket");
|
103 |
+
|
104 |
+
if(isset($mysqlsock) && !@file_exists($mysqlsock))
|
105 |
+
{
|
106 |
+
if(error_get_last()!==null)
|
107 |
+
{
|
108 |
+
throw new Exception();
|
109 |
+
}
|
110 |
+
ob_start();
|
111 |
+
phpinfo();
|
112 |
+
$data=ob_get_contents();
|
113 |
+
ob_end_clean();
|
114 |
+
$cap=preg_match("/MYSQL_SOCKET.*?<td .*?>(.*?)<\/td>/msi",$data,$matches);
|
115 |
+
if($cap)
|
116 |
+
{
|
117 |
+
$mysqlsock=$matches[1];
|
118 |
+
}
|
119 |
+
}
|
120 |
+
if(isset($mysqlsock) && !@file_exists($mysqlsock))
|
121 |
+
{
|
122 |
+
$mysqlsock="";
|
123 |
+
}
|
124 |
+
|
125 |
+
}
|
126 |
+
catch(Exception $e)
|
127 |
+
{
|
128 |
+
}
|
129 |
+
if(error_get_last()!==null)
|
130 |
+
{
|
131 |
+
$mysqlsock=false;
|
132 |
+
}
|
133 |
+
ini_set('track_errors',$old_track);
|
134 |
+
return $mysqlsock;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
*
|
139 |
+
* Initializes database requests stats counters
|
140 |
+
*/
|
141 |
+
public function initDbqStats()
|
142 |
+
{
|
143 |
+
$this->_nreq=0;
|
144 |
+
$this->_indbtime=0;
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
*
|
149 |
+
* Enter description here ...
|
150 |
+
* @param unknown_type $nbreq
|
151 |
+
*/
|
152 |
+
public function collectDbqStats(&$nbreq)
|
153 |
+
{
|
154 |
+
return $this->_nreq;
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* cache sorting comparison method
|
159 |
+
*
|
160 |
+
* @param unknown_type $a
|
161 |
+
* @param unknown_type $b
|
162 |
+
*/
|
163 |
+
public function cachesort($a,$b)
|
164 |
+
{
|
165 |
+
return $b[1]-$a[1];
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Garbages statement cache if above 500 , removes less used statements
|
170 |
+
* Enter description here ...
|
171 |
+
*/
|
172 |
+
public function garbageStmtCache()
|
173 |
+
{
|
174 |
+
if(count($this->prepared)>=500)
|
175 |
+
{
|
176 |
+
uasort($this->prepared,array($this,"cachesort"));
|
177 |
+
array_splice($this->prepared,350,count($this->prepared));
|
178 |
+
}
|
179 |
+
}
|
180 |
+
/**
|
181 |
+
* executes an sql statement
|
182 |
+
* @param string $sql : sql statement (may include ? placeholders or named variables)
|
183 |
+
* @param array $params : parameters to replace placeholders (can be null)
|
184 |
+
* @param boolean $close : auto close cursor after statement execution (defaults to true)
|
185 |
+
* @return PDOStatement : statement for further processing if needed
|
186 |
+
*/
|
187 |
+
public function exec_stmt($sql,$params=null,$close=true)
|
188 |
+
{
|
189 |
+
$this->_nreq++;
|
190 |
+
$t0=microtime(true);
|
191 |
+
|
192 |
+
if($this->_use_stmt_cache && strpos($sql,"'")==false)
|
193 |
+
{
|
194 |
+
//if sql not in statement cache
|
195 |
+
if(!isset($this->prepared[$sql]))
|
196 |
+
{
|
197 |
+
$this->garbageStmtCache();
|
198 |
+
//create new prepared statement
|
199 |
+
$stmt=$this->_db->prepare($sql);
|
200 |
+
//cache prepare statement
|
201 |
+
$this->prepared[$sql]=array($stmt,1);
|
202 |
+
}
|
203 |
+
else
|
204 |
+
{
|
205 |
+
//get from statement cache
|
206 |
+
$this->prepared[$sql][1]++;
|
207 |
+
$stmt=$this->prepared[$sql][0];
|
208 |
+
}
|
209 |
+
}
|
210 |
+
else
|
211 |
+
{
|
212 |
+
//create new prepared statement
|
213 |
+
$stmt=$this->_db->prepare($sql);
|
214 |
+
}
|
215 |
+
$this->_laststmt=$stmt;
|
216 |
+
if($params!=null)
|
217 |
+
{
|
218 |
+
if(!$this->is_assoc($params))
|
219 |
+
{
|
220 |
+
$params=is_array($params)?$params:array($params);
|
221 |
+
$stmt->execute($params);
|
222 |
+
}
|
223 |
+
else
|
224 |
+
{
|
225 |
+
foreach($params as $pname=>$pval)
|
226 |
+
{
|
227 |
+
if(count(explode(":",$pname))==1)
|
228 |
+
{
|
229 |
+
$val=strval($pval);
|
230 |
+
$stmt->bindValue(":$pname",$val);
|
231 |
+
}
|
232 |
+
}
|
233 |
+
$stmt->execute();
|
234 |
+
}
|
235 |
+
}
|
236 |
+
else
|
237 |
+
{
|
238 |
+
|
239 |
+
$stmt->execute();
|
240 |
+
}
|
241 |
+
if($close)
|
242 |
+
{
|
243 |
+
$stmt->closeCursor();
|
244 |
+
}
|
245 |
+
$t1=microtime(true);
|
246 |
+
$this->_indbtime+=$t1-$t0;
|
247 |
+
$this->logdebug("$sql\n".print_r($params,true));
|
248 |
+
unset($params);
|
249 |
+
return $stmt;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Perform a delete statement, sql should be "DELETE"
|
254 |
+
* @param string $sql : DELETE statement sql (placeholders allowed)
|
255 |
+
* @param array $params : placeholder replacements (can be null)
|
256 |
+
*/
|
257 |
+
public function delete($sql,$params=null)
|
258 |
+
{
|
259 |
+
$this->exec_stmt($sql,$params);
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Performs an update statement
|
264 |
+
* Enter description here ...
|
265 |
+
* @param string $sql UPDATE statement sql (placeholder allowed)
|
266 |
+
* @param array $params parameter values if placeholders in SQL
|
267 |
+
*/
|
268 |
+
public function update($sql,$params=null)
|
269 |
+
{
|
270 |
+
$this->exec_stmt($sql,$params);
|
271 |
+
}
|
272 |
+
/**
|
273 |
+
* Perform an insert , sql should be "INSERT"
|
274 |
+
* @param string $sql :INSERT statement SQL (placeholders allowed)
|
275 |
+
* @param array $params : placeholder replacements (can be null)
|
276 |
+
* @return mixed : last inserted id
|
277 |
+
*/
|
278 |
+
public function insert($sql,$params=null)
|
279 |
+
{
|
280 |
+
$this->exec_stmt($sql,$params);
|
281 |
+
$liid=$this->_db->lastInsertId();
|
282 |
+
return $liid;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Perform a select ,sql should be "SELECT"
|
287 |
+
* @param string $sql :SELECT statement SQL (placeholders allowed)
|
288 |
+
* @param array $params : placeholder replacements (can be null)
|
289 |
+
* @return PDOStatement : statement instance for further processing
|
290 |
+
*/
|
291 |
+
public function select($sql,$params=null)
|
292 |
+
{
|
293 |
+
return $this->exec_stmt($sql,$params,false);
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Selects one unique value from one single row
|
298 |
+
* @param $sql : SELECT statement SQL (placeholders allowed)
|
299 |
+
* @param $params :placeholder replacements (can be null)
|
300 |
+
* @param $col : column value to retrieve
|
301 |
+
* @return mixed : null if not result , wanted column value if match
|
302 |
+
*/
|
303 |
+
public function selectone($sql,$params,$col)
|
304 |
+
{
|
305 |
+
$stmt=$this->select($sql,$params);
|
306 |
+
$t0=microtime(true);
|
307 |
+
|
308 |
+
$r=$stmt->fetch(PDO::FETCH_ASSOC);
|
309 |
+
$stmt->closeCursor();
|
310 |
+
$t1=microtime(true);
|
311 |
+
$this->_indbtime+=$t1-$t0;
|
312 |
+
$v=(is_array($r)?$r[$col]:null);
|
313 |
+
unset($r);
|
314 |
+
return $v;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Selects all values from a statement into a php array
|
319 |
+
* @param unknown_type $sql sql select to execute
|
320 |
+
* @param unknown_type $params placeholder replacements (can be null)
|
321 |
+
*/
|
322 |
+
public function selectAll($sql,$params=null)
|
323 |
+
{
|
324 |
+
$stmt=$this->select($sql,$params);
|
325 |
+
$t0=microtime(true);
|
326 |
+
|
327 |
+
$r=$stmt->fetchAll(PDO::FETCH_ASSOC);
|
328 |
+
$stmt->closeCursor();
|
329 |
+
$t1=microtime(true);
|
330 |
+
$this->_indbtime+=$t1-$t0;
|
331 |
+
return $r;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* test if value exists (test should be compatible with unique select)
|
336 |
+
* @param $sql : SELECT statement SQL (placeholders allowed)
|
337 |
+
* @param $params :placeholder replacements (can be null)
|
338 |
+
* @param $col : column value to retrieve
|
339 |
+
* @return boolean : true if value found, false otherwise
|
340 |
+
*/
|
341 |
+
public function testexists($sql,$params,$col)
|
342 |
+
{
|
343 |
+
return $this->selectone($sql,$params,$col)!=null;
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Quote array values in order to be used as parameters (handy if array used directly in explode in a IN condition)
|
348 |
+
* Enter description here ...
|
349 |
+
* @param array $arr array of values to be quoted
|
350 |
+
*/
|
351 |
+
public function quotearr($arr)
|
352 |
+
{
|
353 |
+
$arrout=array();
|
354 |
+
foreach($arr as $v)
|
355 |
+
{
|
356 |
+
$arrout[]=$this->_db->quote($v);
|
357 |
+
}
|
358 |
+
return $arrout;
|
359 |
+
}
|
360 |
+
|
361 |
+
/**
|
362 |
+
*
|
363 |
+
* transforms an array in a comma separated list of enclosed column names for request
|
364 |
+
* @param array $arr list of names to enclose
|
365 |
+
*/
|
366 |
+
public function arr2columns($arr)
|
367 |
+
{
|
368 |
+
$arrout=array();
|
369 |
+
foreach($arr as $cname)
|
370 |
+
{
|
371 |
+
$arrout[]="`".$cname."`";
|
372 |
+
}
|
373 |
+
$colstr=implode(",",$arrout);
|
374 |
+
unset($arrout);
|
375 |
+
return $colstr;
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
*
|
380 |
+
* transform an array of values into equivalent comma separated list of unnamed placeholders.
|
381 |
+
* @param array $arr
|
382 |
+
*/
|
383 |
+
public function arr2values($arr)
|
384 |
+
{
|
385 |
+
$str=substr(str_repeat("?,",count($arr)),0,-1);
|
386 |
+
return $str;
|
387 |
+
}
|
388 |
+
|
389 |
+
/**
|
390 |
+
*
|
391 |
+
* transform a list of values into static select to use it as SQL static resultset
|
392 |
+
* @param array $arr list of values to use as SQL dataset
|
393 |
+
* @param string $cname sql column name to use to represent dataset
|
394 |
+
*/
|
395 |
+
public function arr2select($arr,$cname="id")
|
396 |
+
{
|
397 |
+
$rpt=str_repeat("? AS $cname UNION SELECT ",count($arr));
|
398 |
+
$subsel=substr($rpt,0,-1*strlen(" UNION SELECT "));
|
399 |
+
return "(SELECT $subsel)";
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
*
|
404 |
+
* transform a associative array into a list of update prepared placeholders
|
405 |
+
* @param array $arr associative array to prepare for update , array keys used as column to update
|
406 |
+
*/
|
407 |
+
public function arr2update($arr)
|
408 |
+
{
|
409 |
+
$arrout=array();
|
410 |
+
foreach($arr as $k=>$v)
|
411 |
+
{
|
412 |
+
$arrout[]="$k=?";
|
413 |
+
}
|
414 |
+
$updstr=implode(",",$arrout);
|
415 |
+
unset($arrout);
|
416 |
+
return $updstr;
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
*
|
421 |
+
* Enter description here ...
|
422 |
+
* @param unknown_type $kvarr
|
423 |
+
* @param unknown_type $keys
|
424 |
+
*/
|
425 |
+
public function filterkvarr($kvarr,$keys)
|
426 |
+
{
|
427 |
+
$out=array();
|
428 |
+
foreach($keys as $k)
|
429 |
+
{
|
430 |
+
$out[$k]=isset($kvarr[$k])?$kvarr[$k]:null;
|
431 |
+
}
|
432 |
+
return $out;
|
433 |
+
}
|
434 |
+
|
435 |
+
/**
|
436 |
+
* begins a transaction
|
437 |
+
*/
|
438 |
+
public function beginTransaction()
|
439 |
+
{
|
440 |
+
$this->_db->beginTransaction();
|
441 |
+
$this->_intrans=true;
|
442 |
+
$this->logdebug("-- TRANSACTION BEGIN --");
|
443 |
+
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* commits the current transaction
|
448 |
+
*/
|
449 |
+
public function commitTransaction()
|
450 |
+
{
|
451 |
+
$this->_db->commit();
|
452 |
+
$this->_intrans=false;
|
453 |
+
$this->logdebug("-- TRANSACTION COMMIT --");
|
454 |
+
|
455 |
+
}
|
456 |
+
|
457 |
+
/**
|
458 |
+
* rollback the current transaction
|
459 |
+
*/
|
460 |
+
public function rollbackTransaction()
|
461 |
+
{
|
462 |
+
if($this->_intrans)
|
463 |
+
{
|
464 |
+
$this->_db->rollBack();
|
465 |
+
$this->_intrans=false;
|
466 |
+
$this->logdebug("-- TRANSACTION ROLLBACK --");
|
467 |
+
|
468 |
+
}
|
469 |
+
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
*
|
474 |
+
* Sets debug management
|
475 |
+
* @param bool $debug debug flag
|
476 |
+
* @param string $debugfname debug file name to use
|
477 |
+
*/
|
478 |
+
public function setDebug($debug,$debugfname)
|
479 |
+
{
|
480 |
+
$this->_debug=$debug;
|
481 |
+
$this->_debugfile=$debugfname;
|
482 |
+
}
|
483 |
+
|
484 |
+
/**
|
485 |
+
*
|
486 |
+
* Replaces named params in a descriptive parameterized request
|
487 |
+
* Descriptive parameterized request have parameters defined as
|
488 |
+
* [namespace:name/label/default value] , this parameters may represent table names or any request parameter
|
489 |
+
* namespace is optional, as label & default value
|
490 |
+
* - NameSpaces:
|
491 |
+
* tn : tablename, this namespace ensures replacement of given name with defined DB prefix so, parameterized request can use generic names to define their ops
|
492 |
+
*
|
493 |
+
* @param unknown_type $stmt
|
494 |
+
* @param unknown_type $rparams
|
495 |
+
*/
|
496 |
+
public function replaceParams(&$stmt,&$rparams)
|
497 |
+
{
|
498 |
+
$params=array();
|
499 |
+
$hasp=preg_match_all('|\[\[(.*?)\]\]|msi',$stmt,$matches);
|
500 |
+
if($hasp)
|
501 |
+
{
|
502 |
+
$pdefs=$matches[0];
|
503 |
+
$params=$matches[1];
|
504 |
+
|
505 |
+
}
|
506 |
+
for($i=0;$i<count($params);$i++)
|
507 |
+
{
|
508 |
+
$param=$params[$i];
|
509 |
+
$pdef=$pdefs[$i];
|
510 |
+
$pinfo=explode("/",$param);
|
511 |
+
$pname=$pinfo[0];
|
512 |
+
$epar=explode(":",$pname);
|
513 |
+
if(count($epar)>1)
|
514 |
+
{
|
515 |
+
$stmt=str_replace($pdef,$rparams[$pname],$stmt);
|
516 |
+
}
|
517 |
+
else
|
518 |
+
{
|
519 |
+
$stmt=str_replace($pdef,":$pname",$stmt);
|
520 |
+
}
|
521 |
+
}
|
522 |
+
for($i=0;$i<count($params);$i++)
|
523 |
+
{
|
524 |
+
$param=$params[$i];
|
525 |
+
$pinfo=explode("/",$param);
|
526 |
+
$pname=$pinfo[0];
|
527 |
+
$epar=explode(":",$pname);
|
528 |
+
if(count($epar)>1)
|
529 |
+
{
|
530 |
+
unset($rparams[$pname]);
|
531 |
+
}
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
*
|
537 |
+
* Checks wether an array is associative
|
538 |
+
* @param mixed $var array or variable to test
|
539 |
+
*/
|
540 |
+
public function is_assoc($var) {
|
541 |
+
return is_array($var) && array_keys($var)!==range(0,sizeof($var)-1);
|
542 |
+
}
|
543 |
+
|
544 |
+
/**
|
545 |
+
*
|
546 |
+
* This method handled mutiple statements in a single SQL (PDO cannot do it by itself)
|
547 |
+
* Statements have to be separed by ; & line return.
|
548 |
+
* @param string $sql multiple statements
|
549 |
+
* @param array $params values to use for parameter placeholder, in case of named parameters,array has to have array keys aligned with parameter names
|
550 |
+
*/
|
551 |
+
public function multipleParamRequests($sql,$params,$return=false)
|
552 |
+
{
|
553 |
+
//ensure windows/mac compatibility for user made requests
|
554 |
+
$sql=str_replace("\r\n","\n",$sql);
|
555 |
+
$sqllines=explode("--",$sql);
|
556 |
+
foreach($sqllines as $sqlline)
|
557 |
+
{
|
558 |
+
if($sqlline!="")
|
559 |
+
{
|
560 |
+
$subs=explode(";\n","--".$sqlline);
|
561 |
+
foreach($subs as $sub)
|
562 |
+
{
|
563 |
+
|
564 |
+
if(trim($sub)!="" && substr($sub,0,2)!="--")
|
565 |
+
{
|
566 |
+
$stmts[]=$sub;
|
567 |
+
}
|
568 |
+
}
|
569 |
+
}
|
570 |
+
}
|
571 |
+
$results=array();
|
572 |
+
foreach($stmts as $stmt)
|
573 |
+
{
|
574 |
+
$zparams=$params;
|
575 |
+
$this->replaceParams($stmt,$zparams);
|
576 |
+
if($return)
|
577 |
+
{
|
578 |
+
if(substr(trim($stmt),0,6)=="SELECT")
|
579 |
+
{
|
580 |
+
$results[$stmt]=$this->selectAll($stmt,$zparams);
|
581 |
+
continue;
|
582 |
+
}
|
583 |
+
}
|
584 |
+
$this->exec_stmt($stmt,$zparams);
|
585 |
+
}
|
586 |
+
if($return)
|
587 |
+
{
|
588 |
+
return $results;
|
589 |
+
}
|
590 |
+
}
|
591 |
+
|
592 |
+
|
593 |
+
}
|
lib/Magmi/inc/dbhelper.class.php~
ADDED
@@ -0,0 +1,589 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
class DBHelper
|
10 |
+
{
|
11 |
+
protected $_db;
|
12 |
+
protected $_debug;
|
13 |
+
protected $_laststmt;
|
14 |
+
protected $_use_stmt_cache=true;
|
15 |
+
protected $_nreq;
|
16 |
+
protected $_indbtime;
|
17 |
+
protected $_intrans=false;
|
18 |
+
protected $prepared=array();
|
19 |
+
/**
|
20 |
+
* Intializes database connection
|
21 |
+
* @param string $host : hostname
|
22 |
+
* @param string $dbname : database name
|
23 |
+
* @param string $user : username
|
24 |
+
* @param string $pass : password
|
25 |
+
* @param bool $debug : debug mode
|
26 |
+
*/
|
27 |
+
public function initDb($host,$dbname,$user,$pass,$port=3306,$socket="/tmp/mysql.sock",$conntype="net",$debug=false)
|
28 |
+
{
|
29 |
+
//intialize connection with PDO
|
30 |
+
//fix by Mr Lei for UTF8 special chars
|
31 |
+
if($conntype=="net")
|
32 |
+
{
|
33 |
+
$pdostr="mysql:host=$host;port=$port;dbname=$dbname;charset=utf8";
|
34 |
+
}
|
35 |
+
else
|
36 |
+
{
|
37 |
+
$pdostr="mysql:unix_socket=$socket;dbname=$dbname;charset=utf8";
|
38 |
+
}
|
39 |
+
|
40 |
+
$this->_db=new PDO($pdostr, $user, $pass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
|
41 |
+
//use exception error mode
|
42 |
+
$this->_db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
|
43 |
+
$this->_db->setAttribute(PDO::ATTR_ORACLE_NULLS ,PDO::NULL_NATURAL);
|
44 |
+
$this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC);
|
45 |
+
|
46 |
+
//set database debug mode to trace if necessary
|
47 |
+
$this->_debug=$debug;
|
48 |
+
$this->prepared=array();
|
49 |
+
|
50 |
+
}
|
51 |
+
/**
|
52 |
+
*
|
53 |
+
* store output in some debug file
|
54 |
+
* @param unknown_type $data
|
55 |
+
*/
|
56 |
+
public function logdebug($data)
|
57 |
+
{
|
58 |
+
if($this->_debug)
|
59 |
+
{
|
60 |
+
$f=fopen($this->_debugfile,"a");
|
61 |
+
fwrite($f,microtime());
|
62 |
+
fwrite($f,$data);
|
63 |
+
fwrite($f,"\n");
|
64 |
+
fclose($f);
|
65 |
+
}
|
66 |
+
}
|
67 |
+
/**
|
68 |
+
*
|
69 |
+
* Sets or unsets the usage of internal prepared statement cache for reuse
|
70 |
+
* @param boolean $uc true:use cache,false:do not use cache
|
71 |
+
*/
|
72 |
+
public function usestmtcache($uc)
|
73 |
+
{
|
74 |
+
$this->_use_stmt_cache=$uc;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* releases database connection
|
79 |
+
*/
|
80 |
+
public function exitDb()
|
81 |
+
{
|
82 |
+
//clear PDO resource
|
83 |
+
$this->_db=NULL;
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
*
|
89 |
+
* Helper method to try to guess mysql socket based on some tricky phpinfo analysis
|
90 |
+
* @throws Exception if something got wrong during detection
|
91 |
+
*/
|
92 |
+
public static function getMysqlSocket()
|
93 |
+
{
|
94 |
+
$mysqlsock="";
|
95 |
+
$old_track = ini_set('track_errors', '1');
|
96 |
+
try
|
97 |
+
{
|
98 |
+
$mysqlsock=ini_get("mysql.default_socket");
|
99 |
+
|
100 |
+
if(isset($mysqlsock) && !@file_exists($mysqlsock))
|
101 |
+
{
|
102 |
+
if(error_get_last()!==null)
|
103 |
+
{
|
104 |
+
throw new Exception();
|
105 |
+
}
|
106 |
+
ob_start();
|
107 |
+
phpinfo();
|
108 |
+
$data=ob_get_contents();
|
109 |
+
ob_end_clean();
|
110 |
+
$cap=preg_match("/MYSQL_SOCKET.*?<td .*?>(.*?)<\/td>/msi",$data,$matches);
|
111 |
+
if($cap)
|
112 |
+
{
|
113 |
+
$mysqlsock=$matches[1];
|
114 |
+
}
|
115 |
+
}
|
116 |
+
if(isset($mysqlsock) && !@file_exists($mysqlsock))
|
117 |
+
{
|
118 |
+
$mysqlsock="";
|
119 |
+
}
|
120 |
+
|
121 |
+
}
|
122 |
+
catch(Exception $e)
|
123 |
+
{
|
124 |
+
}
|
125 |
+
if(error_get_last()!==null)
|
126 |
+
{
|
127 |
+
$mysqlsock=false;
|
128 |
+
}
|
129 |
+
ini_set('track_errors',$old_track);
|
130 |
+
return $mysqlsock;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
*
|
135 |
+
* Initializes database requests stats counters
|
136 |
+
*/
|
137 |
+
public function initDbqStats()
|
138 |
+
{
|
139 |
+
$this->_nreq=0;
|
140 |
+
$this->_indbtime=0;
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
*
|
145 |
+
* Enter description here ...
|
146 |
+
* @param unknown_type $nbreq
|
147 |
+
*/
|
148 |
+
public function collectDbqStats(&$nbreq)
|
149 |
+
{
|
150 |
+
return $this->_nreq;
|
151 |
+
}
|
152 |
+
|
153 |
+
/**
|
154 |
+
* cache sorting comparison method
|
155 |
+
*
|
156 |
+
* @param unknown_type $a
|
157 |
+
* @param unknown_type $b
|
158 |
+
*/
|
159 |
+
public function cachesort($a,$b)
|
160 |
+
{
|
161 |
+
return $b[1]-$a[1];
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Garbages statement cache if above 500 , removes less used statements
|
166 |
+
* Enter description here ...
|
167 |
+
*/
|
168 |
+
public function garbageStmtCache()
|
169 |
+
{
|
170 |
+
if(count($this->prepared)>=500)
|
171 |
+
{
|
172 |
+
uasort($this->prepared,array($this,"cachesort"));
|
173 |
+
array_splice($this->prepared,350,count($this->prepared));
|
174 |
+
}
|
175 |
+
}
|
176 |
+
/**
|
177 |
+
* executes an sql statement
|
178 |
+
* @param string $sql : sql statement (may include ? placeholders or named variables)
|
179 |
+
* @param array $params : parameters to replace placeholders (can be null)
|
180 |
+
* @param boolean $close : auto close cursor after statement execution (defaults to true)
|
181 |
+
* @return PDOStatement : statement for further processing if needed
|
182 |
+
*/
|
183 |
+
public function exec_stmt($sql,$params=null,$close=true)
|
184 |
+
{
|
185 |
+
$this->_nreq++;
|
186 |
+
$t0=microtime(true);
|
187 |
+
|
188 |
+
if($this->_use_stmt_cache && strpos($sql,"'")==false)
|
189 |
+
{
|
190 |
+
//if sql not in statement cache
|
191 |
+
if(!isset($this->prepared[$sql]))
|
192 |
+
{
|
193 |
+
$this->garbageStmtCache();
|
194 |
+
//create new prepared statement
|
195 |
+
$stmt=$this->_db->prepare($sql);
|
196 |
+
//cache prepare statement
|
197 |
+
$this->prepared[$sql]=array($stmt,1);
|
198 |
+
}
|
199 |
+
else
|
200 |
+
{
|
201 |
+
//get from statement cache
|
202 |
+
$this->prepared[$sql][1]++;
|
203 |
+
$stmt=$this->prepared[$sql][0];
|
204 |
+
}
|
205 |
+
}
|
206 |
+
else
|
207 |
+
{
|
208 |
+
//create new prepared statement
|
209 |
+
$stmt=$this->_db->prepare($sql);
|
210 |
+
}
|
211 |
+
$this->_laststmt=$stmt;
|
212 |
+
if($params!=null)
|
213 |
+
{
|
214 |
+
if(!$this->is_assoc($params))
|
215 |
+
{
|
216 |
+
$params=is_array($params)?$params:array($params);
|
217 |
+
$stmt->execute($params);
|
218 |
+
}
|
219 |
+
else
|
220 |
+
{
|
221 |
+
foreach($params as $pname=>$pval)
|
222 |
+
{
|
223 |
+
if(count(explode(":",$pname))==1)
|
224 |
+
{
|
225 |
+
$val=strval($pval);
|
226 |
+
$stmt->bindValue(":$pname",$val);
|
227 |
+
}
|
228 |
+
}
|
229 |
+
$stmt->execute();
|
230 |
+
}
|
231 |
+
}
|
232 |
+
else
|
233 |
+
{
|
234 |
+
|
235 |
+
$stmt->execute();
|
236 |
+
}
|
237 |
+
if($close)
|
238 |
+
{
|
239 |
+
$stmt->closeCursor();
|
240 |
+
}
|
241 |
+
$t1=microtime(true);
|
242 |
+
$this->_indbtime+=$t1-$t0;
|
243 |
+
$this->logdebug("$sql\n".print_r($params,true));
|
244 |
+
unset($params);
|
245 |
+
return $stmt;
|
246 |
+
}
|
247 |
+
|
248 |
+
/**
|
249 |
+
* Perform a delete statement, sql should be "DELETE"
|
250 |
+
* @param string $sql : DELETE statement sql (placeholders allowed)
|
251 |
+
* @param array $params : placeholder replacements (can be null)
|
252 |
+
*/
|
253 |
+
public function delete($sql,$params=null)
|
254 |
+
{
|
255 |
+
$this->exec_stmt($sql,$params);
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Performs an update statement
|
260 |
+
* Enter description here ...
|
261 |
+
* @param string $sql UPDATE statement sql (placeholder allowed)
|
262 |
+
* @param array $params parameter values if placeholders in SQL
|
263 |
+
*/
|
264 |
+
public function update($sql,$params=null)
|
265 |
+
{
|
266 |
+
$this->exec_stmt($sql,$params);
|
267 |
+
}
|
268 |
+
/**
|
269 |
+
* Perform an insert , sql should be "INSERT"
|
270 |
+
* @param string $sql :INSERT statement SQL (placeholders allowed)
|
271 |
+
* @param array $params : placeholder replacements (can be null)
|
272 |
+
* @return mixed : last inserted id
|
273 |
+
*/
|
274 |
+
public function insert($sql,$params=null)
|
275 |
+
{
|
276 |
+
$this->exec_stmt($sql,$params);
|
277 |
+
$liid=$this->_db->lastInsertId();
|
278 |
+
return $liid;
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Perform a select ,sql should be "SELECT"
|
283 |
+
* @param string $sql :SELECT statement SQL (placeholders allowed)
|
284 |
+
* @param array $params : placeholder replacements (can be null)
|
285 |
+
* @return PDOStatement : statement instance for further processing
|
286 |
+
*/
|
287 |
+
public function select($sql,$params=null)
|
288 |
+
{
|
289 |
+
return $this->exec_stmt($sql,$params,false);
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Selects one unique value from one single row
|
294 |
+
* @param $sql : SELECT statement SQL (placeholders allowed)
|
295 |
+
* @param $params :placeholder replacements (can be null)
|
296 |
+
* @param $col : column value to retrieve
|
297 |
+
* @return mixed : null if not result , wanted column value if match
|
298 |
+
*/
|
299 |
+
public function selectone($sql,$params,$col)
|
300 |
+
{
|
301 |
+
$stmt=$this->select($sql,$params);
|
302 |
+
$t0=microtime(true);
|
303 |
+
|
304 |
+
$r=$stmt->fetch(PDO::FETCH_ASSOC);
|
305 |
+
$stmt->closeCursor();
|
306 |
+
$t1=microtime(true);
|
307 |
+
$this->_indbtime+=$t1-$t0;
|
308 |
+
$v=(is_array($r)?$r[$col]:null);
|
309 |
+
unset($r);
|
310 |
+
return $v;
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Selects all values from a statement into a php array
|
315 |
+
* @param unknown_type $sql sql select to execute
|
316 |
+
* @param unknown_type $params placeholder replacements (can be null)
|
317 |
+
*/
|
318 |
+
public function selectAll($sql,$params=null)
|
319 |
+
{
|
320 |
+
$stmt=$this->select($sql,$params);
|
321 |
+
$t0=microtime(true);
|
322 |
+
|
323 |
+
$r=$stmt->fetchAll(PDO::FETCH_ASSOC);
|
324 |
+
$stmt->closeCursor();
|
325 |
+
$t1=microtime(true);
|
326 |
+
$this->_indbtime+=$t1-$t0;
|
327 |
+
return $r;
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* test if value exists (test should be compatible with unique select)
|
332 |
+
* @param $sql : SELECT statement SQL (placeholders allowed)
|
333 |
+
* @param $params :placeholder replacements (can be null)
|
334 |
+
* @param $col : column value to retrieve
|
335 |
+
* @return boolean : true if value found, false otherwise
|
336 |
+
*/
|
337 |
+
public function testexists($sql,$params,$col)
|
338 |
+
{
|
339 |
+
return $this->selectone($sql,$params,$col)!=null;
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Quote array values in order to be used as parameters (handy if array used directly in explode in a IN condition)
|
344 |
+
* Enter description here ...
|
345 |
+
* @param array $arr array of values to be quoted
|
346 |
+
*/
|
347 |
+
public function quotearr($arr)
|
348 |
+
{
|
349 |
+
$arrout=array();
|
350 |
+
foreach($arr as $v)
|
351 |
+
{
|
352 |
+
$arrout[]=$this->_db->quote($v);
|
353 |
+
}
|
354 |
+
return $arrout;
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
*
|
359 |
+
* transforms an array in a comma separated list of enclosed column names for request
|
360 |
+
* @param array $arr list of names to enclose
|
361 |
+
*/
|
362 |
+
public function arr2columns($arr)
|
363 |
+
{
|
364 |
+
$arrout=array();
|
365 |
+
foreach($arr as $cname)
|
366 |
+
{
|
367 |
+
$arrout[]="`".$cname."`";
|
368 |
+
}
|
369 |
+
$colstr=implode(",",$arrout);
|
370 |
+
unset($arrout);
|
371 |
+
return $colstr;
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
*
|
376 |
+
* transform an array of values into equivalent comma separated list of unnamed placeholders.
|
377 |
+
* @param array $arr
|
378 |
+
*/
|
379 |
+
public function arr2values($arr)
|
380 |
+
{
|
381 |
+
$str=substr(str_repeat("?,",count($arr)),0,-1);
|
382 |
+
return $str;
|
383 |
+
}
|
384 |
+
|
385 |
+
/**
|
386 |
+
*
|
387 |
+
* transform a list of values into static select to use it as SQL static resultset
|
388 |
+
* @param array $arr list of values to use as SQL dataset
|
389 |
+
* @param string $cname sql column name to use to represent dataset
|
390 |
+
*/
|
391 |
+
public function arr2select($arr,$cname="id")
|
392 |
+
{
|
393 |
+
$rpt=str_repeat("? AS $cname UNION SELECT ",count($arr));
|
394 |
+
$subsel=substr($rpt,0,-1*strlen(" UNION SELECT "));
|
395 |
+
return "(SELECT $subsel)";
|
396 |
+
}
|
397 |
+
|
398 |
+
/**
|
399 |
+
*
|
400 |
+
* transform a associative array into a list of update prepared placeholders
|
401 |
+
* @param array $arr associative array to prepare for update , array keys used as column to update
|
402 |
+
*/
|
403 |
+
public function arr2update($arr)
|
404 |
+
{
|
405 |
+
$arrout=array();
|
406 |
+
foreach($arr as $k=>$v)
|
407 |
+
{
|
408 |
+
$arrout[]="$k=?";
|
409 |
+
}
|
410 |
+
$updstr=implode(",",$arrout);
|
411 |
+
unset($arrout);
|
412 |
+
return $updstr;
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
*
|
417 |
+
* Enter description here ...
|
418 |
+
* @param unknown_type $kvarr
|
419 |
+
* @param unknown_type $keys
|
420 |
+
*/
|
421 |
+
public function filterkvarr($kvarr,$keys)
|
422 |
+
{
|
423 |
+
$out=array();
|
424 |
+
foreach($keys as $k)
|
425 |
+
{
|
426 |
+
$out[$k]=isset($kvarr[$k])?$kvarr[$k]:null;
|
427 |
+
}
|
428 |
+
return $out;
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* begins a transaction
|
433 |
+
*/
|
434 |
+
public function beginTransaction()
|
435 |
+
{
|
436 |
+
$this->_db->beginTransaction();
|
437 |
+
$this->_intrans=true;
|
438 |
+
$this->logdebug("-- TRANSACTION BEGIN --");
|
439 |
+
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* commits the current transaction
|
444 |
+
*/
|
445 |
+
public function commitTransaction()
|
446 |
+
{
|
447 |
+
$this->_db->commit();
|
448 |
+
$this->_intrans=false;
|
449 |
+
$this->logdebug("-- TRANSACTION COMMIT --");
|
450 |
+
|
451 |
+
}
|
452 |
+
|
453 |
+
/**
|
454 |
+
* rollback the current transaction
|
455 |
+
*/
|
456 |
+
public function rollbackTransaction()
|
457 |
+
{
|
458 |
+
if($this->_intrans)
|
459 |
+
{
|
460 |
+
$this->_db->rollBack();
|
461 |
+
$this->_intrans=false;
|
462 |
+
$this->logdebug("-- TRANSACTION ROLLBACK --");
|
463 |
+
|
464 |
+
}
|
465 |
+
|
466 |
+
}
|
467 |
+
|
468 |
+
/**
|
469 |
+
*
|
470 |
+
* Sets debug management
|
471 |
+
* @param bool $debug debug flag
|
472 |
+
* @param string $debugfname debug file name to use
|
473 |
+
*/
|
474 |
+
public function setDebug($debug,$debugfname)
|
475 |
+
{
|
476 |
+
$this->_debug=$debug;
|
477 |
+
$this->_debugfile=$debugfname;
|
478 |
+
}
|
479 |
+
|
480 |
+
/**
|
481 |
+
*
|
482 |
+
* Replaces named params in a descriptive parameterized request
|
483 |
+
* Descriptive parameterized request have parameters defined as
|
484 |
+
* [namespace:name/label/default value] , this parameters may represent table names or any request parameter
|
485 |
+
* namespace is optional, as label & default value
|
486 |
+
* - NameSpaces:
|
487 |
+
* tn : tablename, this namespace ensures replacement of given name with defined DB prefix so, parameterized request can use generic names to define their ops
|
488 |
+
*
|
489 |
+
* @param unknown_type $stmt
|
490 |
+
* @param unknown_type $rparams
|
491 |
+
*/
|
492 |
+
public function replaceParams(&$stmt,&$rparams)
|
493 |
+
{
|
494 |
+
$params=array();
|
495 |
+
$hasp=preg_match_all('|\[\[(.*?)\]\]|msi',$stmt,$matches);
|
496 |
+
if($hasp)
|
497 |
+
{
|
498 |
+
$pdefs=$matches[0];
|
499 |
+
$params=$matches[1];
|
500 |
+
|
501 |
+
}
|
502 |
+
for($i=0;$i<count($params);$i++)
|
503 |
+
{
|
504 |
+
$param=$params[$i];
|
505 |
+
$pdef=$pdefs[$i];
|
506 |
+
$pinfo=explode("/",$param);
|
507 |
+
$pname=$pinfo[0];
|
508 |
+
$epar=explode(":",$pname);
|
509 |
+
if(count($epar)>1)
|
510 |
+
{
|
511 |
+
$stmt=str_replace($pdef,$rparams[$pname],$stmt);
|
512 |
+
}
|
513 |
+
else
|
514 |
+
{
|
515 |
+
$stmt=str_replace($pdef,":$pname",$stmt);
|
516 |
+
}
|
517 |
+
}
|
518 |
+
for($i=0;$i<count($params);$i++)
|
519 |
+
{
|
520 |
+
$param=$params[$i];
|
521 |
+
$pinfo=explode("/",$param);
|
522 |
+
$pname=$pinfo[0];
|
523 |
+
$epar=explode(":",$pname);
|
524 |
+
if(count($epar)>1)
|
525 |
+
{
|
526 |
+
unset($rparams[$pname]);
|
527 |
+
}
|
528 |
+
}
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
*
|
533 |
+
* Checks wether an array is associative
|
534 |
+
* @param mixed $var array or variable to test
|
535 |
+
*/
|
536 |
+
public function is_assoc($var) {
|
537 |
+
return is_array($var) && array_keys($var)!==range(0,sizeof($var)-1);
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
*
|
542 |
+
* This method handled mutiple statements in a single SQL (PDO cannot do it by itself)
|
543 |
+
* Statements have to be separed by ; & line return.
|
544 |
+
* @param string $sql multiple statements
|
545 |
+
* @param array $params values to use for parameter placeholder, in case of named parameters,array has to have array keys aligned with parameter names
|
546 |
+
*/
|
547 |
+
public function multipleParamRequests($sql,$params,$return=false)
|
548 |
+
{
|
549 |
+
//ensure windows/mac compatibility for user made requests
|
550 |
+
$sql=str_replace("\r\n","\n",$sql);
|
551 |
+
$sqllines=explode("--",$sql);
|
552 |
+
foreach($sqllines as $sqlline)
|
553 |
+
{
|
554 |
+
if($sqlline!="")
|
555 |
+
{
|
556 |
+
$subs=explode(";\n","--".$sqlline);
|
557 |
+
foreach($subs as $sub)
|
558 |
+
{
|
559 |
+
|
560 |
+
if(trim($sub)!="" && substr($sub,0,2)!="--")
|
561 |
+
{
|
562 |
+
$stmts[]=$sub;
|
563 |
+
}
|
564 |
+
}
|
565 |
+
}
|
566 |
+
}
|
567 |
+
$results=array();
|
568 |
+
foreach($stmts as $stmt)
|
569 |
+
{
|
570 |
+
$zparams=$params;
|
571 |
+
$this->replaceParams($stmt,$zparams);
|
572 |
+
if($return)
|
573 |
+
{
|
574 |
+
if(substr(trim($stmt),0,6)=="SELECT")
|
575 |
+
{
|
576 |
+
$results[$stmt]=$this->selectAll($stmt,$zparams);
|
577 |
+
continue;
|
578 |
+
}
|
579 |
+
}
|
580 |
+
$this->exec_stmt($stmt,$zparams);
|
581 |
+
}
|
582 |
+
if($return)
|
583 |
+
{
|
584 |
+
return $results;
|
585 |
+
}
|
586 |
+
}
|
587 |
+
|
588 |
+
|
589 |
+
}
|
lib/Magmi/inc/fshelper.php
ADDED
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class FSHelper
|
3 |
+
{
|
4 |
+
public static function isDirWritable($dir)
|
5 |
+
{
|
6 |
+
$test=@fopen("$dir/__testwr__","w");
|
7 |
+
if($test==false)
|
8 |
+
{
|
9 |
+
return false;
|
10 |
+
}
|
11 |
+
else
|
12 |
+
{
|
13 |
+
fclose($test);
|
14 |
+
unlink("$dir/__testwr__");
|
15 |
+
}
|
16 |
+
return true;
|
17 |
+
}
|
18 |
+
|
19 |
+
}
|
20 |
+
|
21 |
+
|
22 |
+
|
23 |
+
class MagentoDirHandlerFactory
|
24 |
+
{
|
25 |
+
protected $_handlers=array();
|
26 |
+
protected static $_instance;
|
27 |
+
|
28 |
+
public function __construct()
|
29 |
+
{
|
30 |
+
}
|
31 |
+
|
32 |
+
public static function getInstance()
|
33 |
+
{
|
34 |
+
if(!isset(self::$_instance))
|
35 |
+
{
|
36 |
+
self::$_instance=new MagentoDirHandlerFactory();
|
37 |
+
}
|
38 |
+
return self::$_instance;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function registerHandler($obj)
|
42 |
+
{
|
43 |
+
$cls=get_class($obj);
|
44 |
+
if(!isset($this->_handlers[$cls]))
|
45 |
+
{
|
46 |
+
$this->_handlers[$cls]=$obj;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
public function getHandler($url)
|
51 |
+
{
|
52 |
+
foreach($this->_handlers as $cls=>$handler)
|
53 |
+
{
|
54 |
+
if ($handler->canHandle($url))
|
55 |
+
{
|
56 |
+
return $handler;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
}
|
63 |
+
|
64 |
+
abstract class RemoteFileGetter
|
65 |
+
{
|
66 |
+
protected $_errors;
|
67 |
+
public abstract function urlExists($url);
|
68 |
+
public abstract function copyRemoteFile($url,$dest);
|
69 |
+
public function getErrors()
|
70 |
+
{
|
71 |
+
return $this->_errors;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
class CURL_RemoteFileGetter extends RemoteFileGetter
|
76 |
+
{
|
77 |
+
protected $_curlh;
|
78 |
+
|
79 |
+
public function createContext($url)
|
80 |
+
{
|
81 |
+
if($this->_curlh==NULL)
|
82 |
+
{
|
83 |
+
$curl_url=str_replace(" ","%20",$url);
|
84 |
+
$context = curl_init($curl_url);
|
85 |
+
$this->_curlh=$context;
|
86 |
+
}
|
87 |
+
return $this->_curlh;
|
88 |
+
}
|
89 |
+
|
90 |
+
public function destroyContext($url)
|
91 |
+
{
|
92 |
+
if($this->_curlh!=NULL)
|
93 |
+
{
|
94 |
+
curl_close($this->_curlh);
|
95 |
+
$this->_curlh=NULL;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
public function urlExists($remoteurl)
|
101 |
+
{
|
102 |
+
$context=$this->createContext($remoteurl);
|
103 |
+
//optimized lookup through curl
|
104 |
+
/* head */
|
105 |
+
curl_setopt($context, CURLOPT_HEADER, TRUE);
|
106 |
+
curl_setopt( $context, CURLOPT_RETURNTRANSFER, true );
|
107 |
+
curl_setopt( $context, CURLOPT_CUSTOMREQUEST, 'HEAD' );
|
108 |
+
curl_setopt( $context, CURLOPT_NOBODY, true );
|
109 |
+
|
110 |
+
/* Get the HTML or whatever is linked in $url. */
|
111 |
+
$response = curl_exec($context);
|
112 |
+
|
113 |
+
/* Check for 404 (file not found). */
|
114 |
+
$httpCode = curl_getinfo($context, CURLINFO_HTTP_CODE);
|
115 |
+
$exists = ($httpCode==200);
|
116 |
+
/* retry on error */
|
117 |
+
|
118 |
+
if($httpCode==503 or $httpCode==403)
|
119 |
+
{
|
120 |
+
/* wait for a half second */
|
121 |
+
usleep(500000);
|
122 |
+
$response = curl_exec($context);
|
123 |
+
$httpCode = curl_getinfo($context, CURLINFO_HTTP_CODE);
|
124 |
+
$exists = ($httpCode==200);
|
125 |
+
}
|
126 |
+
return $exists;
|
127 |
+
}
|
128 |
+
|
129 |
+
public function copyRemoteFile($url,$dest)
|
130 |
+
{
|
131 |
+
$this->_errors=array();
|
132 |
+
$ret=true;
|
133 |
+
$context=$this->createContext($url);
|
134 |
+
if(!$this->urlExists($url))
|
135 |
+
{
|
136 |
+
$this->_errors=array("type"=>"download error","message"=>"URL $url is unreachable");
|
137 |
+
return false;
|
138 |
+
}
|
139 |
+
$fp=fopen($dest,"w");
|
140 |
+
//add support for https urls
|
141 |
+
curl_setopt($context, CURLOPT_SSL_VERIFYPEER ,false);
|
142 |
+
curl_setopt($context, CURLOPT_RETURNTRANSFER, false);
|
143 |
+
curl_setopt( $context, CURLOPT_CUSTOMREQUEST, 'GET' );
|
144 |
+
curl_setopt( $context, CURLOPT_NOBODY, false);
|
145 |
+
curl_setopt($context, CURLOPT_FILE, $fp);
|
146 |
+
curl_setopt($context, CURLOPT_HEADER, 0);
|
147 |
+
curl_setopt($context,CURLOPT_FAILONERROR,true);
|
148 |
+
if(!ini_get('safe_mode'))
|
149 |
+
{
|
150 |
+
curl_setopt($context, CURLOPT_FOLLOWLOCATION, 1);
|
151 |
+
}
|
152 |
+
curl_exec($context);
|
153 |
+
if(curl_getinfo($context,CURLINFO_HTTP_CODE)>=400)
|
154 |
+
{
|
155 |
+
$this->_errors=array("type"=>"download error","message"=>curl_error($context));
|
156 |
+
$ret=false;
|
157 |
+
}
|
158 |
+
fclose($fp);
|
159 |
+
return $ret;
|
160 |
+
}
|
161 |
+
}
|
162 |
+
|
163 |
+
class URLFopen_RemoteFileGetter extends RemoteFileGetter
|
164 |
+
{
|
165 |
+
public function urlExists($url)
|
166 |
+
{
|
167 |
+
$fname=$url;
|
168 |
+
$h=@fopen($fname,"r");
|
169 |
+
if($h!==false)
|
170 |
+
{
|
171 |
+
$exists=true;
|
172 |
+
fclose($h);
|
173 |
+
}
|
174 |
+
unset($h);
|
175 |
+
}
|
176 |
+
|
177 |
+
public function copyRemoteFile($url,$dest)
|
178 |
+
{
|
179 |
+
if(!$this->urlExists($url))
|
180 |
+
{
|
181 |
+
$this->_errors=array("type"=>"target error","message"=>"URL $remoteurl is unreachable");
|
182 |
+
return false;
|
183 |
+
}
|
184 |
+
|
185 |
+
$ok=@copy($url,$dest);
|
186 |
+
if(!$ok)
|
187 |
+
{
|
188 |
+
$this->_errors= error_get_last();
|
189 |
+
}
|
190 |
+
return $ok;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
class RemoteFileGetterFactory
|
195 |
+
{
|
196 |
+
|
197 |
+
public static function getFGInstance()
|
198 |
+
{
|
199 |
+
$fginst=NULL;
|
200 |
+
if(function_exists("curl_init"))
|
201 |
+
{
|
202 |
+
$fginst=new CURL_RemoteFileGetter();
|
203 |
+
}
|
204 |
+
else
|
205 |
+
{
|
206 |
+
$fginst=new URLFopen_RemoteFileGetter();
|
207 |
+
}
|
208 |
+
return $fginst;
|
209 |
+
}
|
210 |
+
|
211 |
+
}
|
212 |
+
|
213 |
+
abstract class MagentoDirHandler
|
214 |
+
{
|
215 |
+
protected $_magdir;
|
216 |
+
protected $_lasterror;
|
217 |
+
public function __construct($magurl)
|
218 |
+
{
|
219 |
+
$this->_magdir=$magurl;
|
220 |
+
$this->_lasterror=array();
|
221 |
+
}
|
222 |
+
public function getMagentoDir()
|
223 |
+
{
|
224 |
+
return $this->_magdir;
|
225 |
+
}
|
226 |
+
public abstract function canhandle($url);
|
227 |
+
public abstract function file_exists($filepath);
|
228 |
+
public abstract function mkdir($path,$mask=null,$rec=false);
|
229 |
+
public abstract function copy($srcpath,$destpath);
|
230 |
+
public abstract function unlink($path);
|
231 |
+
public abstract function chmod($path,$mask);
|
232 |
+
public abstract function exec_cmd($cmd,$params,$workingdir = null);
|
233 |
+
}
|
234 |
+
|
235 |
+
class LocalMagentoDirHandler extends MagentoDirHandler
|
236 |
+
{
|
237 |
+
public function __construct($magdir)
|
238 |
+
{
|
239 |
+
parent::__construct($magdir);
|
240 |
+
MagentoDirHandlerFactory::getInstance()->registerHandler($this);
|
241 |
+
}
|
242 |
+
|
243 |
+
public function canHandle($url)
|
244 |
+
{
|
245 |
+
return (preg_match("|^.*?://.*$|",$url)==false);
|
246 |
+
}
|
247 |
+
|
248 |
+
public function file_exists($filename)
|
249 |
+
{
|
250 |
+
$mp=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $filename));
|
251 |
+
|
252 |
+
return file_exists($mp);
|
253 |
+
}
|
254 |
+
|
255 |
+
public function mkdir($path,$mask=null,$rec=false)
|
256 |
+
{
|
257 |
+
$mp=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $path));
|
258 |
+
|
259 |
+
if($mask==null)
|
260 |
+
{
|
261 |
+
$mask=octdec('755');
|
262 |
+
}
|
263 |
+
$ok=@mkdir($mp,$mask,$rec);
|
264 |
+
if(!$ok)
|
265 |
+
{
|
266 |
+
$this->_lasterror=error_get_last();
|
267 |
+
}
|
268 |
+
return $ok;
|
269 |
+
}
|
270 |
+
|
271 |
+
public function chmod($path,$mask)
|
272 |
+
{
|
273 |
+
$mp=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $path));
|
274 |
+
|
275 |
+
if($mask==null)
|
276 |
+
{
|
277 |
+
$mask=octdec('755');
|
278 |
+
}
|
279 |
+
$ok=@chmod($mp,$mask);
|
280 |
+
if(!$ok)
|
281 |
+
{
|
282 |
+
$this->_lasterror=error_get_last();
|
283 |
+
}
|
284 |
+
return $ok;
|
285 |
+
}
|
286 |
+
|
287 |
+
public function getLastError()
|
288 |
+
{
|
289 |
+
return $this->_lasterror;
|
290 |
+
}
|
291 |
+
|
292 |
+
public function unlink($path)
|
293 |
+
{
|
294 |
+
$mp=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $path));
|
295 |
+
return @unlink($mp);
|
296 |
+
}
|
297 |
+
|
298 |
+
public function copyFromRemote($remoteurl,$destpath)
|
299 |
+
{
|
300 |
+
$rfg=RemoteFileGetterFactory::getFGInstance();
|
301 |
+
$mp=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $destpath));
|
302 |
+
$ok=$rfg->copyRemoteFile($remoteurl,$mp);
|
303 |
+
if(!$ok)
|
304 |
+
{
|
305 |
+
$this->_lasterror=$rfg->getErrors();
|
306 |
+
}
|
307 |
+
unset($rfg);
|
308 |
+
return $ok;
|
309 |
+
}
|
310 |
+
|
311 |
+
public function copy($srcpath,$destpath)
|
312 |
+
{
|
313 |
+
$result=false;
|
314 |
+
$destpath=str_replace("//","/",$this->_magdir."/".str_replace($this->_magdir, '', $destpath));
|
315 |
+
if(preg_match('|^.*?://.*$|', $srcpath))
|
316 |
+
{
|
317 |
+
$result=$this->copyFromRemote($srcpath,$destpath);
|
318 |
+
}
|
319 |
+
else
|
320 |
+
{
|
321 |
+
|
322 |
+
$result=@copy($srcpath,$destpath);
|
323 |
+
if(!$result)
|
324 |
+
{
|
325 |
+
$this->_lasterror=error_get_last();
|
326 |
+
}
|
327 |
+
}
|
328 |
+
return $result;
|
329 |
+
}
|
330 |
+
|
331 |
+
public function exec_cmd($cmd,$params, $working_dir = null)
|
332 |
+
{
|
333 |
+
$full_cmd = $cmd." ".$params;
|
334 |
+
$curdir=false;
|
335 |
+
$precmd="";
|
336 |
+
// If a working directory has been specified, switch to it
|
337 |
+
// before running the requested command
|
338 |
+
if(!empty($working_dir))
|
339 |
+
{
|
340 |
+
$curdir=getcwd();
|
341 |
+
$wdir=realpath($working_dir);
|
342 |
+
//get current directory
|
343 |
+
if($curdir!=$wdir && $wdir!==false)
|
344 |
+
{
|
345 |
+
//trying to change using chdir
|
346 |
+
if(!@chdir($wdir))
|
347 |
+
{
|
348 |
+
//if no success, use cd from shell
|
349 |
+
$precmd="cd $wdir && ";
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
$full_cmd = $precmd. $full_cmd;
|
354 |
+
|
355 |
+
$out=@shell_exec($full_cmd);
|
356 |
+
|
357 |
+
//restore old directory if changed
|
358 |
+
if($curdir)
|
359 |
+
{
|
360 |
+
@chdir($curdir);
|
361 |
+
}
|
362 |
+
|
363 |
+
if($out==null)
|
364 |
+
{
|
365 |
+
$this->_lasterror=array("type"=>" execution error","message"=>error_get_last());
|
366 |
+
return false;
|
367 |
+
}
|
368 |
+
return $out;
|
369 |
+
}
|
370 |
+
}
|
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.
|
lib/Magmi/inc/magmi_config.php
ADDED
@@ -0,0 +1,278 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("properties.php");
|
3 |
+
|
4 |
+
|
5 |
+
class DirbasedConfig extends Properties
|
6 |
+
{
|
7 |
+
protected $_basedir=null;
|
8 |
+
protected $_confname=null;
|
9 |
+
|
10 |
+
public function __construct($basedir,$confname)
|
11 |
+
{
|
12 |
+
$this->_basedir=$basedir;
|
13 |
+
$this->_confname=$basedir.DS.$confname;
|
14 |
+
}
|
15 |
+
|
16 |
+
public function get($secname,$pname,$default=null)
|
17 |
+
{
|
18 |
+
if(!isset($this->_props))
|
19 |
+
{
|
20 |
+
$this->load();
|
21 |
+
}
|
22 |
+
return parent::get($secname, $pname,$default);
|
23 |
+
}
|
24 |
+
|
25 |
+
public function getConfFile()
|
26 |
+
{
|
27 |
+
return $this->_confname;
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getLastSaved($fmt)
|
31 |
+
{
|
32 |
+
|
33 |
+
return strftime($fmt,filemtime($this->_confname));
|
34 |
+
}
|
35 |
+
|
36 |
+
public function load($name=null)
|
37 |
+
{
|
38 |
+
if($name==null)
|
39 |
+
{
|
40 |
+
$name=$this->_confname;
|
41 |
+
}
|
42 |
+
|
43 |
+
if(!file_exists($name))
|
44 |
+
{
|
45 |
+
$this->save();
|
46 |
+
}
|
47 |
+
parent::load($name);
|
48 |
+
}
|
49 |
+
|
50 |
+
public function save($arr=null)
|
51 |
+
{
|
52 |
+
if($arr!=null)
|
53 |
+
{
|
54 |
+
$this->setPropsFromFlatArray($arr);
|
55 |
+
}
|
56 |
+
return parent::save($this->_confname);
|
57 |
+
}
|
58 |
+
|
59 |
+
public function saveTo($arr,$newdir)
|
60 |
+
{
|
61 |
+
if(!file_exists($newdir))
|
62 |
+
{
|
63 |
+
mkdir($newdir,Magmi_Config::getInstance()->getDirMask());
|
64 |
+
}
|
65 |
+
$val=parent::save($newdir.DS.basename($this->_confname));
|
66 |
+
$this->_basedir=$newdir;
|
67 |
+
$this->_confname=$newdir.DS.basename($this->_confname);
|
68 |
+
return $val;
|
69 |
+
}
|
70 |
+
|
71 |
+
public function getConfDir()
|
72 |
+
{
|
73 |
+
return $this->_basedir;
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
class ProfileBasedConfig extends DirbasedConfig
|
78 |
+
{
|
79 |
+
private static $_script=__FILE__;
|
80 |
+
protected $_profile=null;
|
81 |
+
|
82 |
+
public function getProfileDir()
|
83 |
+
{
|
84 |
+
$subdir=($this->_profile=="default"?"":DS.$this->_profile);
|
85 |
+
$confdir=dirname(dirname(self::$_script)).DS."conf$subdir";
|
86 |
+
if(!file_exists($confdir))
|
87 |
+
{
|
88 |
+
@mkdir($confdir,Magmi_Config::getInstance()->getDirMask());
|
89 |
+
}
|
90 |
+
return realpath($confdir);
|
91 |
+
}
|
92 |
+
|
93 |
+
public function __construct($fname,$profile=null)
|
94 |
+
{
|
95 |
+
$this->_profile=$profile;
|
96 |
+
parent::__construct($this->getProfileDir(),$fname);
|
97 |
+
}
|
98 |
+
|
99 |
+
public function getProfile()
|
100 |
+
{
|
101 |
+
return $this->_profile;
|
102 |
+
}
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
|
107 |
+
class Magmi_Config extends DirbasedConfig
|
108 |
+
{
|
109 |
+
private static $_instance=null;
|
110 |
+
private $_defaultconfigname=null;
|
111 |
+
public static $conffile=null;
|
112 |
+
private static $_script=__FILE__;
|
113 |
+
|
114 |
+
|
115 |
+
public function getConfDir()
|
116 |
+
{
|
117 |
+
$confdir=realpath(dirname(dirname(self::$_script)).DS."conf");
|
118 |
+
return $confdir;
|
119 |
+
}
|
120 |
+
|
121 |
+
public function __construct()
|
122 |
+
{
|
123 |
+
parent::__construct($this->getConfDir(),"magmi.ini");
|
124 |
+
|
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 |
+
|
138 |
+
public function getMagentoDir()
|
139 |
+
{
|
140 |
+
$bd=$this->get("MAGENTO","basedir");
|
141 |
+
$dp=$bd[0]=="."?dirname(__FILE__)."/".$bd:$bd;
|
142 |
+
return $dp;
|
143 |
+
}
|
144 |
+
|
145 |
+
public static function getInstance()
|
146 |
+
{
|
147 |
+
if(self::$_instance==null)
|
148 |
+
{
|
149 |
+
self::$_instance=new Magmi_Config();
|
150 |
+
}
|
151 |
+
return self::$_instance;
|
152 |
+
}
|
153 |
+
|
154 |
+
public function isDefault()
|
155 |
+
{
|
156 |
+
return !file_exists($this->_confname);
|
157 |
+
}
|
158 |
+
|
159 |
+
public function load($name=null)
|
160 |
+
{
|
161 |
+
$conf=(!$this->isDefault())?$this->_confname:$this->_confname.".default";
|
162 |
+
parent::load($conf);
|
163 |
+
$alt=false;
|
164 |
+
if($this->hasSection('USE_ALTERNATE'))
|
165 |
+
{
|
166 |
+
$this->_confname=$this->get("USE_ALTERNATE","file");
|
167 |
+
$alt=true;
|
168 |
+
}
|
169 |
+
parent::load($this->_confname);
|
170 |
+
if($alt)
|
171 |
+
{
|
172 |
+
$this->set("USE_ALTERNATE","file",$this->_confname);
|
173 |
+
}
|
174 |
+
//Migration from 0.6.17
|
175 |
+
if($this->hasSection("PLUGINS_DATASOURCES"))
|
176 |
+
{
|
177 |
+
$pluginsconf=new DirbasedConfig($this->getConfDir(),"plugins.conf");
|
178 |
+
$arr=array("PLUGINS_DATASOURCES"=>$this->getSection("PLUGINS_DATASOURCES"),
|
179 |
+
"PLUGINS_GENERAL"=>$this->getSection("PLUGINS_GENERAL"),
|
180 |
+
"PLUGINS_ITEMPROCESSORS"=>$this->getSection("PLUGINS_ITEMPROCESSORS"));
|
181 |
+
$pluginsconf->setProps($arr);
|
182 |
+
$pluginsconf->save();
|
183 |
+
$this->removeSection("PLUGINS_DATASOURCES");
|
184 |
+
$this->removeSection("PLUGINS_GENERAL");
|
185 |
+
$this->removeSection("PLUGINS_ITEMPROCESSORS");
|
186 |
+
$this->save();
|
187 |
+
|
188 |
+
}
|
189 |
+
//Migration step (to percent) , 0.7beta4
|
190 |
+
if($this->get("GLOBAL","step",0)==0 || floatval($this->get("GLOBAL","step",0.5))>20)
|
191 |
+
{
|
192 |
+
$this->set("GLOBAL","step",0.5);
|
193 |
+
$this->save();
|
194 |
+
}
|
195 |
+
return $this;
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
+
public function save($arr=null)
|
200 |
+
{
|
201 |
+
if(isset($arr["USE_ALTERNATE:file"]))
|
202 |
+
{
|
203 |
+
$this->_confname=$arr["USE_ALTERNATE:file"];
|
204 |
+
unset($arr["USE_ALTERNATE:file"]);
|
205 |
+
}
|
206 |
+
if($arr!==null)
|
207 |
+
{
|
208 |
+
foreach($arr as $k=>$v)
|
209 |
+
{
|
210 |
+
if(!preg_match("/\w+:\w+/",$k))
|
211 |
+
{
|
212 |
+
unset($arr[$k]);
|
213 |
+
}
|
214 |
+
}
|
215 |
+
}
|
216 |
+
return parent::save($arr);
|
217 |
+
}
|
218 |
+
|
219 |
+
public function getProfileList()
|
220 |
+
{
|
221 |
+
$proflist=array();
|
222 |
+
$candidates=scandir($this->getConfDir());
|
223 |
+
foreach($candidates as $candidate)
|
224 |
+
{
|
225 |
+
if(is_dir($this->getConfDir().DS.$candidate) && $candidate[0]!="." && substr($candidate,0,2)!="__")
|
226 |
+
{
|
227 |
+
$proflist[]=$candidate;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
return $proflist;
|
231 |
+
}
|
232 |
+
|
233 |
+
}
|
234 |
+
|
235 |
+
class EnabledPlugins_Config extends ProfileBasedConfig
|
236 |
+
{
|
237 |
+
|
238 |
+
public function __construct($profile="default")
|
239 |
+
{
|
240 |
+
parent::__construct("plugins.conf",$profile);
|
241 |
+
}
|
242 |
+
|
243 |
+
public function getEnabledPluginFamilies($typelist)
|
244 |
+
{
|
245 |
+
$btlist=array();
|
246 |
+
if(!is_array($typelist))
|
247 |
+
{
|
248 |
+
$typelist=explode(",",$typelist);
|
249 |
+
}
|
250 |
+
foreach($typelist as $pfamily)
|
251 |
+
{
|
252 |
+
$btlist[$pfamily]=$this->getEnabledPluginClasses($pfamily);
|
253 |
+
}
|
254 |
+
return $btlist;
|
255 |
+
}
|
256 |
+
|
257 |
+
public function getEnabledPluginClasses($type)
|
258 |
+
{
|
259 |
+
$type=strtoupper($type);
|
260 |
+
$cslist=$this->get("PLUGINS_$type","classes");
|
261 |
+
if($cslist==null)
|
262 |
+
{
|
263 |
+
$cslist=$this->get("PLUGINS_$type","class");
|
264 |
+
$epc=($cslist==null?array():array($cslist));
|
265 |
+
}
|
266 |
+
else
|
267 |
+
{
|
268 |
+
$epc=($cslist==""?array():explode(",",$cslist));
|
269 |
+
}
|
270 |
+
return $epc;
|
271 |
+
}
|
272 |
+
|
273 |
+
public function isPluginEnabled($type,$pclass)
|
274 |
+
{
|
275 |
+
return in_array($pclass,$this->getEnabledPluginClasses($type));
|
276 |
+
}
|
277 |
+
|
278 |
+
}
|
lib/Magmi/inc/magmi_csvreader.php
ADDED
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_mixin.php");
|
3 |
+
require_once("magmi_utils.php");
|
4 |
+
|
5 |
+
class Magmi_CSVException extends Exception
|
6 |
+
{
|
7 |
+
|
8 |
+
}
|
9 |
+
|
10 |
+
class Magmi_CSVReader extends Magmi_Mixin
|
11 |
+
{
|
12 |
+
protected $_filename;
|
13 |
+
protected $_fh;
|
14 |
+
protected $_cols;
|
15 |
+
protected $_csep;
|
16 |
+
protected $_dcsep;
|
17 |
+
protected $_params;
|
18 |
+
protected $_buffersize;
|
19 |
+
protected $_curline;
|
20 |
+
protected $_nhcols;
|
21 |
+
protected $_ignored=array();
|
22 |
+
|
23 |
+
|
24 |
+
|
25 |
+
|
26 |
+
public function initialize()
|
27 |
+
{
|
28 |
+
$this->_filename=$this->getParam("CSV:filename");
|
29 |
+
$this->_csep=$this->getParam("CSV:separator",",");
|
30 |
+
$this->_dcsep=$this->_csep;
|
31 |
+
|
32 |
+
if($this->_csep=="\\t")
|
33 |
+
{
|
34 |
+
$this->_csep="\t";
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->_cenc=$this->getParam("CSV:enclosure",'"');
|
38 |
+
$this->_buffersize=$this->getParam("CSV:buffer",0);
|
39 |
+
$this->_ignored=explode(",",$this->getParam("CSV:ignore"));
|
40 |
+
|
41 |
+
}
|
42 |
+
|
43 |
+
|
44 |
+
|
45 |
+
|
46 |
+
|
47 |
+
public function getLinesCount()
|
48 |
+
{
|
49 |
+
//open csv file
|
50 |
+
$f=fopen($this->_filename,"rb");
|
51 |
+
if($this->getParam("CSV:noheader",false)==true)
|
52 |
+
{
|
53 |
+
$count=0;
|
54 |
+
}
|
55 |
+
else
|
56 |
+
{
|
57 |
+
$count=-1;
|
58 |
+
}
|
59 |
+
$linenum=0;
|
60 |
+
if($f!=false)
|
61 |
+
{
|
62 |
+
$line=1;
|
63 |
+
while($line<$this->getParam("CSV:headerline",1))
|
64 |
+
{
|
65 |
+
$line++;
|
66 |
+
$dummy=fgetcsv($f,$this->_buffersize,$this->_csep,$this->_cenc);
|
67 |
+
}
|
68 |
+
//get records count
|
69 |
+
while(fgetcsv($f,$this->_buffersize,$this->_csep,$this->_cenc))
|
70 |
+
{
|
71 |
+
if(!in_array($line,$this->_ignored))
|
72 |
+
{
|
73 |
+
$count++;
|
74 |
+
}
|
75 |
+
}
|
76 |
+
fclose($f);
|
77 |
+
}
|
78 |
+
else
|
79 |
+
{
|
80 |
+
$this->log("Could not read $this->_filename , check permissions","error");
|
81 |
+
}
|
82 |
+
return $count;
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
public function checkCSV()
|
87 |
+
{
|
88 |
+
$this->_curline=0;
|
89 |
+
ini_set("auto_detect_line_endings",true);
|
90 |
+
if(!isset($this->_filename))
|
91 |
+
{
|
92 |
+
throw new Magmi_CSVException("No csv file set");
|
93 |
+
}
|
94 |
+
if(!file_exists($this->_filename))
|
95 |
+
{
|
96 |
+
throw new Magmi_CSVException("{$this->_filename} not found");
|
97 |
+
}
|
98 |
+
$this->log("Importing CSV : $this->_filename using separator [ $this->_dcsep ] enclosing [ $this->_cenc ]","startup");
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
public function openCSV()
|
103 |
+
{
|
104 |
+
$utf8bom=chr(0xEF).chr(0xBB).chr(0xBF);
|
105 |
+
//open csv file
|
106 |
+
$this->_fh=fopen($this->_filename,"rb");
|
107 |
+
//check for UTF8 BOM
|
108 |
+
$bomtest=fread($this->_fh,3);
|
109 |
+
//if 3 first bytes of file are not utf8 bom
|
110 |
+
if($bomtest!=$utf8bom)
|
111 |
+
{
|
112 |
+
//rewind to first byte;
|
113 |
+
$this->log("No BOM detected, assuming File is UTF8 without BOM...","startup");
|
114 |
+
fseek($this->_fh,0,SEEK_SET);
|
115 |
+
}
|
116 |
+
else
|
117 |
+
{
|
118 |
+
$this->log("File is UTF8 (BOM Detected)","startup");
|
119 |
+
}
|
120 |
+
}
|
121 |
+
|
122 |
+
public function getColumnNames($prescan=false)
|
123 |
+
{
|
124 |
+
if($prescan==true)
|
125 |
+
{
|
126 |
+
$this->openCSV();
|
127 |
+
$this->_csep=$this->getParam("CSV:separator",",");
|
128 |
+
$this->_dcsep=$this->_csep;
|
129 |
+
|
130 |
+
if($this->_csep=="\\t")
|
131 |
+
{
|
132 |
+
$this->_csep="\t";
|
133 |
+
}
|
134 |
+
|
135 |
+
$this->_cenc=$this->getParam("CSV:enclosure",'"');
|
136 |
+
$this->_buffersize=$this->getParam("CSV:buffer",0);
|
137 |
+
}
|
138 |
+
|
139 |
+
$line=1;
|
140 |
+
|
141 |
+
while($line<$this->getParam("CSV:headerline",1))
|
142 |
+
{
|
143 |
+
$line++;
|
144 |
+
$dummy=fgetcsv($this->_fh,$this->_buffersize,$this->_csep,$this->_cenc);
|
145 |
+
$this->log("skip line $line:".implode($this->_csep,$dummy),"info");
|
146 |
+
}
|
147 |
+
$cols=fgetcsv($this->_fh,$this->_buffersize,$this->_csep,$this->_cenc);
|
148 |
+
//if csv has no headers,use column number as column name
|
149 |
+
if($this->getParam("CSV:noheader",false)==true)
|
150 |
+
{
|
151 |
+
$kl=array_merge(array("dummy"),$cols);
|
152 |
+
unset($kl[0]);
|
153 |
+
$cols=array();
|
154 |
+
foreach(array_keys($kl) as $c)
|
155 |
+
{
|
156 |
+
$cols[]="col".$c;
|
157 |
+
}
|
158 |
+
//reset file pointer
|
159 |
+
fseek($this->_fh,0);
|
160 |
+
}
|
161 |
+
$this->_cols=$cols;
|
162 |
+
$this->_nhcols=count($this->_cols);
|
163 |
+
//trim column names
|
164 |
+
for($i=0;$i<$this->_nhcols;$i++)
|
165 |
+
{
|
166 |
+
$this->_cols[$i]=trim($this->_cols[$i]);
|
167 |
+
}
|
168 |
+
|
169 |
+
if($prescan==true)
|
170 |
+
{
|
171 |
+
fclose($this->_fh);
|
172 |
+
}
|
173 |
+
else
|
174 |
+
{
|
175 |
+
$this->log("$this->_nhcols CSV headers columns found","startup");
|
176 |
+
}
|
177 |
+
return $this->_cols;
|
178 |
+
}
|
179 |
+
|
180 |
+
public function closeCSV()
|
181 |
+
{
|
182 |
+
fclose($this->_fh);
|
183 |
+
}
|
184 |
+
|
185 |
+
public function isemptyline($row) {
|
186 |
+
return ( !isset($row[1]) && empty($row[0]) );
|
187 |
+
}
|
188 |
+
|
189 |
+
public function getNextRecord()
|
190 |
+
{
|
191 |
+
$row=null;
|
192 |
+
$allowtrunc=$this->getParam("CSV:allowtrunc",false);
|
193 |
+
while($row!==false)
|
194 |
+
{
|
195 |
+
$row=fgetcsv($this->_fh,$this->_buffersize,$this->_csep,$this->_cenc);
|
196 |
+
if($row !==false)
|
197 |
+
{
|
198 |
+
$this->_curline++;
|
199 |
+
//skip empty lines
|
200 |
+
if($this->isemptyline($row))
|
201 |
+
{
|
202 |
+
continue;
|
203 |
+
}
|
204 |
+
$rcols=count($row);
|
205 |
+
if(!$allowtrunc && $rcols!=$this->_nhcols)
|
206 |
+
{
|
207 |
+
//if strict matching, warning & continue
|
208 |
+
$this->log("warning: line $this->_curline , wrong column number : $rcols found over $this->_nhcols, line skipped","warning");
|
209 |
+
continue;
|
210 |
+
}
|
211 |
+
break;
|
212 |
+
}
|
213 |
+
}
|
214 |
+
//if we read something
|
215 |
+
if(is_array($row))
|
216 |
+
{
|
217 |
+
//strict mode
|
218 |
+
if(!$allowtrunc)
|
219 |
+
{
|
220 |
+
//create product attributes values array indexed by attribute code
|
221 |
+
$record=array_combine($this->_cols,$row);
|
222 |
+
}
|
223 |
+
else
|
224 |
+
{
|
225 |
+
|
226 |
+
//relax mode, recompose keys from read columns , others will be left unset
|
227 |
+
$ncols=count($row);
|
228 |
+
$cols=array_slice($this->_cols,0,$ncols);
|
229 |
+
$record=array_combine($cols,$row);
|
230 |
+
}
|
231 |
+
|
232 |
+
|
233 |
+
}
|
234 |
+
else
|
235 |
+
{
|
236 |
+
$record=false;
|
237 |
+
}
|
238 |
+
unset($row);
|
239 |
+
return $record;
|
240 |
+
}
|
241 |
+
|
242 |
+
|
243 |
+
}
|
lib/Magmi/inc/magmi_defs.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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(ini_get("include_path").
|
7 |
+
PATH_SEPARATOR.MAGMI_INCDIR.
|
8 |
+
PATH_SEPARATOR.MAGMI_INTEGRATION_INCDIR.
|
9 |
+
PATH_SEPARATOR.MAGMI_ENGINE_DIR);
|
10 |
+
require_once('magmi_loggers.php');
|
lib/Magmi/inc/magmi_engine.php
ADDED
@@ -0,0 +1,453 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
*
|
11 |
+
* This class is the mother class for magmi engines
|
12 |
+
* A magmi engine is a class that performs operations on DB
|
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 |
+
|
30 |
+
public function getEngineInfo()
|
31 |
+
{
|
32 |
+
return array("name"=>"Generic Magmi Engine","version"=>"1.1","author"=>"dweeves");
|
33 |
+
}
|
34 |
+
|
35 |
+
public function __construct()
|
36 |
+
{
|
37 |
+
//force PHP internal encoding as UTF 8
|
38 |
+
mb_internal_encoding("UTF-8");
|
39 |
+
}
|
40 |
+
|
41 |
+
|
42 |
+
public final function initialize($params=array())
|
43 |
+
{
|
44 |
+
try
|
45 |
+
{
|
46 |
+
$this->_conf=Magmi_Config::getInstance();
|
47 |
+
$this->_conf->load();
|
48 |
+
|
49 |
+
$this->tprefix=$this->_conf->get("DATABASE","table_prefix");
|
50 |
+
$this->_excid=0;
|
51 |
+
$this->_initialized=true;
|
52 |
+
$this->_exceptions=array();
|
53 |
+
}
|
54 |
+
catch(Exception $e)
|
55 |
+
{
|
56 |
+
die("Error initializing Engine:{$this->_conf->getConfigFilename()} \n".$e->getMessage());
|
57 |
+
}
|
58 |
+
|
59 |
+
}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns magento directory
|
63 |
+
*/
|
64 |
+
public function getMagentoDir()
|
65 |
+
{
|
66 |
+
return $this->_conf->getMagentoDir();
|
67 |
+
}
|
68 |
+
public function getMagentoVersion()
|
69 |
+
{
|
70 |
+
return $this->_conf->get("MAGENTO","version");
|
71 |
+
}
|
72 |
+
|
73 |
+
protected function _registerPluginLoopCallback($cbtype,$cb)
|
74 |
+
{
|
75 |
+
$this->_ploop_callbacks[$cbtype]=$cb;
|
76 |
+
}
|
77 |
+
|
78 |
+
protected function _unregisterPluginLoopCallback($cbtype)
|
79 |
+
{
|
80 |
+
unset($this->_ploop_callbacks[$cbtype]);
|
81 |
+
}
|
82 |
+
|
83 |
+
public function getPluginFamilies()
|
84 |
+
{
|
85 |
+
return array();
|
86 |
+
}
|
87 |
+
|
88 |
+
|
89 |
+
public function getEnabledPluginClasses($profile)
|
90 |
+
{
|
91 |
+
$enabledplugins=new EnabledPlugins_Config($profile);
|
92 |
+
$enabledplugins->load();
|
93 |
+
return $enabledplugins->getEnabledPluginFamilies($this->getPluginFamilies());
|
94 |
+
}
|
95 |
+
|
96 |
+
public function initPlugins($profile=null)
|
97 |
+
{
|
98 |
+
|
99 |
+
$this->_pluginclasses=$this->getEnabledPluginClasses($profile);
|
100 |
+
}
|
101 |
+
|
102 |
+
public function getBuiltinPluginClasses()
|
103 |
+
{
|
104 |
+
$bplarr=array();
|
105 |
+
|
106 |
+
foreach($this->_builtinplugins as $pfamily=>$pdef)
|
107 |
+
{
|
108 |
+
$plinfo=explode("::",$pdef);
|
109 |
+
$pfile=$plinfo[0];
|
110 |
+
$pclass=$plinfo[1];
|
111 |
+
require_once($pfile);
|
112 |
+
if(!isset($bplarr[$pfamily]))
|
113 |
+
{
|
114 |
+
$bplarr[$pfamily]=array();
|
115 |
+
}
|
116 |
+
$bplarr[$pfamily][]=$pclass;
|
117 |
+
}
|
118 |
+
return $bplarr;
|
119 |
+
}
|
120 |
+
|
121 |
+
public function getPluginClasses()
|
122 |
+
{
|
123 |
+
return $this->_pluginclasses;
|
124 |
+
}
|
125 |
+
|
126 |
+
public function getPluginInstances($family=null)
|
127 |
+
{
|
128 |
+
$pil=null;
|
129 |
+
if($family==null)
|
130 |
+
{
|
131 |
+
$pil=$this->_activeplugins();
|
132 |
+
}
|
133 |
+
else
|
134 |
+
{
|
135 |
+
$pil=(isset($this->_activeplugins[$family])?$this->_activeplugins[$family]:array());
|
136 |
+
}
|
137 |
+
return $pil;
|
138 |
+
}
|
139 |
+
|
140 |
+
public function setBuiltinPluginClasses($pfamily,$pclasses)
|
141 |
+
{
|
142 |
+
$this->_builtinplugins[$pfamily]=$pclasses;
|
143 |
+
}
|
144 |
+
|
145 |
+
public function sortPlugins($p1,$p2)
|
146 |
+
{
|
147 |
+
|
148 |
+
$m1=$p1->getPluginMeta();
|
149 |
+
if($m1==null)
|
150 |
+
{
|
151 |
+
return 1;
|
152 |
+
}
|
153 |
+
$m2=$p2->getPluginMeta();
|
154 |
+
if($m2==null)
|
155 |
+
{
|
156 |
+
return -1;
|
157 |
+
}
|
158 |
+
return strcmp($m1["file"],$m2["file"]);
|
159 |
+
}
|
160 |
+
public function createPlugins($profile,$params)
|
161 |
+
{
|
162 |
+
$plhelper=Magmi_PluginHelper::getInstance($profile);
|
163 |
+
$this->_pluginclasses = array_merge_recursive($this->_pluginclasses,$this->getBuiltinPluginClasses());
|
164 |
+
foreach($this->_pluginclasses as $pfamily=>$pclasses)
|
165 |
+
{
|
166 |
+
if($pfamily[0]=="*")
|
167 |
+
{
|
168 |
+
$this->_pluginclasses[substr($pfamily,1)]=$pclasses;
|
169 |
+
unset($this->_pluginclasses[$pfamily]);
|
170 |
+
}
|
171 |
+
}
|
172 |
+
foreach($this->_pluginclasses as $pfamily=>$pclasses)
|
173 |
+
{
|
174 |
+
if(!isset($this->_activeplugins[$pfamily]))
|
175 |
+
{
|
176 |
+
$this->_activeplugins[$pfamily]=array();
|
177 |
+
}
|
178 |
+
foreach($pclasses as $pclass)
|
179 |
+
{
|
180 |
+
$this->_activeplugins[$pfamily][]=$plhelper->createInstance($pfamily,$pclass,$params,$this);
|
181 |
+
|
182 |
+
}
|
183 |
+
usort($this->_activeplugins[$pfamily],array(&$this,"sortPlugins"));
|
184 |
+
}
|
185 |
+
|
186 |
+
}
|
187 |
+
|
188 |
+
public function getPluginInstanceByClassName($pfamily,$pclassname)
|
189 |
+
{
|
190 |
+
$inst=null;
|
191 |
+
if(isset($this->_activeplugins[$pfamily]))
|
192 |
+
{
|
193 |
+
foreach($this->_activeplugins[$pfamily] as $pinstance)
|
194 |
+
{
|
195 |
+
if(get_class($pinstance)==$pclassname)
|
196 |
+
{
|
197 |
+
$inst=$pinstance;
|
198 |
+
break;
|
199 |
+
}
|
200 |
+
}
|
201 |
+
}
|
202 |
+
return $inst;
|
203 |
+
}
|
204 |
+
|
205 |
+
public function getPluginInstance($family,$order=-1)
|
206 |
+
{
|
207 |
+
if($order<0)
|
208 |
+
{
|
209 |
+
$order+=count($this->_activeplugins[$family]);
|
210 |
+
}
|
211 |
+
return $this->_activeplugins[$family][$order];
|
212 |
+
}
|
213 |
+
|
214 |
+
public function callPlugins($types,$callback,&$data=null,$params=null,$break=true)
|
215 |
+
{
|
216 |
+
$result=true;
|
217 |
+
if(!is_array($types))
|
218 |
+
{
|
219 |
+
if($types!="*")
|
220 |
+
{
|
221 |
+
$types=explode(",",$types);
|
222 |
+
}
|
223 |
+
else
|
224 |
+
{
|
225 |
+
$types=array_keys($this->_activeplugins);
|
226 |
+
}
|
227 |
+
}
|
228 |
+
foreach($types as $ptype)
|
229 |
+
{
|
230 |
+
if(isset($this->_activeplugins[$ptype]))
|
231 |
+
{
|
232 |
+
foreach($this->_activeplugins[$ptype] as $pinst)
|
233 |
+
{
|
234 |
+
if(method_exists($pinst,$callback))
|
235 |
+
{
|
236 |
+
$callres=($data==null?($params==null?$pinst->$callback():$pinst->$callback($params)):$pinst->$callback($data,$params));
|
237 |
+
if($callres===false && $data!=null)
|
238 |
+
{
|
239 |
+
|
240 |
+
$result=false;
|
241 |
+
|
242 |
+
}
|
243 |
+
if(isset($this->_ploop_callbacks[$callback]))
|
244 |
+
{
|
245 |
+
$cb=$this->_ploop_callbacks[$callback];
|
246 |
+
$this->$cb($pinst,$data,$result);
|
247 |
+
}
|
248 |
+
if($result===false && $break)
|
249 |
+
{
|
250 |
+
return $result;
|
251 |
+
}
|
252 |
+
}
|
253 |
+
}
|
254 |
+
}
|
255 |
+
}
|
256 |
+
return $result;
|
257 |
+
}
|
258 |
+
|
259 |
+
public function getParam($params,$pname,$default=null)
|
260 |
+
{
|
261 |
+
return isset($params[$pname])?$params[$pname]:$default;
|
262 |
+
}
|
263 |
+
|
264 |
+
public function setLogger($logger)
|
265 |
+
{
|
266 |
+
$this->logger=$logger;
|
267 |
+
}
|
268 |
+
/**
|
269 |
+
* logging function
|
270 |
+
* @param string $data : string to log
|
271 |
+
* @param string $type : log type
|
272 |
+
*/
|
273 |
+
public function microDateTime()
|
274 |
+
{
|
275 |
+
list($microSec, $timeStamp) = explode(" ", microtime());
|
276 |
+
return date('Y-m-d h:i:', $timeStamp) . (date('s', $timeStamp) + $microSec);
|
277 |
+
}
|
278 |
+
|
279 |
+
public function log($data,$type="default",$logger=null)
|
280 |
+
{
|
281 |
+
$usedlogger=($logger==null?$this->logger:$logger);
|
282 |
+
if(isset($usedlogger))
|
283 |
+
{
|
284 |
+
$usedlogger->log($data,$type);
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
public function logException($e,$data="",$logger=null)
|
289 |
+
{
|
290 |
+
$this->trace($e,$data);
|
291 |
+
$this->log($this->_excid.":".$e->getMessage()." - ".$data,"error",$logger);
|
292 |
+
}
|
293 |
+
|
294 |
+
public function getExceptionTrace($tk,&$traces)
|
295 |
+
{
|
296 |
+
$this->_excid++;
|
297 |
+
$trstr="";
|
298 |
+
foreach($traces as $trace)
|
299 |
+
{
|
300 |
+
if(isset($trace["file"]))
|
301 |
+
{
|
302 |
+
$fname=str_replace(dirname(dirname(__FILE__)),"",$trace["file"]);
|
303 |
+
$trstr.= $fname.":".(isset($trace["line"])?$trace["line"]:"?")." - ";
|
304 |
+
if(isset($trace["class"]))
|
305 |
+
{
|
306 |
+
$trstr.=$trace["class"]."->";
|
307 |
+
if(isset($trace["function"]))
|
308 |
+
{
|
309 |
+
$trstr.=$trace["function"];
|
310 |
+
}
|
311 |
+
$trstr.="\n----------------------------------------\n";
|
312 |
+
if(isset($trace["args"]))
|
313 |
+
{
|
314 |
+
$trstr.=print_r($trace["args"],true);
|
315 |
+
}
|
316 |
+
$trstr.="\n";
|
317 |
+
}
|
318 |
+
}
|
319 |
+
}
|
320 |
+
if(!isset($this->_exceptions[$tk]))
|
321 |
+
{
|
322 |
+
$this->_exceptions[$tk]=array(0,$this->_excid);
|
323 |
+
}
|
324 |
+
$this->_exceptions[$tk][0]++;
|
325 |
+
$trstr="************************************\n$trstr";
|
326 |
+
return array($trstr,$this->_exceptions[$tk][0]==1,$this->_exceptions[$tk][1]);
|
327 |
+
}
|
328 |
+
|
329 |
+
public function trace($e,$data="")
|
330 |
+
{
|
331 |
+
$traces=$e->getTrace();
|
332 |
+
$tk=$e->getMessage();
|
333 |
+
$traceinfo=$this->getExceptionTrace($tk,$traces);
|
334 |
+
$f=fopen(Magmi_StateManager::getTraceFile(),"a");
|
335 |
+
fwrite($f,"---- TRACE : $this->_excid -----\n");
|
336 |
+
try
|
337 |
+
{
|
338 |
+
if($traceinfo[1]==true)
|
339 |
+
{
|
340 |
+
fwrite($f,$traceinfo[0]);
|
341 |
+
fwrite($f,"+++++++++++++++++++++++++++++\nCONTEXT DUMP\n+++++++++++++++++++++++++++++\n");
|
342 |
+
fwrite($f,print_r($this,true));
|
343 |
+
fwrite($f,"\n+++++++++++++++++++++++++++++\nEND CONTEXT DUMP\n+++++++++++++++++++++++++++++\n");
|
344 |
+
}
|
345 |
+
else
|
346 |
+
{
|
347 |
+
$tnum=$traceinfo[2];
|
348 |
+
fwrite($f,"Duplicated exception - same trace as TRACE : $tnum\n");
|
349 |
+
}
|
350 |
+
}
|
351 |
+
catch(Exception $te)
|
352 |
+
{
|
353 |
+
fwrite($f,"Exception occured during trace:".$te->getMessage());
|
354 |
+
}
|
355 |
+
fwrite($f,"---- ENDTRACE : $this->_excid -----\n");
|
356 |
+
fclose($f);
|
357 |
+
}
|
358 |
+
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Engine run method
|
362 |
+
* @param array $params - run parameters
|
363 |
+
*/
|
364 |
+
public final function run($params=array())
|
365 |
+
{
|
366 |
+
try
|
367 |
+
{
|
368 |
+
$f=fopen(Magmi_StateManager::getTraceFile(),"w");
|
369 |
+
fclose($f);
|
370 |
+
$enginf=$this->getEngineInfo();
|
371 |
+
$this->log("MAGMI by dweeves - version:".Magmi_Version::$version,"title");
|
372 |
+
$this->log("Running {$enginf["name"]} v${enginf["version"]} by ${enginf["author"]}","startup");
|
373 |
+
if(!$this->_initialized)
|
374 |
+
{
|
375 |
+
$this->initialize($params);
|
376 |
+
}
|
377 |
+
$this->connectToMagento();
|
378 |
+
$this->engineInit($params);
|
379 |
+
$this->engineRun($params);
|
380 |
+
$this->disconnectFromMagento();
|
381 |
+
}
|
382 |
+
catch(Exception $e)
|
383 |
+
{
|
384 |
+
$this->disconnectFromMagento();
|
385 |
+
|
386 |
+
$this->handleException($e);
|
387 |
+
}
|
388 |
+
|
389 |
+
}
|
390 |
+
|
391 |
+
public function handleException($e)
|
392 |
+
{
|
393 |
+
$this->logException($e);
|
394 |
+
if(method_exists($this, "onEngineException"))
|
395 |
+
{
|
396 |
+
$this->onEngineException($e);
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
/**
|
401 |
+
shortcut method for configuration properties get
|
402 |
+
*/
|
403 |
+
public function getProp($sec,$val,$default=null)
|
404 |
+
{
|
405 |
+
return $this->_conf->get($sec,$val,$default);
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Initialize Connection with Magento Database
|
410 |
+
*/
|
411 |
+
public function connectToMagento()
|
412 |
+
{
|
413 |
+
#get database infos from properties
|
414 |
+
if(!$this->_connected)
|
415 |
+
{
|
416 |
+
$host=$this->getProp("DATABASE","host","localhost");
|
417 |
+
$dbname=$this->getProp("DATABASE","dbname","magento");
|
418 |
+
$user=$this->getProp("DATABASE","user");
|
419 |
+
$pass=$this->getProp("DATABASE","password");
|
420 |
+
$debug=$this->getProp("DATABASE","debug");
|
421 |
+
$conn=$this->getProp("DATABASE","connectivity","net");
|
422 |
+
$port=$this->getProp("DATABASE","port","3306");
|
423 |
+
$socket=$this->getProp("DATABASE","unix_socket");
|
424 |
+
$this->initDb($host,$dbname,$user,$pass,$port,$socket,$conn,$debug);
|
425 |
+
//suggested by pastanislas
|
426 |
+
$this->_db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,true);
|
427 |
+
}
|
428 |
+
}
|
429 |
+
/*
|
430 |
+
* Disconnect Magento db
|
431 |
+
*/
|
432 |
+
public function disconnectFromMagento()
|
433 |
+
{
|
434 |
+
if($this->_connected)
|
435 |
+
{
|
436 |
+
$this->exitDb();
|
437 |
+
}
|
438 |
+
}
|
439 |
+
|
440 |
+
/**
|
441 |
+
* returns prefixed table name
|
442 |
+
* @param string $magname : magento base table name
|
443 |
+
*/
|
444 |
+
public function tablename($magname)
|
445 |
+
{
|
446 |
+
return $this->tprefix!=""?$this->tprefix."$magname":$magname;
|
447 |
+
}
|
448 |
+
|
449 |
+
|
450 |
+
public abstract function engineInit($params);
|
451 |
+
public abstract function engineRun($params);
|
452 |
+
|
453 |
+
}
|
lib/Magmi/inc/magmi_loggers.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class FileLogger
|
3 |
+
{
|
4 |
+
protected $_fname;
|
5 |
+
|
6 |
+
public function __construct($fname=null)
|
7 |
+
{
|
8 |
+
if($fname==null)
|
9 |
+
{
|
10 |
+
$fname=Magmi_StateManager::getProgressFile(true);
|
11 |
+
}
|
12 |
+
$this->_fname=$fname;
|
13 |
+
$f=fopen($this->_fname,"w");
|
14 |
+
if($f==false)
|
15 |
+
{
|
16 |
+
throw new Exception("CANNOT WRITE PROGRESS FILE ");
|
17 |
+
}
|
18 |
+
fclose($f);
|
19 |
+
}
|
20 |
+
|
21 |
+
public function log($data,$type)
|
22 |
+
{
|
23 |
+
|
24 |
+
$f=fopen($this->_fname,"a");
|
25 |
+
if($f==false)
|
26 |
+
{
|
27 |
+
throw new Exception("CANNOT WRITE PROGRESS FILE ");
|
28 |
+
}
|
29 |
+
$data=preg_replace ("/(\r|\n|\r\n)/", "<br>", $data);
|
30 |
+
fwrite($f,"$type:$data\n");
|
31 |
+
fclose($f);
|
32 |
+
}
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
class EchoLogger
|
37 |
+
{
|
38 |
+
public function log($data,$type)
|
39 |
+
{
|
40 |
+
$info=explode(";",$type);
|
41 |
+
$type=$info[0];
|
42 |
+
echo('<p class="logentry log_'.$type.'">'.$data."</p>");
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
46 |
+
class CLILogger
|
47 |
+
{
|
48 |
+
public function log($data,$type)
|
49 |
+
{
|
50 |
+
echo("$type:$data\n");
|
51 |
+
}
|
52 |
+
}
|
53 |
+
?>
|
lib/Magmi/inc/magmi_mixin.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_Mixin
|
3 |
+
{
|
4 |
+
protected $_callers;
|
5 |
+
|
6 |
+
public function bind($caller)
|
7 |
+
{
|
8 |
+
$this->_callers[]=$caller;
|
9 |
+
$this->_callers=array_unique($this->_callers);
|
10 |
+
}
|
11 |
+
|
12 |
+
public function unbind($caller)
|
13 |
+
{
|
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 |
+
|
26 |
+
public function __call($data,$arg)
|
27 |
+
{
|
28 |
+
if(substr($data,0,8)=="_caller_")
|
29 |
+
{
|
30 |
+
$data=substr($data,8);
|
31 |
+
}
|
32 |
+
for($i=0;$i<count($this->_callers);$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 |
+
}
|
lib/Magmi/inc/magmi_pluginhelper.php
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_config.php");
|
3 |
+
require_once("fshelper.php");
|
4 |
+
class Magmi_PluginHelper
|
5 |
+
{
|
6 |
+
|
7 |
+
|
8 |
+
static $_plugins_cache=array();
|
9 |
+
static $_instances=array();
|
10 |
+
public $base_dir;
|
11 |
+
public $plugin_dir;
|
12 |
+
protected $_profile;
|
13 |
+
protected $_plmeta=array("datasources"=>array("Magmi_Datasource","*/*"),
|
14 |
+
"itemprocessors"=>array("Magmi_ItemProcessor","*/*"),
|
15 |
+
"general"=>array("Magmi_GeneralImportPlugin","*/*"),
|
16 |
+
"utilities"=>array("Magmi_UtilityPlugin","utilities"));
|
17 |
+
|
18 |
+
public function __construct($profile=null)
|
19 |
+
{
|
20 |
+
$this->_profile=$profile;
|
21 |
+
$this->base_dir=dirname(__FILE__);
|
22 |
+
$this->plugin_dir=realpath(dirname(dirname(__FILE__)).DS."plugins");
|
23 |
+
//set include path to inclue plugins inc & base dir
|
24 |
+
set_include_path(ini_get("include_path").PATH_SEPARATOR."$this->plugin_dir/inc".PATH_SEPARATOR."$this->base_dir");
|
25 |
+
//add base classes in context
|
26 |
+
require_once("magmi_item_processor.php");
|
27 |
+
require_once("magmi_datasource.php");
|
28 |
+
require_once("magmi_generalimport_plugin.php");
|
29 |
+
require_once("magmi_utility_plugin.php");
|
30 |
+
|
31 |
+
}
|
32 |
+
public static function getInstance($profile=null)
|
33 |
+
{
|
34 |
+
$key=($profile==null?"default":$profile);
|
35 |
+
if(!isset(self::$_instances[$key]))
|
36 |
+
{
|
37 |
+
self::$_instances[$key]=new Magmi_PluginHelper($profile);
|
38 |
+
}
|
39 |
+
return self::$_instances[$key];
|
40 |
+
}
|
41 |
+
|
42 |
+
public static function fnsort($f1,$f2)
|
43 |
+
{
|
44 |
+
return strcmp(basename($f1),basename($f2));
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
public function initPluginInfos($baseclass,$basedir="*/*")
|
49 |
+
{
|
50 |
+
$candidates=glob("$this->plugin_dir/$basedir/*/*.php");
|
51 |
+
usort($candidates,array("Magmi_PluginHelper","fnsort"));
|
52 |
+
$pluginclasses=array();
|
53 |
+
foreach($candidates as $pcfile)
|
54 |
+
{
|
55 |
+
$dirname=dirname(substr($pcfile,strlen($this->plugin_dir)));
|
56 |
+
if(substr(basename($dirname),0,2)!='__')
|
57 |
+
{
|
58 |
+
$content=file_get_contents($pcfile);
|
59 |
+
if(preg_match_all("/class\s+(.*?)\s+extends\s+$baseclass/mi",$content,$matches,PREG_SET_ORDER))
|
60 |
+
{
|
61 |
+
require_once($pcfile);
|
62 |
+
foreach($matches as $match)
|
63 |
+
{
|
64 |
+
$pluginclasses[]=array("class"=>$match[1],"dir"=>$dirname,"file"=>basename($pcfile));
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
}
|
69 |
+
return $pluginclasses;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getPluginClasses($pltypes)
|
73 |
+
{
|
74 |
+
return self::getPluginsInfo($pltypes,"class");
|
75 |
+
}
|
76 |
+
|
77 |
+
public function getPluginsInfo($pltypes,$filter=null)
|
78 |
+
{
|
79 |
+
if(self::$_plugins_cache==null)
|
80 |
+
{
|
81 |
+
self::scanPlugins($pltypes);
|
82 |
+
}
|
83 |
+
|
84 |
+
if(isset($filter))
|
85 |
+
{
|
86 |
+
$out=array();
|
87 |
+
foreach(self::$_plugins_cache as $k=>$arr)
|
88 |
+
{
|
89 |
+
if(!isset($out[$k]))
|
90 |
+
{
|
91 |
+
$out[$k]=array();
|
92 |
+
}
|
93 |
+
foreach($arr as $desc)
|
94 |
+
{
|
95 |
+
$out[$k][]=$desc[$filter];
|
96 |
+
}
|
97 |
+
}
|
98 |
+
$plugins=$out;
|
99 |
+
}
|
100 |
+
else
|
101 |
+
{
|
102 |
+
$plugins=self::$_plugins_cache;
|
103 |
+
}
|
104 |
+
return $plugins;
|
105 |
+
|
106 |
+
}
|
107 |
+
|
108 |
+
public function scanPlugins($pltypes)
|
109 |
+
{
|
110 |
+
if(!is_array($pltypes))
|
111 |
+
{
|
112 |
+
$pltypes=array($pltypes);
|
113 |
+
}
|
114 |
+
foreach($pltypes as $pltype)
|
115 |
+
{
|
116 |
+
if(!isset(self::$_plugins_cache[$pltype]))
|
117 |
+
{
|
118 |
+
self::$_plugins_cache[$pltype]=self::initPluginInfos($this->_plmeta[$pltype][0],$this->_plmeta[$pltype][1]);
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
public function createInstance($ptype,$pclass,$params=null,$mmi=null)
|
125 |
+
{
|
126 |
+
|
127 |
+
if(!isset(self::$_plugins_cache[$ptype]))
|
128 |
+
{
|
129 |
+
self::scanPlugins($ptype);
|
130 |
+
}
|
131 |
+
$plinst=new $pclass();
|
132 |
+
|
133 |
+
$plinst->pluginInit($mmi,$this->getPluginMeta($plinst),$params,($mmi!=null),$this->_profile);
|
134 |
+
return $plinst;
|
135 |
+
}
|
136 |
+
|
137 |
+
public function getPluginDir($pinst)
|
138 |
+
{
|
139 |
+
$mt=$this->getPluginMeta($pinst);
|
140 |
+
return $mt["dir"];
|
141 |
+
}
|
142 |
+
|
143 |
+
public function getPluginMeta($pinst)
|
144 |
+
{
|
145 |
+
if(self::$_plugins_cache==null)
|
146 |
+
{
|
147 |
+
self::scanPlugins();
|
148 |
+
}
|
149 |
+
|
150 |
+
foreach(self::$_plugins_cache as $t=>$l)
|
151 |
+
{
|
152 |
+
foreach($l as $pdesc)
|
153 |
+
{
|
154 |
+
if($pdesc["class"]==get_class($pinst))
|
155 |
+
{
|
156 |
+
$out=$pdesc;
|
157 |
+
$out["dir"]=$this->plugin_dir.$pdesc["dir"];
|
158 |
+
return $out;
|
159 |
+
}
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
public function installPluginPackage($pkgname)
|
165 |
+
{
|
166 |
+
$zip = new ZipArchive();
|
167 |
+
$res = $zip->open($pkgname);
|
168 |
+
if ($res === TRUE)
|
169 |
+
{
|
170 |
+
$zip->extractTo($this->plugin_dir);
|
171 |
+
$zip->close();
|
172 |
+
return array("plugin_install"=>"OK");
|
173 |
+
}
|
174 |
+
else
|
175 |
+
{
|
176 |
+
return array("plugin_install"=>"ERROR",
|
177 |
+
"ERROR"=>"Invalid Plugin Package Archive");
|
178 |
+
}
|
179 |
+
$packages=glob("$this->plugin_dir/*");
|
180 |
+
foreach($packages as $pdir)
|
181 |
+
{
|
182 |
+
if(file_exists($pdir.DS."obsolete.txt"))
|
183 |
+
{
|
184 |
+
$content=file_get_contents($pdir.DS."obsolete.txt");
|
185 |
+
$obsolete=explode("\n",$content);
|
186 |
+
foreach($obsolete as $todelete)
|
187 |
+
{
|
188 |
+
if($todelete!="")
|
189 |
+
{
|
190 |
+
@unlink($pdir.DS.$todelete);
|
191 |
+
}
|
192 |
+
}
|
193 |
+
unlink($pdir.DS."obsolete.txt");
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
public function removePlugin($pgpath)
|
199 |
+
{
|
200 |
+
unlink($pgpath);
|
201 |
+
}
|
202 |
+
}
|
lib/Magmi/inc/magmi_postinstall.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_version.php");
|
3 |
+
|
4 |
+
function magmi_post_install()
|
5 |
+
{
|
6 |
+
$out="";
|
7 |
+
if(version_compare(Magmi_Version::$version,"0.7.17")<=0)
|
8 |
+
{
|
9 |
+
$delcds=array_merge(glob("../integration/inc/*.*"),glob("../integration/samples/*.*"));
|
10 |
+
$todelete=array();
|
11 |
+
foreach($delcds as $fname)
|
12 |
+
{
|
13 |
+
$todelete[]=basename($fname);
|
14 |
+
}
|
15 |
+
$allfiles=glob("../integration/*.*");
|
16 |
+
if($allfiles!==false)
|
17 |
+
{
|
18 |
+
foreach($allfiles as $fname)
|
19 |
+
{
|
20 |
+
if(in_array(basename($fname),$todelete))
|
21 |
+
{
|
22 |
+
$out.="deleting $fname (new dir struct)<br>";
|
23 |
+
unlink($fname);
|
24 |
+
}
|
25 |
+
else
|
26 |
+
{
|
27 |
+
$out.="moving $fname to migrated (custom script)<br>";
|
28 |
+
@mkdir("../integration/scripts/migrated/");
|
29 |
+
copy($fname,"../integration/scripts/migrated/".basename($fname));
|
30 |
+
unlink($fname);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
34 |
+
else
|
35 |
+
{
|
36 |
+
$out="nothing to do";
|
37 |
+
}
|
38 |
+
|
39 |
+
}
|
40 |
+
return array("OK"=>$out);
|
41 |
+
}
|
lib/Magmi/inc/magmi_statemanager.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if(!defined("DS"))
|
3 |
+
{
|
4 |
+
define("DS",DIRECTORY_SEPARATOR);
|
5 |
+
}
|
6 |
+
class Magmi_StateManager
|
7 |
+
{
|
8 |
+
private static $_statefile=null;
|
9 |
+
private static $_script=__FILE__;
|
10 |
+
private static $_state="idle";
|
11 |
+
|
12 |
+
|
13 |
+
public static function getStateFile()
|
14 |
+
{
|
15 |
+
return self::getStateDir().DS."magmistate";
|
16 |
+
}
|
17 |
+
|
18 |
+
public static function getTraceFile()
|
19 |
+
{
|
20 |
+
return self::getStateDir().DS."trace.txt";
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function getStateDir()
|
25 |
+
{
|
26 |
+
return dirname(dirname(self::$_script)).DS."state";
|
27 |
+
}
|
28 |
+
|
29 |
+
public static function getProgressFile($full=false)
|
30 |
+
{
|
31 |
+
$fullname=self::getStateDir().DS."progress.txt";
|
32 |
+
$pfname=($full?$fullname:"progress.txt");
|
33 |
+
return $pfname;
|
34 |
+
}
|
35 |
+
|
36 |
+
public static function setState($state,$force=false)
|
37 |
+
{
|
38 |
+
|
39 |
+
if(self::$_state==$state && !$force)
|
40 |
+
{
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
|
44 |
+
self::$_state=$state;
|
45 |
+
$f=fopen(self::getStateFile(),"w");
|
46 |
+
fwrite($f,self::$_state);
|
47 |
+
fclose($f);
|
48 |
+
@chmod(self::getStateFile(),0664);
|
49 |
+
if($state=="running")
|
50 |
+
{
|
51 |
+
$f=fopen(self::getTraceFile(),"w");
|
52 |
+
fclose($f);
|
53 |
+
@chmod(self::getTraceFile(),0664);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
public static function getState($cached=false)
|
58 |
+
{
|
59 |
+
if(!$cached)
|
60 |
+
{
|
61 |
+
if(!file_exists(self::getStateFile()))
|
62 |
+
{
|
63 |
+
self::setState("idle",true);
|
64 |
+
}
|
65 |
+
$state=file_get_contents(self::getStateFile());
|
66 |
+
}
|
67 |
+
else
|
68 |
+
{
|
69 |
+
$state=self::$_state;
|
70 |
+
}
|
71 |
+
return $state;
|
72 |
+
}
|
73 |
+
|
74 |
+
}
|
lib/Magmi/inc/magmi_utils.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
//utilities function
|
3 |
+
// return null for empty string
|
4 |
+
function nullifempty($val)
|
5 |
+
{
|
6 |
+
return (isset($val)?(trim($val)==""?null:$val):null);
|
7 |
+
}
|
8 |
+
// return false for empty string
|
9 |
+
function falseifempty($val)
|
10 |
+
{
|
11 |
+
return (isset($val)?(strlen($val)==0?false:$val):false);
|
12 |
+
}
|
13 |
+
//test for empty string
|
14 |
+
function testempty($arr,$val)
|
15 |
+
{
|
16 |
+
|
17 |
+
return !isset($arr[$val]) || strlen(trim($arr[$val]))==0;
|
18 |
+
}
|
19 |
+
|
20 |
+
function deleteifempty($val)
|
21 |
+
{
|
22 |
+
return (isset($val)?(trim($val)==""?"__MAGMI_DELETE__":$val):"__MAGMI_DELETE__");
|
23 |
+
}
|
24 |
+
|
25 |
+
function csl2arr($cslarr,$sep=",")
|
26 |
+
{
|
27 |
+
$arr=explode($sep,$cslarr);
|
28 |
+
for($i=0;$i<count($arr);$i++)
|
29 |
+
{
|
30 |
+
$arr[$i]=trim($arr[$i]);
|
31 |
+
}
|
32 |
+
return $arr;
|
33 |
+
}
|
34 |
+
|
35 |
+
function trimarray(&$arr)
|
36 |
+
{
|
37 |
+
for($i=0;$i<count($arr);$i++)
|
38 |
+
{
|
39 |
+
$arr[$i]=trim($arr[$i]);
|
40 |
+
}
|
41 |
+
|
42 |
+
}
|
43 |
+
|
44 |
+
function getRelative(&$val)
|
45 |
+
{
|
46 |
+
$dir="+";
|
47 |
+
if($val[0]=="-")
|
48 |
+
{
|
49 |
+
$val=substr($val,1);
|
50 |
+
$dir="-";
|
51 |
+
}
|
52 |
+
else
|
53 |
+
if($val[0]=="+")
|
54 |
+
{
|
55 |
+
$val=substr($val,1);
|
56 |
+
}
|
57 |
+
return $dir;
|
58 |
+
}
|
59 |
+
|
60 |
+
function is_remote_path($path)
|
61 |
+
{
|
62 |
+
$parsed=parse_url($path);
|
63 |
+
return isset($parsed['host']);
|
64 |
+
}
|
65 |
+
|
66 |
+
function abspath($path,$basepath="",$resolve=true)
|
67 |
+
{
|
68 |
+
if($basepath=="")
|
69 |
+
{
|
70 |
+
$basepath=dirname(dirname(__FILE__));
|
71 |
+
}
|
72 |
+
$cpath=str_replace('//','/',$basepath."/".$path);
|
73 |
+
if($resolve && !is_remote_path($cpath))
|
74 |
+
{
|
75 |
+
$abs=realpath($cpath);
|
76 |
+
}
|
77 |
+
else
|
78 |
+
{
|
79 |
+
$abs=preg_replace('|\w+/\.\.\/|', '',$cpath );
|
80 |
+
$abs=preg_replace('|\./|','',$abs);
|
81 |
+
|
82 |
+
}
|
83 |
+
return $abs;
|
84 |
+
}
|
85 |
+
|
86 |
+
function truepath($path){
|
87 |
+
$opath=$path;
|
88 |
+
// whether $path is unix or not
|
89 |
+
$unipath=strlen($path)==0 || $path{0}!='/';
|
90 |
+
// attempts to detect if path is relative in which case, add cwd
|
91 |
+
if(strpos($path,':')===false && $unipath)
|
92 |
+
$path=getcwd().DIRECTORY_SEPARATOR.$path;
|
93 |
+
// resolve path parts (single dot, double dot and double delimiters)
|
94 |
+
$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
|
95 |
+
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
|
96 |
+
$absolutes = array();
|
97 |
+
foreach ($parts as $part) {
|
98 |
+
if ('.' == $part) continue;
|
99 |
+
if ('..' == $part) {
|
100 |
+
array_pop($absolutes);
|
101 |
+
} else {
|
102 |
+
$absolutes[] = $part;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
$path=implode(DIRECTORY_SEPARATOR, $absolutes);
|
106 |
+
// resolve any symlinks
|
107 |
+
if(file_exists($path) && linkinfo($path)>0)
|
108 |
+
{
|
109 |
+
$path=readlink($path);
|
110 |
+
}
|
111 |
+
// put initial separator that could have been lost
|
112 |
+
$path=!$unipath ? '/'.$path : $path;
|
113 |
+
return $path;
|
114 |
+
}
|
115 |
+
|
116 |
+
|
117 |
+
function isabspath($path)
|
118 |
+
{
|
119 |
+
return ($path[0]=="." || (substr(PHP_OS,3)=="WIN" && strlen($path)>1)?$path[1]==":":$path[0]=="/");
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
class Slugger
|
124 |
+
{
|
125 |
+
static protected $_translit=array(
|
126 |
+
'Š'=>'S', 'š'=>'s', 'Ð'=>'Dj','Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A',
|
127 |
+
'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I',
|
128 |
+
'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U',
|
129 |
+
'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss','à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a',
|
130 |
+
'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i',
|
131 |
+
'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u',
|
132 |
+
'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y', 'ƒ'=>'f'
|
133 |
+
);
|
134 |
+
|
135 |
+
public static function stripAccents($text){
|
136 |
+
|
137 |
+
return strtr($text,self::$_translit);
|
138 |
+
}
|
139 |
+
|
140 |
+
public static function slug($str,$allowslash=false)
|
141 |
+
{
|
142 |
+
$str = strtolower(self::stripAccents(trim($str)));
|
143 |
+
$rerep=$allowslash?'[^a-z0-9-/]':'[^a-z0-9-]';
|
144 |
+
$str = preg_replace("|$rerep|", '-', $str);
|
145 |
+
$str = preg_replace('|-+|', "-", $str);
|
146 |
+
$str = preg_replace('|-$|', "", $str);
|
147 |
+
return $str;
|
148 |
+
}
|
149 |
+
}
|
lib/Magmi/inc/magmi_version.php
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_Version
|
3 |
+
{
|
4 |
+
public static $version="0.7.18";
|
5 |
+
}
|
lib/Magmi/inc/properties.php
ADDED
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
if(!defined("DS"))
|
3 |
+
{
|
4 |
+
define("DS",DIRECTORY_SEPARATOR);
|
5 |
+
}
|
6 |
+
class FileNotFoundException extends Exception
|
7 |
+
{
|
8 |
+
|
9 |
+
}
|
10 |
+
class InvalidPropertiesException extends Exception
|
11 |
+
{
|
12 |
+
|
13 |
+
}
|
14 |
+
class Properties
|
15 |
+
{
|
16 |
+
protected $_props;
|
17 |
+
public $inifile;
|
18 |
+
protected $_specialchars=array('"'=>":DQUOTE:",
|
19 |
+
"'"=>":SQUOTE:",
|
20 |
+
'\\t'=>"TAB");
|
21 |
+
public function __construct()
|
22 |
+
{
|
23 |
+
$this->inifile=null;
|
24 |
+
$this->_props=array();
|
25 |
+
}
|
26 |
+
|
27 |
+
public function setPropsFromFlatArray($flatarr)
|
28 |
+
{
|
29 |
+
|
30 |
+
$this->_props=$this->getIniStruct($flatarr);
|
31 |
+
}
|
32 |
+
|
33 |
+
public function setProps($proparr)
|
34 |
+
{
|
35 |
+
$this->_props=$proparr;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function load($file)
|
39 |
+
{
|
40 |
+
if(!file_exists($file))
|
41 |
+
{
|
42 |
+
return;
|
43 |
+
//throw new FileNotFoundException();
|
44 |
+
|
45 |
+
}
|
46 |
+
try
|
47 |
+
{
|
48 |
+
$this->inifile=$file;
|
49 |
+
$this->_props=parse_ini_file($this->inifile,true);
|
50 |
+
foreach($this->_props as $sec=>$data)
|
51 |
+
{
|
52 |
+
foreach($data as $k=>$v)
|
53 |
+
{
|
54 |
+
foreach($this->_specialchars as $spch=>$alias)
|
55 |
+
{
|
56 |
+
$newv=str_replace($alias,$spch,$v);
|
57 |
+
if($newv!=$v)
|
58 |
+
{
|
59 |
+
break;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
$this->_props[$sec][$k]=$newv;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
catch(Exception $e)
|
67 |
+
{
|
68 |
+
throw new InvalidPropertiesException();
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getIniStruct($arr)
|
73 |
+
{
|
74 |
+
$conf=array();
|
75 |
+
foreach($arr as $k=>$v)
|
76 |
+
{
|
77 |
+
list($section,$value)=explode(":",$k,2);
|
78 |
+
if(!isset($conf[$section]))
|
79 |
+
{
|
80 |
+
$conf[$section]=array();
|
81 |
+
}
|
82 |
+
$conf[$section][$value]=$v;
|
83 |
+
}
|
84 |
+
return $conf;
|
85 |
+
}
|
86 |
+
|
87 |
+
public function save($fname=null)
|
88 |
+
{
|
89 |
+
if($fname==null)
|
90 |
+
{
|
91 |
+
$fname==$this->inifile;
|
92 |
+
}
|
93 |
+
return $this->write_ini_file($this->_props,$fname,true);
|
94 |
+
}
|
95 |
+
|
96 |
+
public function esc($str)
|
97 |
+
{
|
98 |
+
foreach($this->_specialchars as $spch=>$alias)
|
99 |
+
{
|
100 |
+
$str=str_replace($spch,$alias,$str);
|
101 |
+
}
|
102 |
+
return $str;
|
103 |
+
}
|
104 |
+
|
105 |
+
public function write_ini_file($assoc_arr, $path, $has_sections=FALSE) {
|
106 |
+
$content = "";
|
107 |
+
if(count($assoc_arr)>0)
|
108 |
+
{
|
109 |
+
if ($has_sections) {
|
110 |
+
foreach ($assoc_arr as $key=>$elem) {
|
111 |
+
$content .= "[".$key."]\n";
|
112 |
+
foreach ($elem as $key2=>$elem2) {
|
113 |
+
if(is_array($elem2))
|
114 |
+
{
|
115 |
+
for($i=0;$i<count($elem2);$i++)
|
116 |
+
{
|
117 |
+
$content .= $key2."[] = \"".$this->esc($elem2[$i])."\"\n";
|
118 |
+
}
|
119 |
+
}
|
120 |
+
else if($elem2=="") $content .= $key2." = \n";
|
121 |
+
else $content .= $key2." = \"".$this->esc($elem2)."\"\n";
|
122 |
+
}
|
123 |
+
}
|
124 |
+
}
|
125 |
+
else {
|
126 |
+
foreach ($assoc_arr as $key=>$elem) {
|
127 |
+
if(is_array($elem))
|
128 |
+
{
|
129 |
+
for($i=0;$i<count($elem);$i++)
|
130 |
+
{
|
131 |
+
$content .= $key2."[] = \"".$this->esc($elem[$i])."\"\n";
|
132 |
+
}
|
133 |
+
}
|
134 |
+
else if($elem=="") $content .= $key2." = \n";
|
135 |
+
else $content .= $key2." = \"".$this->esc($elem)."\"\n";
|
136 |
+
}
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
if (!$handle = fopen($path, 'w')) {
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
if (!fwrite($handle, $content)) {
|
144 |
+
return false;
|
145 |
+
}
|
146 |
+
@chmod($path,0664);
|
147 |
+
fclose($handle);
|
148 |
+
return true;
|
149 |
+
}
|
150 |
+
|
151 |
+
public function set($secname,$pname,$val)
|
152 |
+
{
|
153 |
+
$this->_props[$secname][$pname]=$val;
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* retrieve property value with default if not found
|
158 |
+
* @param string $secname section name
|
159 |
+
* @param string $pname property name
|
160 |
+
* @param string $default default value if not found (null if not set)
|
161 |
+
* @return string value if found or default if not found
|
162 |
+
*/
|
163 |
+
public function get($secname,$pname,$default=null)
|
164 |
+
{
|
165 |
+
if(isset($this->_props[$secname]) && isset($this->_props[$secname][$pname]))
|
166 |
+
{
|
167 |
+
$v=$this->_props[$secname][$pname];
|
168 |
+
return $v;
|
169 |
+
}
|
170 |
+
else
|
171 |
+
{
|
172 |
+
return $default;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
public function getsection($secname)
|
177 |
+
{
|
178 |
+
if(isset($this->_props[$secname]))
|
179 |
+
{
|
180 |
+
return $this->_props[$secname];
|
181 |
+
}
|
182 |
+
else
|
183 |
+
{
|
184 |
+
return array();
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
public function hasSection($secname)
|
189 |
+
{
|
190 |
+
return isset($this->_props[$secname]);
|
191 |
+
}
|
192 |
+
|
193 |
+
public function removeSection($secname)
|
194 |
+
{
|
195 |
+
if($this->hasSection($secname))
|
196 |
+
{
|
197 |
+
unset($this->_props[$secname]);
|
198 |
+
}
|
199 |
+
}
|
200 |
+
|
201 |
+
|
202 |
+
}
|
lib/Magmi/integration/inc/magmi_datapump.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("properties.php");
|
3 |
+
|
4 |
+
class Magmi_DataPumpFactory
|
5 |
+
{
|
6 |
+
static protected $_factoryprops=null;
|
7 |
+
static function getDataPumpInstance($pumptype)
|
8 |
+
{
|
9 |
+
if(self::$_factoryprops==null)
|
10 |
+
{
|
11 |
+
self::$_factoryprops=new Properties();
|
12 |
+
self::$_factoryprops->load(dirname(__FILE__).DS."pumpfactory.ini");
|
13 |
+
}
|
14 |
+
$pumpinfo=self::$_factoryprops->get("DATAPUMPS",$pumptype,"");
|
15 |
+
$arr=explode("::",$pumpinfo);
|
16 |
+
if(count($arr)==2)
|
17 |
+
{
|
18 |
+
$pumpfile=$arr[0];
|
19 |
+
$pumpclass=$arr[1];
|
20 |
+
|
21 |
+
try
|
22 |
+
{
|
23 |
+
require_once(dirname(__FILE__).DS."$pumpfile.php");
|
24 |
+
$pumpinst=new $pumpclass();
|
25 |
+
}
|
26 |
+
catch(Exception $e)
|
27 |
+
{
|
28 |
+
$pumpinst=null;
|
29 |
+
}
|
30 |
+
}
|
31 |
+
else
|
32 |
+
{
|
33 |
+
echo "Invalid Pump Type";
|
34 |
+
}
|
35 |
+
return $pumpinst;
|
36 |
+
}
|
37 |
+
}
|
lib/Magmi/integration/inc/magmi_datapumpdatasource.php
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This is a fake datasource for datapump, it just does nothing ;)
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
*/
|
7 |
+
class Magmi_DatapumpDS extends Magmi_Datasource
|
8 |
+
{
|
9 |
+
|
10 |
+
public function getPluginInfo()
|
11 |
+
{
|
12 |
+
return array("name"=>"DataPump Datasource",
|
13 |
+
"author"=>"Dweeves",
|
14 |
+
"version"=>"1.0.0");
|
15 |
+
}
|
16 |
+
|
17 |
+
|
18 |
+
}
|
lib/Magmi/integration/inc/productimport_datapump.php
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
require_once("magmi_productimportengine.php");
|
4 |
+
|
5 |
+
class Magmi_ProductImport_DataPump
|
6 |
+
{
|
7 |
+
protected $_engine=null;
|
8 |
+
protected $_params=array();
|
9 |
+
protected $_logger=null;
|
10 |
+
protected $_importcolumns=array();
|
11 |
+
protected $_defaultvalues=array();
|
12 |
+
protected $_stats;
|
13 |
+
protected $_crow;
|
14 |
+
protected $_rstep=100;
|
15 |
+
protected $_mdpatched=false;
|
16 |
+
|
17 |
+
|
18 |
+
public function __construct()
|
19 |
+
{
|
20 |
+
$this->_engine=new Magmi_ProductImportEngine();
|
21 |
+
$this->_engine->setBuiltinPluginClasses("*datasources",dirname(__FILE__).DS."magmi_datapumpdatasource.php::Magmi_DatapumpDS");
|
22 |
+
|
23 |
+
$this->_stats["tstart"]=microtime(true);
|
24 |
+
//differential
|
25 |
+
$this->_stats["tdiff"]=$this->_stats["tstart"];
|
26 |
+
}
|
27 |
+
|
28 |
+
public function setReportingStep($rstep)
|
29 |
+
{
|
30 |
+
$this->_rstep=$rstep;
|
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 |
+
|
49 |
+
|
50 |
+
public function setDefaultValues($dv=array())
|
51 |
+
{
|
52 |
+
$this->_defaultvalues=$dv;
|
53 |
+
}
|
54 |
+
|
55 |
+
|
56 |
+
public function ingest($item=array())
|
57 |
+
{
|
58 |
+
$item=array_merge($this->_defaultvalues,$item);
|
59 |
+
$diff=array_diff(array_keys($item),$this->_importcolumns);
|
60 |
+
if(count($diff)>0)
|
61 |
+
{
|
62 |
+
$this->_importcolumns=array_keys($item);
|
63 |
+
//process columns
|
64 |
+
$this->_engine->callPlugins("itemprocessors","processColumnList",$this->_importcolumns);
|
65 |
+
$this->_engine->initAttrInfos($this->_importcolumns);
|
66 |
+
}
|
67 |
+
$res=$this->_engine->processDataSourceLine($item, $this->_rstep,$this->_stats["tstart"],$this->_stats["tdiff"],$this->_stats["lastdbtime"],$_this->stats["lastrec"]);
|
68 |
+
|
69 |
+
}
|
70 |
+
|
71 |
+
public function endImportSession()
|
72 |
+
{
|
73 |
+
$this->_engine->reportStats($this->_engine->getCurrentRow(),$this->_stats["tstart"],$this->_stats["tdiff"],$this->_stats["lastdbtime"],$_this->stats["lastrec"]);
|
74 |
+
$skustats=$this->_engine->getSkuStats();
|
75 |
+
$this->_engine->log("Skus imported OK:".$skustats["ok"]."/".$skustats["nsku"],"info");
|
76 |
+
if($skustats["ko"]>0)
|
77 |
+
{
|
78 |
+
$this->_engine->log("Skus imported KO:".$skustats["ko"]."/".$skustats["nsku"],"warning");
|
79 |
+
}
|
80 |
+
|
81 |
+
$this->_engine->exitImport();
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
lib/Magmi/integration/inc/pumpfactory.ini
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
[DATAPUMPS]
|
2 |
+
productimport=productimport_datapump::Magmi_ProductImport_Datapump
|
lib/Magmi/integration/samples/sample.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("../../inc/magmi_defs.php");
|
3 |
+
require_once("../inc/magmi_datapump.php");
|
4 |
+
|
5 |
+
|
6 |
+
/** Define a logger class that will receive all magmi logs **/
|
7 |
+
class TestLogger
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* logging methos
|
11 |
+
* @param string $data : log content
|
12 |
+
* @param string $type : log type
|
13 |
+
*/
|
14 |
+
public function log($data,$type)
|
15 |
+
{
|
16 |
+
echo "$type:$data\n";
|
17 |
+
}
|
18 |
+
}
|
19 |
+
/**
|
20 |
+
* create a Product import Datapump using Magmi_DatapumpFactory
|
21 |
+
*/
|
22 |
+
$dp=Magmi_DataPumpFactory::getDataPumpInstance("productimport");
|
23 |
+
/**
|
24 |
+
* Start import session
|
25 |
+
* with :
|
26 |
+
* - profile : test_ptj
|
27 |
+
* - mode : create
|
28 |
+
* - logger : an instance of the class defined above
|
29 |
+
*/
|
30 |
+
|
31 |
+
/**
|
32 |
+
* FOR THE SAMPLE TO WORK CORRECTLY , YOU HAVE TO DEFINE A test_ptj profile with :
|
33 |
+
* UPSELL/CROSS SELL, ITEM RELATER, CATEGORIES IMPORTER/CREATOR selected
|
34 |
+
* ON THE FLY INDEXER IS RECOMMENDED (better endimport performance)
|
35 |
+
* Reindexer needed also to have products show up on front : select all but "catalog_category_product" & "url_rewrite" (both are handled by on the fly indexer)
|
36 |
+
*/
|
37 |
+
$dp->beginImportSession("test_ptj","create",new TestLogger());
|
38 |
+
|
39 |
+
/* Create 5000 items , with every 100 :
|
40 |
+
*
|
41 |
+
* upsell on last 100 even
|
42 |
+
* cross sell on last 100 odd
|
43 |
+
* related on last 100 every 5
|
44 |
+
* cross sell on last 100 every 10
|
45 |
+
* categories named catX/even or catX/odd with X is thousand of item (using categories plugin) */
|
46 |
+
for($sku=0;$sku<5000;$sku++)
|
47 |
+
{
|
48 |
+
//create item category path array
|
49 |
+
//catX/even or catX/odd, X being the 1000's of the item
|
50 |
+
$cats=array("cat".strval(intval($sku/1000)));
|
51 |
+
if($sku%2==0)
|
52 |
+
{
|
53 |
+
$cats[]="even";
|
54 |
+
}
|
55 |
+
else
|
56 |
+
{
|
57 |
+
$cats[]="odd";
|
58 |
+
}
|
59 |
+
//create item to import
|
60 |
+
// sku : XXXXX , 5 numbers , padded left with current loop counter as sku
|
61 |
+
// name : itemXXXXX
|
62 |
+
// description : testXXXXX
|
63 |
+
// price : random between $1 & $500
|
64 |
+
// categories : the ones built above
|
65 |
+
$item=array("sku"=>str_pad($sku,5,"0",STR_PAD_LEFT),"name"=>"item".$sku,"description"=>"test".$sku,"price"=>rand(1,500),"categories"=>implode("/",$cats));
|
66 |
+
//now some fun, every 100 items, create some relations
|
67 |
+
if($sku>99 && $sku%100==0)
|
68 |
+
{
|
69 |
+
//first, we'll remove all existing relations (upsell/cross sell / related)
|
70 |
+
$upsell=array("-re::.*");
|
71 |
+
$csell=array("-re::.*");
|
72 |
+
$re=array("-re::.*");
|
73 |
+
$xre=array();
|
74 |
+
for($i=$sku-99;$i<$sku;$i++)
|
75 |
+
{
|
76 |
+
//related item sku
|
77 |
+
$rsku=str_pad($i,5,"0",STR_PAD_LEFT);
|
78 |
+
//add upselling on each odd item in the 100 before the current
|
79 |
+
if($i%2==1)
|
80 |
+
{
|
81 |
+
$upsell[]=$rsku;
|
82 |
+
}
|
83 |
+
else
|
84 |
+
//add cross sell on each even item in the 100 before the current
|
85 |
+
{
|
86 |
+
$csell[]=$rsku;
|
87 |
+
}
|
88 |
+
|
89 |
+
//on each 10 before, cross relate
|
90 |
+
if($i%10==0)
|
91 |
+
{
|
92 |
+
$xre[]="-$rsku";
|
93 |
+
}
|
94 |
+
else
|
95 |
+
{
|
96 |
+
//on each 5 before , single relate
|
97 |
+
if($i%5==0)
|
98 |
+
{
|
99 |
+
$re[]=$rsku;
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
103 |
+
//fill upsell with the computed skus from rules above
|
104 |
+
$item["us_skus"]=implode(",",$upsell);
|
105 |
+
//fill cross sell with the computed skus from rules above
|
106 |
+
$item["cs_skus"]=implode(",",$csell);
|
107 |
+
//fill single related with the computed skus from rules above
|
108 |
+
$item["re_skus"]=implode(",",$re);
|
109 |
+
//fill cross related with the computed skus from rules above
|
110 |
+
$item["xre_skus"]=implode(",",$xre);
|
111 |
+
}
|
112 |
+
/* import current item */
|
113 |
+
$dp->ingest($item);
|
114 |
+
}
|
115 |
+
/* end import session, will run post import plugins */
|
116 |
+
$dp->endImportSession();
|
117 |
+
|
lib/Magmi/integration/samples/sample2_configurables.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("../../inc/magmi_defs.php");
|
3 |
+
require_once("../inc/magmi_datapump.php");
|
4 |
+
|
5 |
+
|
6 |
+
/** Define a logger class that will receive all magmi logs **/
|
7 |
+
class TestLogger
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* logging methos
|
11 |
+
* @param string $data : log content
|
12 |
+
* @param string $type : log type
|
13 |
+
*/
|
14 |
+
public function log($data,$type)
|
15 |
+
{
|
16 |
+
echo "$type:$data\n";
|
17 |
+
}
|
18 |
+
}
|
19 |
+
/**
|
20 |
+
* create a Product import Datapump using Magmi_DatapumpFactory
|
21 |
+
*/
|
22 |
+
$dp=Magmi_DataPumpFactory::getDataPumpInstance("productimport");
|
23 |
+
/**
|
24 |
+
* Start import session
|
25 |
+
* with :
|
26 |
+
* - profile : test_ptj
|
27 |
+
* - mode : create
|
28 |
+
* - logger : an instance of the class defined above
|
29 |
+
*/
|
30 |
+
|
31 |
+
/**
|
32 |
+
* FOR THE SAMPLE TO WORK CORRECTLY , YOU HAVE TO DEFINE A test_ptj profile with :
|
33 |
+
* UPSELL/CROSS SELL, ITEM RELATER, CATEGORIES IMPORTER/CREATOR selected
|
34 |
+
* ON THE FLY INDEXER IS RECOMMENDED (better endimport performance)
|
35 |
+
* Reindexer needed also to have products show up on front : select all but "catalog_category_product" & "url_rewrite" (both are handled by on the fly indexer)
|
36 |
+
*/
|
37 |
+
$dp->beginImportSession("default","create",new TestLogger());
|
38 |
+
|
39 |
+
/* Create 5000 items , with every 100 :
|
40 |
+
*
|
41 |
+
* upsell on last 100 even
|
42 |
+
* cross sell on last 100 odd
|
43 |
+
* related on last 100 every 5
|
44 |
+
* cross sell on last 100 every 10
|
45 |
+
* categories named catX/even or catX/odd with X is thousand of item (using categories plugin) */
|
46 |
+
for($sku=0;$sku<=200;$sku++)
|
47 |
+
{
|
48 |
+
// price : random between $1 & $500
|
49 |
+
$item=array("store"=>"admin","type"=>"simple","sku"=>str_pad($sku,5,"0",STR_PAD_LEFT),"name"=>"item".$sku,"description"=>"test".$sku,"price"=>rand(1,500),"min_qty"=>3,"qty"=>"+7");
|
50 |
+
//color : radom c0/c10
|
51 |
+
$item["color"]="c".strval(rand(0, 10));
|
52 |
+
|
53 |
+
//now some fun, every 100 items, create some relations
|
54 |
+
if($sku>99 && $sku%100==0)
|
55 |
+
{
|
56 |
+
//first, we'll remove all existing relations (upsell/cross sell / related)
|
57 |
+
$subskus=array();
|
58 |
+
for($i=$sku-99;$i<$sku;$i++)
|
59 |
+
{
|
60 |
+
//related item sku
|
61 |
+
$subskus[]=str_pad($i,5,"0",STR_PAD_LEFT);
|
62 |
+
}
|
63 |
+
$item["simples_skus"]=implode(",",$subskus);
|
64 |
+
$item["type"]="configurable";
|
65 |
+
$item["configurable_attributes"]="color";
|
66 |
+
//cross relate with all skus ending by 2
|
67 |
+
$item["xre_skus"]="re::.*2$";
|
68 |
+
//star relate all skus ending with 1
|
69 |
+
$item["*re_skus"]="re::.*1$";
|
70 |
+
|
71 |
+
|
72 |
+
}
|
73 |
+
|
74 |
+
/* import current item */
|
75 |
+
$dp->ingest($item);
|
76 |
+
}
|
77 |
+
/* end import session, will run post import plugins */
|
78 |
+
$dp->endImportSession();
|
79 |
+
|
lib/Magmi/plugins/base/datasources/__magento/magmi_magentodatasource.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_engine.php");
|
3 |
+
|
4 |
+
class Magmi_DSEngine extends Magmi_Engine
|
5 |
+
{
|
6 |
+
public function engineInit($params)
|
7 |
+
{
|
8 |
+
|
9 |
+
}
|
10 |
+
|
11 |
+
public function engineRun($params)
|
12 |
+
{
|
13 |
+
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
class Magmi_MagentoDatasource extends Magmi_Datasource
|
18 |
+
{
|
19 |
+
public function initialize($params)
|
20 |
+
{
|
21 |
+
$this->engine=new Magmi_DSEngine();
|
22 |
+
$this->extractSQL=$this->buildSQL();
|
23 |
+
}
|
24 |
+
|
25 |
+
public function buildSQL()
|
26 |
+
{
|
27 |
+
|
28 |
+
}
|
29 |
+
|
30 |
+
public function getPluginInfo()
|
31 |
+
{
|
32 |
+
return array("name"=>"Magento Products Datasource",
|
33 |
+
"author"=>"Dweeves",
|
34 |
+
"version"=>"1.0.0");
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getPluginParamNames()
|
38 |
+
{
|
39 |
+
return array("MAGDS:fields");
|
40 |
+
}
|
41 |
+
|
42 |
+
public function startImport()
|
43 |
+
{
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
|
48 |
+
public function getRecordsCount()
|
49 |
+
{
|
50 |
+
$sql=null;
|
51 |
+
//optimized count query
|
52 |
+
$sql="SELECT COUNT(*) as cnt FROM (".str_replace("\n"," ",$this->extractsql).") as t1";
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getColumnNames($prescan=false)
|
56 |
+
{
|
57 |
+
$s=$this->dbh->select($this->extractsql);
|
58 |
+
$test=$s->fetch();
|
59 |
+
$s->closeCursor();
|
60 |
+
unset($s);
|
61 |
+
$cl=array_keys($test);
|
62 |
+
return $cl;
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
|
67 |
+
public function getNextRecord()
|
68 |
+
{
|
69 |
+
if(!isset($this->stmt))
|
70 |
+
{
|
71 |
+
$this->stmt=$this->dbh->select($this->extractsql);
|
72 |
+
}
|
73 |
+
$data=$this->stmt->fetch();
|
74 |
+
if(!$data)
|
75 |
+
{
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
return $data;
|
79 |
+
}
|
80 |
+
|
81 |
+
public function endImport()
|
82 |
+
{
|
83 |
+
|
84 |
+
}
|
85 |
+
public function afterImport()
|
86 |
+
{
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
lib/Magmi/plugins/base/datasources/__magento/options_panel.php
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="plugin_description">
|
3 |
+
This plugin enables magmi <b>mass updates</b> by selecting
|
4 |
+
existing products from magento database
|
5 |
+
</div>
|
6 |
+
|
lib/Magmi/plugins/base/datasources/csv/csvds_filelist.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
$files=$this->getCSVList();
|
3 |
+
if($files!==false && count($files)>0){?>
|
4 |
+
<select name="CSV:filename" id="csvfile">
|
5 |
+
<?php foreach($files as $fname){ ?>
|
6 |
+
<option <?php if($fname==$this->getParam("CSV:filename")){?>selected=selected<?php }?> value="<?php echo $fname?>"><?php echo basename($fname)?></option>
|
7 |
+
<?php }?>
|
8 |
+
</select>
|
9 |
+
<a id='csvdl' href="./download_file.php?file=<?php $this->getParam("CSV:filename")?>">Download CSV</a>
|
10 |
+
<script type="text/javascript">
|
11 |
+
$('csvdl').observe('click',function(el){
|
12 |
+
var fval=$('csvfile').value;
|
13 |
+
$('csvdl').href="./download_file.php?file="+fval;}
|
14 |
+
);
|
15 |
+
</script><?php } else {?>
|
16 |
+
<span> No csv files found in <?php echo $this->getScanDir(false)?></span>
|
17 |
+
<?php }?>
|
lib/Magmi/plugins/base/datasources/csv/magmi_csvdatasource.php
ADDED
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_csvreader.php");
|
3 |
+
|
4 |
+
|
5 |
+
class Magmi_CSVDataSource extends Magmi_Datasource
|
6 |
+
{
|
7 |
+
protected $_csvreader;
|
8 |
+
|
9 |
+
public function initialize($params)
|
10 |
+
{
|
11 |
+
$this->_csvreader=new Magmi_CSVReader();
|
12 |
+
$this->_csvreader->bind($this);
|
13 |
+
$this->_csvreader->initialize();
|
14 |
+
|
15 |
+
}
|
16 |
+
|
17 |
+
public function getAbsPath($path)
|
18 |
+
{
|
19 |
+
|
20 |
+
return abspath($path,$this->getScanDir());
|
21 |
+
|
22 |
+
}
|
23 |
+
|
24 |
+
public function getScanDir($resolve=true)
|
25 |
+
{
|
26 |
+
$scandir=$this->getParam("CSV:basedir","var/import");
|
27 |
+
if(!isabspath($scandir))
|
28 |
+
{
|
29 |
+
$scandir=abspath($scandir,Magmi_Config::getInstance()->getMagentoDir(),$resolve);
|
30 |
+
}
|
31 |
+
return $scandir;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function getCSVList()
|
35 |
+
{
|
36 |
+
$scandir=$this->getScanDir();
|
37 |
+
$files=glob("$scandir/*.csv");
|
38 |
+
return $files;
|
39 |
+
}
|
40 |
+
|
41 |
+
public function getPluginParams($params)
|
42 |
+
{
|
43 |
+
$pp=array();
|
44 |
+
foreach($params as $k=>$v)
|
45 |
+
{
|
46 |
+
if(preg_match("/^CSV:.*$/",$k))
|
47 |
+
{
|
48 |
+
$pp[$k]=$v;
|
49 |
+
}
|
50 |
+
}
|
51 |
+
return $pp;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function getPluginInfo()
|
55 |
+
{
|
56 |
+
return array("name"=>"CSV Datasource",
|
57 |
+
"author"=>"Dweeves",
|
58 |
+
"version"=>"1.3");
|
59 |
+
}
|
60 |
+
|
61 |
+
public function getRecordsCount()
|
62 |
+
{
|
63 |
+
return $this->_csvreader->getLinesCount();
|
64 |
+
}
|
65 |
+
|
66 |
+
public function getAttributeList()
|
67 |
+
{
|
68 |
+
|
69 |
+
}
|
70 |
+
|
71 |
+
public function getRemoteFile($url,$creds=null,$authmode=null,$cookies=null)
|
72 |
+
{
|
73 |
+
$ch = curl_init($url);
|
74 |
+
$this->log("Fetching CSV: $url","startup");
|
75 |
+
//output filename (current dir+remote filename)
|
76 |
+
$csvdldir=dirname(__FILE__)."/downloads";
|
77 |
+
if(!file_exists($csvdldir))
|
78 |
+
{
|
79 |
+
@mkdir($csvdldir);
|
80 |
+
@chmod($csvdldir, Magmi_Config::getInstance()->getDirMask());
|
81 |
+
}
|
82 |
+
|
83 |
+
$outname=$csvdldir."/".basename($url);
|
84 |
+
$ext = substr(strrchr($outname, '.'), 1);
|
85 |
+
if($ext!=".txt" && $ext!=".csv")
|
86 |
+
{
|
87 |
+
$outname=$outname.".csv";
|
88 |
+
}
|
89 |
+
//open file for writing
|
90 |
+
if(file_exists($outname))
|
91 |
+
{
|
92 |
+
unlink($outname);
|
93 |
+
}
|
94 |
+
$fp = fopen($outname, "w");
|
95 |
+
if($fp==false)
|
96 |
+
{
|
97 |
+
throw new Exception("Cannot write file:$outname");
|
98 |
+
}
|
99 |
+
if(substr($url,0,4)=="http")
|
100 |
+
{
|
101 |
+
$lookup=1;
|
102 |
+
|
103 |
+
$lookup_opts= array(CURLOPT_RETURNTRANSFER=>true,
|
104 |
+
CURLOPT_HEADER=>true,
|
105 |
+
CURLOPT_NOBODY=>true,
|
106 |
+
CURLOPT_FOLLOWLOCATION=>true,
|
107 |
+
CURLOPT_FILETIME=>true,
|
108 |
+
CURLOPT_CUSTOMREQUEST=>"HEAD");
|
109 |
+
|
110 |
+
$dl_opts=array(CURLOPT_FILE=>$fp,
|
111 |
+
CURLOPT_CUSTOMREQUEST=>"GET",
|
112 |
+
CURLOPT_HEADER=>false,
|
113 |
+
CURLOPT_NOBODY=>false,
|
114 |
+
CURLOPT_FOLLOWLOCATION=>true,
|
115 |
+
CURLOPT_UNRESTRICTED_AUTH=>true,
|
116 |
+
CURLOPT_HTTPHEADER=> array('Expect:'));
|
117 |
+
|
118 |
+
}
|
119 |
+
else
|
120 |
+
{
|
121 |
+
if(substr($url,0,3)=="ftp")
|
122 |
+
{
|
123 |
+
$lookup=0;
|
124 |
+
$dl_opts=array(CURLOPT_FILE=>$fp);
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
|
129 |
+
if($creds!="")
|
130 |
+
{
|
131 |
+
if($lookup!=0)
|
132 |
+
{
|
133 |
+
if(substr($url,0,4)=="http")
|
134 |
+
{
|
135 |
+
$lookup_opts[CURLOPT_HTTPAUTH]=CURLAUTH_ANY;
|
136 |
+
$lookup_opts[CURLOPT_UNRESTRICTED_AUTH]=true;
|
137 |
+
}
|
138 |
+
$lookup_opts[CURLOPT_USERPWD]="$creds";
|
139 |
+
}
|
140 |
+
|
141 |
+
|
142 |
+
if(substr($url,0,4)=="http")
|
143 |
+
{
|
144 |
+
$dl_opts[CURLOPT_HTTPAUTH]=CURLAUTH_ANY;
|
145 |
+
$dl_opts[CURLOPT_UNRESTRICTED_AUTH]=true;
|
146 |
+
}
|
147 |
+
$dl_opts[CURLOPT_USERPWD]="$creds";
|
148 |
+
}
|
149 |
+
|
150 |
+
if($cookies)
|
151 |
+
{
|
152 |
+
if($lookup!=0)
|
153 |
+
{
|
154 |
+
if(substr($url,0,4)=="http")
|
155 |
+
{
|
156 |
+
$lookup_opts[CURLOPT_COOKIE]=$cookies;
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
if(substr($url,0,4)=="http")
|
161 |
+
{
|
162 |
+
$dl_opts[CURLOPT_COOKIE]=$cookies;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
|
166 |
+
if($lookup)
|
167 |
+
{
|
168 |
+
//lookup , using HEAD request
|
169 |
+
$ok=curl_setopt_array($ch,$lookup_opts);
|
170 |
+
$res=curl_exec($ch);
|
171 |
+
if($res!==false)
|
172 |
+
{
|
173 |
+
$lm=curl_getinfo($ch);
|
174 |
+
if(curl_getinfo($ch,CURLINFO_HTTP_CODE)!=200)
|
175 |
+
{
|
176 |
+
$resp = explode("\n\r\n", $res);
|
177 |
+
$this->log("http header:<pre>".$resp[0]."</pre>","error");
|
178 |
+
throw new Exception("Cannot fetch $url");
|
179 |
+
|
180 |
+
}
|
181 |
+
}
|
182 |
+
else
|
183 |
+
{
|
184 |
+
$lm=curl_getinfo($ch);
|
185 |
+
throw new Exception("Cannot fetch $url");
|
186 |
+
}
|
187 |
+
|
188 |
+
}
|
189 |
+
|
190 |
+
$res=array("should_dl"=>true,"reason"=>"");
|
191 |
+
|
192 |
+
if($res["should_dl"])
|
193 |
+
{
|
194 |
+
//clear url options
|
195 |
+
$ok=curl_setopt_array($ch, array());
|
196 |
+
|
197 |
+
//Download the file , force expect to nothing to avoid buffer save problem
|
198 |
+
curl_setopt_array($ch,$dl_opts);
|
199 |
+
curl_exec($ch);
|
200 |
+
if(curl_error($ch)!="")
|
201 |
+
{
|
202 |
+
$this->log(curl_error($ch),"error");
|
203 |
+
throw new Exception("Cannot fetch $url");
|
204 |
+
}
|
205 |
+
else
|
206 |
+
{
|
207 |
+
$lm=curl_getinfo($ch);
|
208 |
+
|
209 |
+
$this->log("CSV Fetched in ".$lm['total_time']. "secs","startup");
|
210 |
+
}
|
211 |
+
curl_close($ch);
|
212 |
+
fclose($fp);
|
213 |
+
|
214 |
+
}
|
215 |
+
else
|
216 |
+
{
|
217 |
+
curl_close($ch);
|
218 |
+
//bad file or bad hour, no download this time
|
219 |
+
$this->log("No dowload , ".$res["reason"],"info");
|
220 |
+
}
|
221 |
+
//return the csv filename
|
222 |
+
return $outname;
|
223 |
+
}
|
224 |
+
public function beforeImport()
|
225 |
+
{
|
226 |
+
if($this->getParam("CSV:importmode","local")=="remote")
|
227 |
+
{
|
228 |
+
$url=$this->getParam("CSV:remoteurl","");
|
229 |
+
$creds="";
|
230 |
+
$authmode="";
|
231 |
+
if($this->getParam("CSV:remoteauth",false)==true)
|
232 |
+
{
|
233 |
+
$user=$this->getParam("CSV:remoteuser");
|
234 |
+
$pass=$this->getParam("CSV:remotepass");
|
235 |
+
|
236 |
+
$authmode=$this->getParam("CSV:authmode");
|
237 |
+
$creds="$user:$pass";
|
238 |
+
}
|
239 |
+
$cookies=$this->getParam("CSV:remotecookie");
|
240 |
+
$outname=$this->getRemoteFile($url,$creds,$authmode,$cookies);
|
241 |
+
$this->setParam("CSV:filename", $outname);
|
242 |
+
$this->_csvreader->initialize();
|
243 |
+
}
|
244 |
+
return $this->_csvreader->checkCSV();
|
245 |
+
}
|
246 |
+
|
247 |
+
public function afterImport()
|
248 |
+
{
|
249 |
+
|
250 |
+
}
|
251 |
+
|
252 |
+
public function startImport()
|
253 |
+
{
|
254 |
+
$this->_csvreader->openCSV();
|
255 |
+
}
|
256 |
+
|
257 |
+
public function getColumnNames($prescan=false)
|
258 |
+
{
|
259 |
+
return $this->_csvreader->getColumnNames($prescan);
|
260 |
+
}
|
261 |
+
|
262 |
+
public function endImport()
|
263 |
+
{
|
264 |
+
$this->_csvreader->closeCSV();
|
265 |
+
}
|
266 |
+
|
267 |
+
|
268 |
+
public function getNextRecord()
|
269 |
+
{
|
270 |
+
return $this->_csvreader->getNextRecord();
|
271 |
+
}
|
272 |
+
|
273 |
+
|
274 |
+
}
|
lib/Magmi/plugins/base/datasources/csv/options_panel.php
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="plugin_description">
|
3 |
+
This plugin enables magmi import from csv files (using Dataflow format + magmi extended columns)<br/> <b>NOT Magento 1.5 new importexport format!!</b>
|
4 |
+
</div>
|
5 |
+
<div>
|
6 |
+
|
7 |
+
<div class="csvmode">
|
8 |
+
</div>
|
9 |
+
|
10 |
+
<ul class="formline">
|
11 |
+
<li class="label">CSV import mode</li>
|
12 |
+
<li class="value">
|
13 |
+
<select name="CSV:importmode" id="CSV:importmode">
|
14 |
+
<option value="local" <?php if($this->getParam("CSV:importmode","local")=="local"){?>selected="selected"<?php }?>>Local</option>
|
15 |
+
<option value="remote" <?php if($this->getParam("CSV:importmode","local")=="remote"){?>selected="selected"<?php }?>>Remote</option>
|
16 |
+
</select>
|
17 |
+
</ul>
|
18 |
+
|
19 |
+
<div id="localcsv" <?php if($this->getParam("CSV:importmode","local")=="remote"){?> style="display:none"<?php }?>>
|
20 |
+
<ul class="formline">
|
21 |
+
<li class="label">CSVs base directory</li>
|
22 |
+
<li class="value">
|
23 |
+
<input type="text" name="CSV:basedir" id="CSV:basedir" value="<?php echo $this->getParam("CSV:basedir","var/import")?>"></input>
|
24 |
+
<div class="fieldinfo">Relative paths are relative to magento base directory , absolute paths will be used as is</div></li>
|
25 |
+
</ul>
|
26 |
+
<ul class="formline">
|
27 |
+
<li class="label" >File to import:</li>
|
28 |
+
<li class="value" id="csvds_filelist">
|
29 |
+
<?php echo $this->getOptionsPanel("csvds_filelist.php")->getHtml(); ?>
|
30 |
+
</li>
|
31 |
+
</ul>
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<div id="remotecsv" <?php if($this->getParam("CSV:importmode","local")=="local"){?> style="display:none"<?php }?>>
|
35 |
+
<ul class="formline">
|
36 |
+
<li class="label">Remote CSV url</li>
|
37 |
+
<li class="value">
|
38 |
+
<input type="text" name="CSV:remoteurl" id="CSV:remoteurl" value="<?php echo $this->getParam("CSV:remoteurl","")?>" style="width:400px"></input>
|
39 |
+
</li>
|
40 |
+
</ul>
|
41 |
+
<div id="remotecookie" >
|
42 |
+
<ul class="formline">
|
43 |
+
<li class="label">HTTP Cookie</li>
|
44 |
+
<li class="value"><input type="text" name="CSV:remotecookie" id="CSV:remotecookie" value="<?php echo $this->getParam("CSV:remotecookie","")?>" style="width:400px"></li>
|
45 |
+
</ul>
|
46 |
+
</div>
|
47 |
+
<input type="checkbox" id="CSV:remoteauth" name="CSV:remoteauth" <?php if($this->getParam("CSV:remoteauth",false)==true){?>checked="checked"<?php }?>>authentication needed
|
48 |
+
<div id="remoteauth" <?php if($this->getParam("CSV:remoteauth",false)==false){?>style="display:none"<?php }?>>
|
49 |
+
|
50 |
+
<div class="remoteuserpass">
|
51 |
+
<ul class="formline">
|
52 |
+
<li class="label">User</li>
|
53 |
+
<li class="value"><input type="text" name="CSV:remoteuser" id="CSV:remoteuser" value="<?php echo $this->getParam("CSV:remoteuser","")?>"></li>
|
54 |
+
|
55 |
+
</ul>
|
56 |
+
<ul class="formline">
|
57 |
+
<li class="label">Password</li>
|
58 |
+
<li class="value"><input type="text" name="CSV:remotepass" id="CSV:remotepass" value="<?php echo $this->getParam("CSV:remotepass","")?>"></li>
|
59 |
+
</ul>
|
60 |
+
</div>
|
61 |
+
|
62 |
+
</div>
|
63 |
+
|
64 |
+
</div>
|
65 |
+
|
66 |
+
|
67 |
+
</div>
|
68 |
+
<div>
|
69 |
+
<h3>CSV options</h3>
|
70 |
+
<span class="">CSV separator:</span><input type="text" maxlength="3" size="3" name="CSV:separator" value="<?php echo $this->getParam("CSV:separator")?>"></input>
|
71 |
+
<span class="">CSV Enclosure:</span><input type="text" maxlength="3" size="3" name="CSV:enclosure" value='<?php echo $this->getParam("CSV:enclosure")?>'></input>
|
72 |
+
</div>
|
73 |
+
|
74 |
+
<div class=""><input type="checkbox" name="CSV:noheader" <?php if($this->getParam("CSV:noheader",false)==true){?>checked="checked"<?php }?>>
|
75 |
+
Headerless CSV (Use Column Mapper Plugin to set processable column names)</div>
|
76 |
+
<div class=""><input type="checkbox" name="CSV:allowtrunc" <?php if($this->getParam("CSV:allowtrunc",false)==true){?>checked="checked"<?php }?>>
|
77 |
+
Allow truncated lines (bypasses data line structure correlation with headers)</div>
|
78 |
+
|
79 |
+
<?php $hdline=$this->getParam("CSV:headerline","");
|
80 |
+
$malformed=($hdline!="" && $hdline!=1)?>
|
81 |
+
<input type="checkbox" id="malformedcb" <?php if($malformed){?>checked="checked"<?php }?>/>Malformed CSV (column list line not at top of file)
|
82 |
+
<div id="malformed" <?php if(!$malformed){?>style="display:none"<?php }?>>
|
83 |
+
<span class="">CSV Header at line:</span><input type="text" id="CSV:headerline" name="CSV:headerline" maxlength="7" size="7" value="<?php echo $hdline?>"></input>
|
84 |
+
</div>
|
85 |
+
<script type="text/javascript">
|
86 |
+
handle_auth=function()
|
87 |
+
{
|
88 |
+
if($('CSV:remoteauth').checked)
|
89 |
+
{
|
90 |
+
$('remoteauth').show();
|
91 |
+
}
|
92 |
+
else
|
93 |
+
{
|
94 |
+
$('remoteauth').hide();
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
$('CSV:basedir').observe('blur',function()
|
99 |
+
{
|
100 |
+
new Ajax.Updater('csvds_filelist','ajax_pluginconf.php',{
|
101 |
+
parameters:{file:'csvds_filelist.php',
|
102 |
+
plugintype:'datasources',
|
103 |
+
pluginclass:'<?php echo get_class($this->_plugin)?>',
|
104 |
+
profile:'<?php echo $this->getConfig()->getProfile()?>',
|
105 |
+
'CSV:basedir':$F('CSV:basedir')}});
|
106 |
+
});
|
107 |
+
$('malformedcb').observe('click',function(ev){
|
108 |
+
if($('malformedcb').checked)
|
109 |
+
{
|
110 |
+
$('malformed').show();
|
111 |
+
}
|
112 |
+
else
|
113 |
+
{
|
114 |
+
$('malformed').hide();
|
115 |
+
}
|
116 |
+
});
|
117 |
+
$('CSV:headerline').observe('blur',function()
|
118 |
+
{
|
119 |
+
var wellformed=($F('CSV:headerline')=="1" || $F('CSV:headerline')=="");
|
120 |
+
if(wellformed)
|
121 |
+
{
|
122 |
+
$('malformedcb').checked=false;
|
123 |
+
$('malformed').hide();
|
124 |
+
$('CSV:headerline').value="";
|
125 |
+
}
|
126 |
+
});
|
127 |
+
$('CSV:importmode').observe('change',function()
|
128 |
+
{
|
129 |
+
if($F('CSV:importmode')=='local')
|
130 |
+
{
|
131 |
+
$('localcsv').show();
|
132 |
+
$('remotecsv').hide();
|
133 |
+
}
|
134 |
+
else
|
135 |
+
{
|
136 |
+
$('localcsv').hide();
|
137 |
+
$('remotecsv').show();
|
138 |
+
}
|
139 |
+
});
|
140 |
+
$('CSV:remoteauth').observe('click',handle_auth);
|
141 |
+
$('CSV:remoteurl').observe('blur',handle_auth);
|
142 |
+
</script>
|
lib/Magmi/plugins/base/datasources/genericsql/mysql_options.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div id="mysql_config">
|
2 |
+
<ul class="formline">
|
3 |
+
<li class="label">Input DB Host</li>
|
4 |
+
<li class="value"><input type="text" name="SQL:dbhost" value="<?php echo $this->getParam("SQL:dbhost","localhost")?>"/></li>
|
5 |
+
</ul>
|
6 |
+
<ul class="formline">
|
7 |
+
<li class="label">Input DB Name</li>
|
8 |
+
<li class="value"><input type="text" name="SQL:dbname" value="<?php echo $this->getParam("SQL:dbname","")?>"/></li>
|
9 |
+
</ul>
|
10 |
+
<ul class="formline">
|
11 |
+
<li class="label">Input DB User</li>
|
12 |
+
<li class="value"><input type="text" name="SQL:dbuser" value="<?php echo $this->getParam("SQL:dbuser","")?>"/></li>
|
13 |
+
</ul>
|
14 |
+
<ul class="formline">
|
15 |
+
<li class="label">Input DB Password</li>
|
16 |
+
<li class="value"><input type="password" name="SQL:dbpass" value="<?php echo $this->getParam("SQL:dbpass","")?>"/></li>
|
17 |
+
</ul>
|
18 |
+
<ul class="formline">
|
19 |
+
<li class="label">Input DB Initial Statements (optional)</li>
|
20 |
+
<li class="value"><textarea name="SQL:dbextra" cols="80" rows="5">
|
21 |
+
<?php echo $this->getParam("SQL:dbextra","")?>
|
22 |
+
</textarea>
|
23 |
+
<div class="fieldinfo">
|
24 |
+
Put DB requests like SET NAMES if necessary separated by ;
|
25 |
+
</div>
|
26 |
+
</li>
|
27 |
+
</ul>
|
28 |
+
</div>
|
lib/Magmi/plugins/base/datasources/genericsql/options_panel.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin imports data from Generic SQL Backend<br/>
|
3 |
+
You should put sql files in the <b><?php echo $this->getPluginDir()."/requests"?></b> directory
|
4 |
+
</div>
|
5 |
+
<ul class="formline">
|
6 |
+
<?php $dbtype=$this->getParam("SQL:dbtype");?>
|
7 |
+
<li class="label">Input DB Type</li>
|
8 |
+
<li><select name="SQL:dbtype" id="SQL:dbtype">
|
9 |
+
<option value="mysql" <?php if ($dbtype=="mysql"){?>selected="selected"<?php }?>>MySQL</option>
|
10 |
+
<option value="other" <?php if ($dbtype=="other"){?>selected="selected"<?php }?>>Other</option>
|
11 |
+
</select></li>
|
12 |
+
</ul>
|
13 |
+
<div id="options_container">
|
14 |
+
<?php echo $this->getOptionsPanel("$dbtype"."_options.php")->getHtml();?>
|
15 |
+
</div>
|
16 |
+
<ul class="formline">
|
17 |
+
<li class="label">SQL file</li>
|
18 |
+
<li class="value">
|
19 |
+
<?php $dr=$this->getParam("SQL:queryfile");?>
|
20 |
+
<?php $sqlfiles=$this->getSQLFileList();?>
|
21 |
+
<?php if(count($sqlfiles)>0){?>
|
22 |
+
|
23 |
+
<select name="SQL:queryfile">
|
24 |
+
<?php foreach($sqlfiles as $curfile):?>
|
25 |
+
<option <?php if($curfile==$dr){?>selected=selected<?php }?> value="<?php echo $curfile?>" ><?php echo basename($curfile)?></option>
|
26 |
+
<?php endforeach?>
|
27 |
+
</select>
|
28 |
+
<?php }else{?>
|
29 |
+
<span class="error">No SQL files detected in <?php echo $this->getPluginDir()."/requests"?></span>
|
30 |
+
<?php }?>
|
31 |
+
</li>
|
32 |
+
</ul>
|
33 |
+
<script type="text/javascript">
|
34 |
+
var dbt=$('SQL:dbtype');
|
35 |
+
dbt.observe('change',function(ev)
|
36 |
+
{
|
37 |
+
new Ajax.Updater('options_container','ajax_pluginconf.php',{
|
38 |
+
parameters:{file:$('SQL:dbtype').value+'_options.php',
|
39 |
+
plugintype:'datasources',
|
40 |
+
pluginclass:'<?php echo get_class($this->_plugin)?>',
|
41 |
+
profile:'<?php echo $this->getConfig()->getProfile()?>',
|
42 |
+
}});
|
43 |
+
}
|
44 |
+
);
|
45 |
+
</script>
|
lib/Magmi/plugins/base/datasources/genericsql/other_options.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div id="other_config">
|
2 |
+
<ul class="formline">
|
3 |
+
<li class="label">Input DB User</li>
|
4 |
+
<li class="value"><input type="text" name="SQL:dbuser" value="<?echo $this->getParam("SQL:dbuser","")?>"/></li>
|
5 |
+
</ul>
|
6 |
+
<ul class="formline">
|
7 |
+
<li class="label">Input DB Password</li>
|
8 |
+
<li class="value"><input type="password" name="SQL:dbpass" value="<?echo $this->getParam("SQL:dbpass","")?>"/></li>
|
9 |
+
</ul>
|
10 |
+
<ul class="formline">
|
11 |
+
<li class="label">PDO Connection String</li>
|
12 |
+
<li class="value"><input type="text" size="80" name="SQL:pdostr" value="<?echo $this->getParam("SQL:pdostr","")?>"/>
|
13 |
+
<div class="fieldinfo">you must have correct PDO driver installed & also know PDO connection string syntax</div></li>
|
14 |
+
</ul>
|
15 |
+
</div>
|
lib/Magmi/plugins/base/datasources/genericsql/sql_datasource.php
ADDED
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("dbhelper.class.php");
|
3 |
+
|
4 |
+
class ExtDBHelper extends DBHelper
|
5 |
+
{
|
6 |
+
public function initDBMysql($dbname,$host,$user,$pass)
|
7 |
+
{
|
8 |
+
|
9 |
+
$this->_db=new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass);
|
10 |
+
}
|
11 |
+
|
12 |
+
public function initDBPDOStr($user,$pass,$pdostr)
|
13 |
+
{
|
14 |
+
//fix by Mr Lei for UTF8 special chars
|
15 |
+
$this->_db=new PDO("$pdostr", $user, $pass);
|
16 |
+
}
|
17 |
+
|
18 |
+
}
|
19 |
+
class SQL_Datasource extends Magmi_Datasource
|
20 |
+
{
|
21 |
+
public $dbh;
|
22 |
+
public $stmt;
|
23 |
+
public $extractsql;
|
24 |
+
public $sqlfile;
|
25 |
+
|
26 |
+
public function initialize($params)
|
27 |
+
{
|
28 |
+
$this->dbh=new ExtDBHelper();
|
29 |
+
$cdbtype=$this->getParam("SQL:dbtype");
|
30 |
+
$cdbusr=$this->getParam("SQL:dbuser");
|
31 |
+
$cdbpass=$this->getParam("SQL:dbpass");
|
32 |
+
if($cdbtype=="other")
|
33 |
+
{
|
34 |
+
$cdbpdostr=$this->getParam("SQL:pdostr","");
|
35 |
+
|
36 |
+
$this->dbh->initDBPDOStr($cdbuser,$cdbpass,$cdbpdostr);
|
37 |
+
}
|
38 |
+
else
|
39 |
+
{
|
40 |
+
$cdbname=$this->getParam("SQL:dbname");
|
41 |
+
$cdbhost=$this->getParam("SQL:dbhost");
|
42 |
+
$extra=$this->getParam("SQL:dbextra");
|
43 |
+
$this->dbh->initDbMysql($cdbname,$cdbhost,$cdbusr, $cdbpass);
|
44 |
+
|
45 |
+
}
|
46 |
+
//handle extra initial commands
|
47 |
+
if(isset($extra) && $extra!="")
|
48 |
+
{
|
49 |
+
foreach(explode(";\n",$extra) as $st)
|
50 |
+
{
|
51 |
+
if($st!="")
|
52 |
+
{
|
53 |
+
$this->dbh->exec_stmt($st);
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
$this->stmt=null;
|
58 |
+
$this->sqlfile=$this->getParam("SQL:queryfile");
|
59 |
+
$this->extractsql=file_get_contents($this->sqlfile);
|
60 |
+
}
|
61 |
+
|
62 |
+
public function getPluginInfo()
|
63 |
+
{
|
64 |
+
return array("name"=>"Generic SQL Datasource",
|
65 |
+
"author"=>"Dweeves",
|
66 |
+
"version"=>"1.0.2");
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getPluginParamNames()
|
70 |
+
{
|
71 |
+
return array("SQL:dbtype","SQL:dbname","SQL:dbhost","SQL:dbuser","SQL:dbpass","SQL:dbextra","SQL:queryfile","SQL:pdostr");
|
72 |
+
}
|
73 |
+
|
74 |
+
public function startImport()
|
75 |
+
{
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
|
80 |
+
public function getSQLFileList()
|
81 |
+
{
|
82 |
+
$files=glob(dirname(__file__)."/requests/*.sql");
|
83 |
+
return $files;
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
public function getRecordsCount()
|
88 |
+
{
|
89 |
+
$sql=null;
|
90 |
+
//optimized count query
|
91 |
+
if(file_exists($this->sqlfile.".count"))
|
92 |
+
{
|
93 |
+
$sql=file_get_contents($this->sqlfile.".count");
|
94 |
+
}
|
95 |
+
if(!isset($sql))
|
96 |
+
{
|
97 |
+
$sql="SELECT COUNT(*) as cnt FROM (".str_replace("\n"," ",$this->extractsql).") as t1";
|
98 |
+
}
|
99 |
+
$cnt=$this->dbh->selectone($sql,null,"cnt");
|
100 |
+
|
101 |
+
return $cnt;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function getColumnNames($prescan=false)
|
105 |
+
{
|
106 |
+
$s=$this->dbh->select($this->extractsql);
|
107 |
+
$test=$s->fetch();
|
108 |
+
$s->closeCursor();
|
109 |
+
unset($s);
|
110 |
+
$cl=array_keys($test);
|
111 |
+
return $cl;
|
112 |
+
}
|
113 |
+
|
114 |
+
|
115 |
+
|
116 |
+
public function getNextRecord()
|
117 |
+
{
|
118 |
+
if(!isset($this->stmt))
|
119 |
+
{
|
120 |
+
$this->stmt=$this->dbh->select($this->extractsql);
|
121 |
+
}
|
122 |
+
$data=$this->stmt->fetch();
|
123 |
+
if(!$data)
|
124 |
+
{
|
125 |
+
return false;
|
126 |
+
}
|
127 |
+
return $data;
|
128 |
+
}
|
129 |
+
|
130 |
+
public function endImport()
|
131 |
+
{
|
132 |
+
|
133 |
+
}
|
134 |
+
public function afterImport()
|
135 |
+
{
|
136 |
+
|
137 |
+
}
|
138 |
+
}
|
lib/Magmi/plugins/base/general/emailreport/emailreport.php
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class EmailReportPlugin extends Magmi_GeneralImportPlugin
|
3 |
+
{
|
4 |
+
protected $_attach;
|
5 |
+
|
6 |
+
public function initialize($params)
|
7 |
+
{
|
8 |
+
$this->_attach=array();
|
9 |
+
}
|
10 |
+
|
11 |
+
public function getPluginInfo()
|
12 |
+
{
|
13 |
+
return array(
|
14 |
+
"name" => "Import Report Mail Notifier",
|
15 |
+
"author" => "Dweeves",
|
16 |
+
"version" => "1.0.0",
|
17 |
+
"url"=>$this->pluginDocUrl("Import_report_mail_notifier")
|
18 |
+
);
|
19 |
+
}
|
20 |
+
public function send_email($to, $from, $from_name, $subject, $message, $attachments=false)
|
21 |
+
{
|
22 |
+
$headers = "From: ".$from_name."<".$from.">\n";
|
23 |
+
$headers .= "Reply-To: ".$from_name."<".$from.">\n";
|
24 |
+
$headers .= "Return-Path: ".$from_name."<".$from.">\n";
|
25 |
+
$headers .= "Message-ID: <".time()."-".$from.">\n";
|
26 |
+
$headers .= "X-Mailer: PHP v".phpversion();
|
27 |
+
|
28 |
+
$msg_txt="";
|
29 |
+
$email_txt = $message;
|
30 |
+
|
31 |
+
$semi_rand = md5(time());
|
32 |
+
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
|
33 |
+
|
34 |
+
$headers .= "\nMIME-Version: 1.0\n" .
|
35 |
+
"Content-Type: multipart/mixed;\n" .
|
36 |
+
" boundary=\"{$mime_boundary}\"";
|
37 |
+
|
38 |
+
$email_txt .= $msg_txt;
|
39 |
+
$email_message = $email_txt;
|
40 |
+
$email_message .= "This is a multi-part message in MIME format.\n\n" .
|
41 |
+
"--{$mime_boundary}\n" .
|
42 |
+
"Content-Type:text/html; charset=\"iso-8859-1\"\n" .
|
43 |
+
"Content-Transfer-Encoding: 7bit\n\n" .
|
44 |
+
$email_txt . "\n\n";
|
45 |
+
|
46 |
+
$attachments=$this->_attach;
|
47 |
+
if ($attachments !== false)
|
48 |
+
{
|
49 |
+
for($i=0; $i < count($attachments); $i++)
|
50 |
+
{
|
51 |
+
if (is_file($attachments[$i]))
|
52 |
+
{
|
53 |
+
$fileatt = $attachments[$i];
|
54 |
+
$fileatt_type = "application/octet-stream";
|
55 |
+
$start= strrpos($attachments[$i], '/') == -1 ? strrpos($attachments[$i], '//') : strrpos($attachments[$i], '/')+1;
|
56 |
+
$fileatt_name = substr($attachments[$i], $start, strlen($attachments[$i]));
|
57 |
+
|
58 |
+
$file = fopen($fileatt,'rb');
|
59 |
+
$data = fread($file,filesize($fileatt));
|
60 |
+
fclose($file);
|
61 |
+
|
62 |
+
$data = chunk_split(base64_encode($data));
|
63 |
+
|
64 |
+
$email_message .= "--{$mime_boundary}\n" .
|
65 |
+
"Content-Type: {$fileatt_type};\n" .
|
66 |
+
" name=\"{$fileatt_name}\"\n" .
|
67 |
+
"Content-Transfer-Encoding: base64\n\n" .
|
68 |
+
$data . "\n\n";
|
69 |
+
|
70 |
+
}
|
71 |
+
}
|
72 |
+
}
|
73 |
+
|
74 |
+
$email_message .= "--{$mime_boundary}--\n";
|
75 |
+
$this->log("Sending report to : $to","info");
|
76 |
+
$ok= mail($to, $subject, $email_message, $headers);
|
77 |
+
return $ok;
|
78 |
+
}
|
79 |
+
|
80 |
+
public function addAttachment($fname)
|
81 |
+
{
|
82 |
+
$this->_attach[]=$fname;
|
83 |
+
$this->_attach=array_unique($this->_attach);
|
84 |
+
}
|
85 |
+
|
86 |
+
public function getPluginParams($params)
|
87 |
+
{
|
88 |
+
$pp=array();
|
89 |
+
foreach($params as $k=>$v)
|
90 |
+
{
|
91 |
+
if(preg_match("/^EMAILREP:.*$/",$k))
|
92 |
+
{
|
93 |
+
$pp[$k]=$v;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
return $pp;
|
97 |
+
}
|
98 |
+
|
99 |
+
public function afterImport()
|
100 |
+
{
|
101 |
+
$eng=$this->_callers[0];
|
102 |
+
if($this->getParam("EMAILREP:to","")!="" && $this->getParam("EMAILREP:from","")!="")
|
103 |
+
{
|
104 |
+
if($this->getParam("EMAILREP:attachcsv",false)==true)
|
105 |
+
{
|
106 |
+
$ds=$eng->getPluginInstanceByClassName("datasources","Magmi_CSVDataSource");
|
107 |
+
if($ds!=null)
|
108 |
+
{
|
109 |
+
$csvfile=$ds->getParam("CSV:filename");
|
110 |
+
$this->addAttachment($csvfile);
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
if($this->getParam("EMAILREP:attachlog",false)==true)
|
115 |
+
{
|
116 |
+
//copy magmi report
|
117 |
+
$pfile=Magmi_StateManager::getProgressFile(true);
|
118 |
+
$this->addAttachment($pfile);
|
119 |
+
}
|
120 |
+
|
121 |
+
$ok=$this->send_email($this->getParam("EMAILREP:to"),
|
122 |
+
$this->getParam("EMAILREP:from"),
|
123 |
+
$this->getParam("EMAILREP:from_alias",""),
|
124 |
+
$this->getParam("EMAILREP:subject","Magmi import report"),
|
125 |
+
$this->getParam("EMAILREP:body","report attached"),$this->_attach);
|
126 |
+
if(!$ok)
|
127 |
+
{
|
128 |
+
$this->log("Cannot send email","error");
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
}
|
lib/Magmi/plugins/base/general/emailreport/options_panel.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
<p>This plugin can be used to send a email report for the import</p>
|
3 |
+
<p>it uses PHP <b>mail</b> feature, <b>please ensure your setup is compatible with this</b></p>
|
4 |
+
</div>
|
5 |
+
<ul class="formline">
|
6 |
+
<li class="label">Email report to:</li>
|
7 |
+
<li class="value"><input type="text" style="width:400px" name="EMAILREP:to" value="<?php echo $this->getParam("EMAILREP:to","")?>"><div class="fieldinfo">You can set several receiver emails separated by a comma (,)</div></li>
|
8 |
+
</ul>
|
9 |
+
<ul class="formline">
|
10 |
+
<li class="label">Report sender:</li>
|
11 |
+
<li class="value"><input type="text" name="EMAILREP:from" value="<?php echo $this->getParam("EMAILREP:from","magmi@sourceforge.net")?>"></li>
|
12 |
+
</ul>
|
13 |
+
<ul class="formline">
|
14 |
+
<li class="label">Report sender alias:</li>
|
15 |
+
<li class="value"><input type="text" name="EMAILREP:from_alias" value="<?php echo $this->getParam("EMAILREP:from_alias","Magmi Importer")?>"></li>
|
16 |
+
</ul>
|
17 |
+
<ul class="formline">
|
18 |
+
<li class="label">Subject:</li>
|
19 |
+
<li class="value"><input type="text" name="EMAILREP:subject" value="<?php echo $this->getParam("EMAILREP:subject","Magmi import report")?>"></li>
|
20 |
+
</ul>
|
21 |
+
<ul class="formline">
|
22 |
+
<li class="label">Body:</li>
|
23 |
+
<li class="value"><textarea name="EMAILREP:body"><?php echo $this->getParam("EMAILREP:body","report attached");?></textarea></li>
|
24 |
+
</ul>
|
25 |
+
<ul class="formline">
|
26 |
+
<li class="label">Attachments</li>
|
27 |
+
<li class="value"><input type="checkbox" name="EMAILREP:attachlog" <?php if($this->getParam("EMAILREP:attachlog")==true){?>checked="checked"<?php }?>>Attach import log</li>
|
28 |
+
<li class="value"><input type="checkbox" name="EMAILREP:attachcsv" <?php if($this->getParam("EMAILREP:attachcsv")==true){?>checked="checked"<?php }?>>Attach source CSV</li>
|
29 |
+
</ul>
|
lib/Magmi/plugins/base/general/importurl/importurl_plugin.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_ImportUrlPlugin extends Magmi_GeneralImportPlugin
|
3 |
+
{
|
4 |
+
public function getPluginInfo()
|
5 |
+
{
|
6 |
+
return array("name"=>"Magmi Import Url UI",
|
7 |
+
"author"=>"Dweeves",
|
8 |
+
"version"=>"1.0.3",
|
9 |
+
"url"=>$this->pluginDocUrl("Magmi_Import_Url_UI"));
|
10 |
+
}
|
11 |
+
public function initialize($params)
|
12 |
+
{
|
13 |
+
|
14 |
+
}
|
15 |
+
}
|
lib/Magmi/plugins/base/general/importurl/options_panel.php
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin provides a textarea that gives the wget or curl command line (or just url if you want) that will run magmi with
|
3 |
+
current settings.
|
4 |
+
<p>this area is refreshed each time you leave any field of this import config page.</p>
|
5 |
+
</div>
|
6 |
+
<select id="GETURL:mode">
|
7 |
+
<option value="wget">wget</option>
|
8 |
+
<option value="wget_auth">wget (authentified)</option>
|
9 |
+
<option value="curl">curl</option>
|
10 |
+
<option value="curl_auth">curl (authentified)</option>
|
11 |
+
<option value="rawurl">just url</option>
|
12 |
+
<option value="cli">magmi cli</option>
|
13 |
+
</select>
|
14 |
+
|
15 |
+
<div id="GETURL:urlcontainer">
|
16 |
+
<textarea id="GETURL:url" cols="100" rows="5"></textarea>
|
17 |
+
</div>
|
18 |
+
<div class="fieldinfo">
|
19 |
+
</div>
|
20 |
+
<script type="text/javascript">
|
21 |
+
|
22 |
+
magmi_getimporturl=function()
|
23 |
+
{
|
24 |
+
var mode=$('GETURL:mode').value;
|
25 |
+
var old_action=$('runmagmi').action;
|
26 |
+
$('runmagmi').action="./magmi_run.php";
|
27 |
+
var url=$('runmagmi').action+'?'+Form.serializeElements([$('mode'),$('runprofile')])+'&engine=magmi_productimportengine:Magmi_ProductImportEngine';
|
28 |
+
$('runmagmi').action=old_action;
|
29 |
+
var content="";
|
30 |
+
switch(mode)
|
31 |
+
{
|
32 |
+
case "wget_auth":
|
33 |
+
url=url.replace("://","://your_username:your_pass@");
|
34 |
+
case "wget":
|
35 |
+
content='wget "'+url+'" -O /dev/null';
|
36 |
+
break;
|
37 |
+
case "curl_auth":
|
38 |
+
url=url.replace("://","://your_username:your_pass@");
|
39 |
+
case "curl":
|
40 |
+
content='curl -o /dev/null "'+url+'"';
|
41 |
+
break;
|
42 |
+
case "rawurl":
|
43 |
+
content=url;
|
44 |
+
break;
|
45 |
+
case "cli":
|
46 |
+
content='magmi.cli.php -mode='+$F('mode')+' -profile='+$F('runprofile');
|
47 |
+
break;
|
48 |
+
default:
|
49 |
+
content=url;
|
50 |
+
}
|
51 |
+
$('GETURL:url').update(content);
|
52 |
+
}
|
53 |
+
|
54 |
+
|
55 |
+
$('runmagmi').getElements().each(function(it){
|
56 |
+
it.observe('blur',magmi_getimporturl);
|
57 |
+
});
|
58 |
+
$('GETURL:mode').observe('change',magmi_getimporturl);
|
59 |
+
magmi_getimporturl();
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
</script>
|
lib/Magmi/plugins/base/general/optimizer/magmi_optimizer_plugin.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_OptimizerPlugin extends Magmi_GeneralImportPlugin
|
3 |
+
{
|
4 |
+
public function getPluginInfo()
|
5 |
+
{
|
6 |
+
return array("name"=>"Magmi Optimizer",
|
7 |
+
"author"=>"Dweeves",
|
8 |
+
"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 |
+
|
38 |
+
public function initialize($params)
|
39 |
+
{
|
40 |
+
|
41 |
+
}
|
42 |
+
}
|
lib/Magmi/plugins/base/general/reindex/magmi_reindexing_plugin.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_ReindexingPlugin extends Magmi_GeneralImportPlugin
|
3 |
+
{
|
4 |
+
protected $_reindex;
|
5 |
+
protected $_indexlist="catalog_product_attribute,catalog_product_price,catalog_product_flat,catalog_category_flat,catalog_category_product,cataloginventory_stock,catalog_url,catalogsearch_fulltext";
|
6 |
+
protected $_mdh;
|
7 |
+
|
8 |
+
public function getPluginInfo()
|
9 |
+
{
|
10 |
+
return array("name"=>"Magmi Magento Reindexer",
|
11 |
+
"author"=>"Dweeves",
|
12 |
+
"version"=>"1.0.2",
|
13 |
+
"url"=>$this->pluginDocUrl("Magmi_Magento_Reindexer"));
|
14 |
+
}
|
15 |
+
|
16 |
+
public function afterImport()
|
17 |
+
{
|
18 |
+
$this->fixFlat();
|
19 |
+
$this->log("running indexer","info");
|
20 |
+
$this->updateIndexes();
|
21 |
+
return true;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function OptimEav()
|
25 |
+
{
|
26 |
+
$tables=array("catalog_product_entity_varchar",
|
27 |
+
"catalog_product_entity_int",
|
28 |
+
"catalog_product_entity_text",
|
29 |
+
"catalog_product_entity_decimal",
|
30 |
+
"catalog_product_entity_datetime",
|
31 |
+
"catalog_product_entity_media_gallery",
|
32 |
+
"catalog_product_entity_tier_price");
|
33 |
+
|
34 |
+
$cpe=$this->tablename('catalog_product_entity');
|
35 |
+
$this->log("Optmizing EAV Tables...","info");
|
36 |
+
foreach($tables as $t)
|
37 |
+
{
|
38 |
+
$this->log("Optmizing $t....","info");
|
39 |
+
$sql="DELETE ta.* FROM ".$this->tablename($t)." as ta
|
40 |
+
LEFT JOIN $cpe as cpe on cpe.entity_id=ta.entity_id
|
41 |
+
WHERE ta.store_id=0 AND cpe.entity_id IS NULL";
|
42 |
+
$this->delete($sql);
|
43 |
+
$this->log("$t optimized","info");
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
public function fixFlat()
|
48 |
+
{
|
49 |
+
$this->log("Cleaning flat tables before reindex...","info");
|
50 |
+
$stmt=$this->exec_stmt("SHOW TABLES LIKE '".$this->tablename('catalog_product_flat')."%'",NULL,false);
|
51 |
+
while($row=$stmt->fetch(PDO::FETCH_NUM))
|
52 |
+
{
|
53 |
+
$tname=$row[0];
|
54 |
+
//removing records in flat tables that are no more linked to entries in catalog_product_entity table
|
55 |
+
//for some reasons, this seem to happen
|
56 |
+
$sql="DELETE cpf.* FROM $tname as cpf
|
57 |
+
LEFT JOIN ".$this->tablename('catalog_product_entity')." as cpe ON cpe.entity_id=cpf.entity_id
|
58 |
+
WHERE cpe.entity_id IS NULL";
|
59 |
+
$this->delete($sql);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
public function getPluginParamNames()
|
63 |
+
{
|
64 |
+
return array("REINDEX:indexes","REINDEX:phpcli");
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getIndexList()
|
68 |
+
{
|
69 |
+
return $this->_indexlist;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function updateIndexes()
|
73 |
+
{
|
74 |
+
//make sure we are not in session
|
75 |
+
if(session_id()!=="")
|
76 |
+
{
|
77 |
+
session_write_close();
|
78 |
+
}
|
79 |
+
$cl=$this->getParam("REINDEX:phpcli")." shell/indexer.php";
|
80 |
+
$idxlstr=$this->getParam("REINDEX:indexes","");
|
81 |
+
$idxlist=explode(",",$idxlstr);
|
82 |
+
if(count($idxlist)==0)
|
83 |
+
{
|
84 |
+
$this->log("No indexes selected , skipping reindexing...","warning");
|
85 |
+
return true;
|
86 |
+
}
|
87 |
+
foreach($idxlist as $idx)
|
88 |
+
{
|
89 |
+
$tstart=microtime(true);
|
90 |
+
$this->log("Reindexing $idx....","info");
|
91 |
+
|
92 |
+
// Execute Reindex command, and specify that it should be ran from Magento directory
|
93 |
+
$out = $this->_mdh->exec_cmd($cl,"--reindex $idx", $this->_mdh->getMagentoDir());
|
94 |
+
$this->log($out,"info");
|
95 |
+
$tend=microtime(true);
|
96 |
+
$this->log("done in ".round($tend-$tstart,2). " secs","info");
|
97 |
+
if(Magmi_StateManager::getState()=="canceled")
|
98 |
+
{
|
99 |
+
exit();
|
100 |
+
}
|
101 |
+
flush();
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
public function isRunnable()
|
107 |
+
{
|
108 |
+
return array(true,"");
|
109 |
+
}
|
110 |
+
|
111 |
+
public function initialize($params)
|
112 |
+
{
|
113 |
+
$magdir=Magmi_Config::getInstance()->getMagentoDir();
|
114 |
+
$this->_mdh=MagentoDirHandlerFactory::getInstance()->getHandler($magdir);
|
115 |
+
|
116 |
+
}
|
117 |
+
}
|
lib/Magmi/plugins/base/general/reindex/options_panel.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="plugin_description">
|
3 |
+
This plugin calls magento reindex script via calling php cli. please ensure security configuration enable "shell_exec()" calls from php
|
4 |
+
</div>
|
5 |
+
|
6 |
+
<div class="formline">
|
7 |
+
<span class="label">PHP CLI command</span>
|
8 |
+
<span class="value"><input type="text" name="REINDEX:phpcli" value="<?php echo $this->getParam("REINDEX:phpcli","php")?>"></input></span>
|
9 |
+
</div>
|
10 |
+
<hr/>
|
11 |
+
<input type="hidden" name="REINDEX:indexes" id="indexes" value="<?php echo $this->getParam("REINDEX:indexes")?>"></input>
|
12 |
+
<div>
|
13 |
+
<a name="REINDEX:config"></a>
|
14 |
+
<span>Indexing:</span><a href="#REINDEX:config" onclick="fcheck(1);">All</a> <a href="#REINDEX:config" onclick="fcheck(0)">None</a>
|
15 |
+
<ul>
|
16 |
+
<?php
|
17 |
+
$idxarr=explode(",",$this->_plugin->getIndexList());
|
18 |
+
$indexes=explode(",",$this->getParam("REINDEX:indexes"));
|
19 |
+
foreach($idxarr as $indexname)
|
20 |
+
{
|
21 |
+
?>
|
22 |
+
<li><input type="checkbox" name="<?php echo $indexname?>" class="_magindex" <?php if(in_array($indexname,$indexes)){?>checked=checked<?php }?>><?php echo $indexname?></li>
|
23 |
+
<?php }?>
|
24 |
+
</ul>
|
25 |
+
</div>
|
26 |
+
<script type="text/javascript">
|
27 |
+
getIndexes=function()
|
28 |
+
{
|
29 |
+
var outs=[];
|
30 |
+
$$('._magindex').each(function(it){if(it.checked){outs.push(it.name)}});
|
31 |
+
return outs.join(",");
|
32 |
+
};
|
33 |
+
|
34 |
+
|
35 |
+
|
36 |
+
fcheck=function(t)
|
37 |
+
{
|
38 |
+
$$('._magindex').each(function(it){it.checked=t});
|
39 |
+
updateIndexes();
|
40 |
+
|
41 |
+
}
|
42 |
+
|
43 |
+
updateIndexes=function()
|
44 |
+
{
|
45 |
+
$('indexes').value=getIndexes();
|
46 |
+
}
|
47 |
+
|
48 |
+
$$('._magindex').each(function(it){it.observe('click',updateIndexes)});
|
49 |
+
</script>
|
lib/Magmi/plugins/base/itemprocessors/columnmapper/000_columnmapper.php
ADDED
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class SampleItemProcessor
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
* This class is a sample for item processing
|
7 |
+
*/
|
8 |
+
class ColumnMappingItemProcessor extends Magmi_ItemProcessor
|
9 |
+
{
|
10 |
+
|
11 |
+
protected $_dcols=array();
|
12 |
+
|
13 |
+
public function getPluginInfo()
|
14 |
+
{
|
15 |
+
return array(
|
16 |
+
"name" => "Column mapper",
|
17 |
+
"author" => "Dweeves",
|
18 |
+
"version" => "0.0.3",
|
19 |
+
"url"=>$this->pluginDocUrl("Column_mapper")
|
20 |
+
);
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
25 |
+
* @param Magmi_Engine $mmi : reference to magmi engine(convenient to perform database operations)
|
26 |
+
* @param unknown_type $item : 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 |
+
|
33 |
+
public function processColumnList(&$cols,$params=null)
|
34 |
+
{
|
35 |
+
$icols=$cols;
|
36 |
+
$ocols=array();
|
37 |
+
$scols=array();
|
38 |
+
foreach($icols as $cname)
|
39 |
+
{
|
40 |
+
|
41 |
+
if(isset($this->_dcols[$cname]))
|
42 |
+
{
|
43 |
+
$mlist=array_unique(explode(",",$this->_dcols[$cname]));
|
44 |
+
$ncol=array_shift($mlist);
|
45 |
+
$ocols[]=$ncol;
|
46 |
+
if($ncol!=$cname)
|
47 |
+
{
|
48 |
+
$this->log("Replacing Column $cname by $ncol","startup");
|
49 |
+
}
|
50 |
+
if(count($mlist)>0)
|
51 |
+
{
|
52 |
+
$scols=array_merge($scols,$mlist);
|
53 |
+
$this->log("Replicating Column $cname to ".implode(",",$mlist),"startup");
|
54 |
+
}
|
55 |
+
}
|
56 |
+
else
|
57 |
+
{
|
58 |
+
$ocols[]=$cname;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
$ocols=array_unique(array_merge($ocols,$scols));
|
62 |
+
$cols=$ocols;
|
63 |
+
return true;
|
64 |
+
}
|
65 |
+
|
66 |
+
public function processItemBeforeId(&$item,$params=null)
|
67 |
+
{
|
68 |
+
foreach($this->_dcols as $oname=>$mnames)
|
69 |
+
{
|
70 |
+
if(isset($item[$oname]))
|
71 |
+
{
|
72 |
+
$mapped=explode(",",$mnames);
|
73 |
+
foreach($mapped as $mname)
|
74 |
+
{
|
75 |
+
$item[$mname]=$item[$oname];
|
76 |
+
}
|
77 |
+
if(!in_array($oname,$mapped))
|
78 |
+
{
|
79 |
+
unset($item[$oname]);
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
return true;
|
84 |
+
}
|
85 |
+
|
86 |
+
public function initialize($params)
|
87 |
+
{
|
88 |
+
foreach($params as $k=>$v)
|
89 |
+
{
|
90 |
+
if(preg_match_all("/^CMAP:(.*)$/",$k,$m) && $k!="CMAP:columnlist")
|
91 |
+
{
|
92 |
+
$colname=rawurldecode($m[1][0]);
|
93 |
+
$this->_dcols[$colname]=$params[$k];
|
94 |
+
}
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getPluginParams($params)
|
99 |
+
{
|
100 |
+
$pp=array();
|
101 |
+
foreach($params as $k=>$v)
|
102 |
+
{
|
103 |
+
if(preg_match("/^CMAP:.*$/",$k))
|
104 |
+
{
|
105 |
+
$pp[$k]=$v;
|
106 |
+
}
|
107 |
+
}
|
108 |
+
return $pp;
|
109 |
+
}
|
110 |
+
|
111 |
+
static public function getCategory()
|
112 |
+
{
|
113 |
+
return "Input Data Preprocessing";
|
114 |
+
}
|
115 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/columnmapper/options_panel.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin enables to change column names from datasource before they are handled by magmi.
|
3 |
+
enter columns to set new name for in mapped column list field, separated by commas (,)
|
4 |
+
when leaving the field, new fields will be inserted for filling new column names.
|
5 |
+
<b>You can put several values (comma separated) in the mapped column names,doing so , the column mapper will replicate
|
6 |
+
values of column to map to all mapped columns !!!</b>
|
7 |
+
</div>
|
8 |
+
<?php $clist=$this->fixListParam($this->getParam("CMAP:columnlist"))?>
|
9 |
+
<div>
|
10 |
+
<ul class="formline">
|
11 |
+
<li class="label">Mapped columns list</li>
|
12 |
+
<li class="value"><input type="text" id="CMAP:columnlist" name="CMAP:columnlist" size="80" value="<?php echo $clist?>" onblur="cmap_mf.buildparamlist()"></input></li>
|
13 |
+
</ul>
|
14 |
+
<div id="CMAP:columnsetup">
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
<script type="text/javascript">
|
18 |
+
var cm_vals=<?php echo tdarray_to_js($this,'CMAP:columnlist','CMAP')?>;
|
19 |
+
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>';
|
20 |
+
cmap_mf=new magmi_multifield('CMAP:columnlist','CMAP:columnsetup',cm_linetpl,cm_vals);
|
21 |
+
cmap_mf.buildparamlist();
|
22 |
+
</script>
|
lib/Magmi/plugins/base/itemprocessors/configurables/magmi_configurableprocessor.php
ADDED
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_ConfigurableItemProcessor extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
|
5 |
+
|
6 |
+
private $_configurable_attrs=array();
|
7 |
+
private $_use_defaultopc=false;
|
8 |
+
private $_optpriceinfo=array();
|
9 |
+
private $_currentsimples=array();
|
10 |
+
|
11 |
+
public function initialize($params)
|
12 |
+
{
|
13 |
+
|
14 |
+
}
|
15 |
+
|
16 |
+
public function getPluginInfo()
|
17 |
+
{
|
18 |
+
return array(
|
19 |
+
"name" => "Configurable Item processor",
|
20 |
+
"author" => "Dweeves",
|
21 |
+
"version" => "1.3.7",
|
22 |
+
"url"=> $this->pluginDocUrl("Configurable_Item_processor")
|
23 |
+
);
|
24 |
+
}
|
25 |
+
|
26 |
+
public function getConfigurableOptsFromAsId($asid)
|
27 |
+
{
|
28 |
+
if(!isset($this->_configurable_attrs[$asid]))
|
29 |
+
{
|
30 |
+
$ea=$this->tablename("eav_attribute");
|
31 |
+
$eea=$this->tablename("eav_entity_attribute");
|
32 |
+
$eas=$this->tablename("eav_attribute_set");
|
33 |
+
$eet=$this->tablename("eav_entity_type");
|
34 |
+
|
35 |
+
$sql="SELECT ea.attribute_code FROM `$ea` as ea
|
36 |
+
JOIN $eet as eet ON eet.entity_type_id=ea.entity_type_id AND eet.entity_type_id=?
|
37 |
+
JOIN $eas as eas ON eas.entity_type_id=eet.entity_type_id AND eas.attribute_set_id=?
|
38 |
+
JOIN $eea as eea ON eea.attribute_id=ea.attribute_id";
|
39 |
+
$cond="ea.is_user_defined=1";
|
40 |
+
if($this->getMagentoVersion()!="1.3.x")
|
41 |
+
{
|
42 |
+
$cea=$this->tablename("catalog_eav_attribute");
|
43 |
+
$sql.=" JOIN $cea as cea ON cea.attribute_id=ea.attribute_id AND cea.is_global=1 AND cea.is_configurable=1";
|
44 |
+
}
|
45 |
+
else
|
46 |
+
{
|
47 |
+
$cond.=" AND ea.is_global=1 AND ea.is_configurable=1";
|
48 |
+
}
|
49 |
+
$sql.=" WHERE $cond
|
50 |
+
GROUP by ea.attribute_id";
|
51 |
+
|
52 |
+
$result=$this->selectAll($sql,array($this->getProductEntityType(),$asid));
|
53 |
+
foreach($result as $r)
|
54 |
+
{
|
55 |
+
$this->_configurable_attrs[$asid][]=$r["attribute_code"];
|
56 |
+
}
|
57 |
+
}
|
58 |
+
return $this->_configurable_attrs[$asid];
|
59 |
+
}
|
60 |
+
|
61 |
+
|
62 |
+
public function dolink($pid,$cond,$conddata=array())
|
63 |
+
{
|
64 |
+
$cpsl=$this->tablename("catalog_product_super_link");
|
65 |
+
$cpr=$this->tablename("catalog_product_relation");
|
66 |
+
$cpe=$this->tablename("catalog_product_entity");
|
67 |
+
$sql="DELETE cpsl.*,cpsr.* FROM $cpsl as cpsl
|
68 |
+
JOIN $cpr as cpsr ON cpsr.parent_id=cpsl.parent_id
|
69 |
+
WHERE cpsl.parent_id=?";
|
70 |
+
$this->delete($sql,array($pid));
|
71 |
+
//recreate associations
|
72 |
+
$sql="INSERT INTO $cpsl (`parent_id`,`product_id`) SELECT cpec.entity_id as parent_id,cpes.entity_id as product_id
|
73 |
+
FROM $cpe as cpec
|
74 |
+
JOIN $cpe as cpes ON cpes.type_id IN ('simple','virtual') AND cpes.sku $cond
|
75 |
+
WHERE cpec.entity_id=?";
|
76 |
+
$this->insert($sql,array_merge($conddata,array($pid)));
|
77 |
+
$sql="INSERT INTO $cpr (`parent_id`,`child_id`) SELECT cpec.entity_id as parent_id,cpes.entity_id as child_id
|
78 |
+
FROM $cpe as cpec
|
79 |
+
JOIN $cpe as cpes ON cpes.type_id IN ('simple','virtual') AND cpes.sku $cond
|
80 |
+
WHERE cpec.entity_id=?";
|
81 |
+
$this->insert($sql,array_merge($conddata,array($pid)));
|
82 |
+
unset($conddata);
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
public function autoLink($pid)
|
87 |
+
{
|
88 |
+
$this->dolink($pid,"LIKE CONCAT(cpec.sku,'%')");
|
89 |
+
}
|
90 |
+
|
91 |
+
public function updSimpleVisibility($pid)
|
92 |
+
{
|
93 |
+
$vis=$this->getParam("CFGR:updsimplevis",0);
|
94 |
+
if($vis!=0)
|
95 |
+
{
|
96 |
+
$attinfo=$this->getAttrInfo("visibility");
|
97 |
+
$sql="UPDATE ".$this->tablename("catalog_product_entity_int")." as cpei
|
98 |
+
JOIN ".$this->tablename("catalog_product_super_link"). " as cpsl ON cpsl.parent_id=?
|
99 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe ON cpe.entity_id=cpsl.product_id
|
100 |
+
SET cpei.value=?
|
101 |
+
WHERE cpei.entity_id=cpe.entity_id AND attribute_id=?";
|
102 |
+
$this->update($sql,array($pid,$vis,$attinfo["attribute_id"]));
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
public function fixedLink($pid,$skulist)
|
107 |
+
{
|
108 |
+
$this->dolink($pid,"IN (".$this->arr2values($skulist).")",$skulist);
|
109 |
+
}
|
110 |
+
|
111 |
+
public function buildSAPTable($sapdesc)
|
112 |
+
{
|
113 |
+
$saptable=array();
|
114 |
+
$sapentries=explode(",",$sapdesc);
|
115 |
+
foreach($sapentries as $sapentry)
|
116 |
+
{
|
117 |
+
$sapinf=explode("::",$sapentry);
|
118 |
+
$sapname=$sapinf[0];
|
119 |
+
$sapdata=$sapinf[1];
|
120 |
+
$sapdarr=explode(";",$sapdata);
|
121 |
+
$saptable[$sapname]=$sapdarr;
|
122 |
+
unset($sapdarr);
|
123 |
+
}
|
124 |
+
unset($sapentries);
|
125 |
+
return $saptable;
|
126 |
+
}
|
127 |
+
public function processItemBeforeId(&$item,$params=null)
|
128 |
+
{
|
129 |
+
//if item is not configurable, nothing to do
|
130 |
+
if($item["type"]!=="configurable")
|
131 |
+
{
|
132 |
+
return true;
|
133 |
+
}
|
134 |
+
if($this->_use_defaultopc || ($item["options_container"]!="container1" && $item["options_container"]!="container2"))
|
135 |
+
{
|
136 |
+
$item["options_container"]="container2";
|
137 |
+
}
|
138 |
+
//reset option price info
|
139 |
+
$this->_optpriceinfo=array();
|
140 |
+
if(isset($item["super_attribute_pricing"]))
|
141 |
+
{
|
142 |
+
$this->_optpriceinfo=$this->buildSAPTable($item["super_attribute_pricing"]);
|
143 |
+
unset($item["super_attribute_pricing"]);
|
144 |
+
}
|
145 |
+
return true;
|
146 |
+
}
|
147 |
+
|
148 |
+
public function getMatchMode($item)
|
149 |
+
{
|
150 |
+
$matchmode="auto";
|
151 |
+
if($this->getParam('CFGR:nolink',0))
|
152 |
+
{
|
153 |
+
$matchmode="none";
|
154 |
+
|
155 |
+
}
|
156 |
+
else
|
157 |
+
{
|
158 |
+
if($this->getParam("CFGR:simplesbeforeconf")==1)
|
159 |
+
{
|
160 |
+
$matchmode="cursimples";
|
161 |
+
}
|
162 |
+
if(isset($item["simples_skus"]) && trim($item["simples_skus"])!="")
|
163 |
+
{
|
164 |
+
$matchmode="fixed";
|
165 |
+
}
|
166 |
+
}
|
167 |
+
return $matchmode;
|
168 |
+
}
|
169 |
+
|
170 |
+
public function processItemAfterId(&$item,$params=null)
|
171 |
+
{
|
172 |
+
//if item is not configurable, nothing to do
|
173 |
+
if($item["type"]!=="configurable")
|
174 |
+
{
|
175 |
+
if($this->getParam("CFGR:simplesbeforeconf")==1)
|
176 |
+
{
|
177 |
+
$this->_currentsimples[]=$item["sku"];
|
178 |
+
}
|
179 |
+
return true;
|
180 |
+
}
|
181 |
+
|
182 |
+
//check for explicit configurable attributes
|
183 |
+
if(isset($item["configurable_attributes"]))
|
184 |
+
{
|
185 |
+
$confopts=explode(",",$item["configurable_attributes"]);
|
186 |
+
for($i=0;$i<count($confopts);$i++)
|
187 |
+
{
|
188 |
+
$confopts[$i]=trim($confopts[$i]);
|
189 |
+
}
|
190 |
+
}
|
191 |
+
//if not found, try to deduce them
|
192 |
+
else
|
193 |
+
{
|
194 |
+
$asconfopts=$this->getConfigurableOptsFromAsId($params["asid"]);
|
195 |
+
//limit configurable options to ones presents & defined in item
|
196 |
+
$confopts=array();
|
197 |
+
foreach($asconfopts as $confopt)
|
198 |
+
{
|
199 |
+
if(in_array($confopt,array_keys($item)) && trim($item[$confopt])!="")
|
200 |
+
{
|
201 |
+
$confopts[]=$confopt;
|
202 |
+
}
|
203 |
+
}
|
204 |
+
unset($asconfotps);
|
205 |
+
}
|
206 |
+
//if no configurable attributes, nothing to do
|
207 |
+
if(count($confopts)==0)
|
208 |
+
{
|
209 |
+
$this->log("No configurable attributes found for configurable sku: ".$item["sku"]." cannot link simples.","warning");
|
210 |
+
return true;
|
211 |
+
}
|
212 |
+
//set product to have options & required
|
213 |
+
$tname=$this->tablename('catalog_product_entity');
|
214 |
+
$sql="UPDATE $tname SET has_options=1,required_options=1 WHERE entity_id=?";
|
215 |
+
$this->update($sql,$params["product_id"]);
|
216 |
+
//matching mode
|
217 |
+
//if associated skus
|
218 |
+
|
219 |
+
$matchmode=$this->getMatchMode($item);
|
220 |
+
|
221 |
+
//check if item has exising options
|
222 |
+
$pid=$params["product_id"];
|
223 |
+
$cpsa=$this->tablename("catalog_product_super_attribute");
|
224 |
+
$cpsal=$this->tablename("catalog_product_super_attribute_label");
|
225 |
+
|
226 |
+
//process configurable options
|
227 |
+
$ins_sa=array();
|
228 |
+
$data_sa=array();
|
229 |
+
$ins_sal=array();
|
230 |
+
$data_sal=array();
|
231 |
+
$idx=0;
|
232 |
+
foreach($confopts as $confopt)
|
233 |
+
{
|
234 |
+
|
235 |
+
$attrinfo=$this->getAttrInfo($confopt);
|
236 |
+
$attrid=$attrinfo["attribute_id"];
|
237 |
+
$psaid=NULL;
|
238 |
+
|
239 |
+
//try to get psaid for attribute
|
240 |
+
$sql="SELECT product_super_attribute_id as psaid FROM `$cpsa` WHERE product_id=? AND attribute_id=?";
|
241 |
+
$psaid=$this->selectOne($sql,array($pid,$attrid),"psaid");
|
242 |
+
//if no entry found, create one
|
243 |
+
if($psaid==NULL)
|
244 |
+
{
|
245 |
+
$sql="INSERT INTO `$cpsa` (`product_id`,`attribute_id`,`position`) VALUES (?,?,?)";
|
246 |
+
//inserting new options
|
247 |
+
$psaid=$this->insert($sql,array($pid,$attrid,$idx));
|
248 |
+
}
|
249 |
+
|
250 |
+
|
251 |
+
//for all stores defined for the item
|
252 |
+
$sids=$this->getItemStoreIds($item,0);
|
253 |
+
$data=array();
|
254 |
+
$ins=array();
|
255 |
+
foreach($sids as $sid)
|
256 |
+
{
|
257 |
+
$data[]=$psaid;
|
258 |
+
$data[]=$sid;
|
259 |
+
$data[] = $attrinfo['frontend_label'];
|
260 |
+
$ins[]="(?,?,1,?)";
|
261 |
+
}
|
262 |
+
if(count($ins)>0)
|
263 |
+
{
|
264 |
+
//insert/update attribute value for association
|
265 |
+
$sql="INSERT INTO `$cpsal` (`product_super_attribute_id`,`store_id`,`use_default`,`value`) VALUES ".implode(",",$ins).
|
266 |
+
"ON DUPLICATE KEY UPDATE value=VALUES(`value`)";
|
267 |
+
$this->insert($sql,$data);
|
268 |
+
}
|
269 |
+
//if we have price info for this attribute
|
270 |
+
if(isset($this->_optpriceinfo[$confopt]))
|
271 |
+
{
|
272 |
+
$cpsap=$this->tablename("catalog_product_super_attribute_pricing");
|
273 |
+
$wsids=$this->getItemWebsites($item);
|
274 |
+
//if admin set as store, website force to 0
|
275 |
+
if(in_array(0,$sids))
|
276 |
+
{
|
277 |
+
$wsids=array(0);
|
278 |
+
}
|
279 |
+
$data=array();
|
280 |
+
$ins=array();
|
281 |
+
|
282 |
+
foreach($this->_optpriceinfo[$confopt] as $opdef)
|
283 |
+
{
|
284 |
+
//if optpriceinfo has no is_percent, force to 0
|
285 |
+
$opinf=explode(":",$opdef);
|
286 |
+
$optids=$this->getOptionIds($attrid,0,explode("//",$opinf[0]));
|
287 |
+
foreach($optids as $optid)
|
288 |
+
{
|
289 |
+
//generate price info for each given website
|
290 |
+
foreach($wsids as $wsid)
|
291 |
+
{
|
292 |
+
if(count($opinf)<3)
|
293 |
+
{
|
294 |
+
$opinf[]=0;
|
295 |
+
}
|
296 |
+
|
297 |
+
$data[]=$psaid;
|
298 |
+
$data[]=$optid;
|
299 |
+
$data[]=$opinf[1];
|
300 |
+
$data[]=$opinf[2];
|
301 |
+
$data[]=$wsid;
|
302 |
+
$ins[]="(?,?,?,?,?)";
|
303 |
+
}
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
$sql="INSERT INTO $cpsap (`product_super_attribute_id`,`value_index`,`pricing_value`,`is_percent`,`website_id`) VALUES ".implode(",",$ins).
|
308 |
+
" ON DUPLICATE KEY UPDATE pricing_value=VALUES(pricing_value),is_percent=VALUES(is_percent)";
|
309 |
+
$this->insert($sql,$data);
|
310 |
+
unset($data);
|
311 |
+
}
|
312 |
+
$idx++;
|
313 |
+
}
|
314 |
+
unset($confopts);
|
315 |
+
switch($matchmode)
|
316 |
+
{
|
317 |
+
case "none":
|
318 |
+
break;
|
319 |
+
case "auto":
|
320 |
+
//destroy old associations
|
321 |
+
$this->autoLink($pid);
|
322 |
+
$this->updSimpleVisibility($pid);
|
323 |
+
break;
|
324 |
+
case "cursimples":
|
325 |
+
$this->fixedLink($pid,$this->_currentsimples);
|
326 |
+
$this->updSimpleVisibility($pid);
|
327 |
+
|
328 |
+
break;
|
329 |
+
case "fixed":
|
330 |
+
$sskus=explode(",",$item["simples_skus"]);
|
331 |
+
trimarray($sskus);
|
332 |
+
$this->fixedLink($pid,$sskus);
|
333 |
+
$this->updSimpleVisibility($pid);
|
334 |
+
unset($item["simples_skus"]);
|
335 |
+
break;
|
336 |
+
default:
|
337 |
+
break;
|
338 |
+
}
|
339 |
+
//always clear current simples
|
340 |
+
if(count($this->_currentsimples)>0)
|
341 |
+
{
|
342 |
+
unset($this->_currentsimples);
|
343 |
+
$this->_currentsimples=array();
|
344 |
+
}
|
345 |
+
return true;
|
346 |
+
}
|
347 |
+
|
348 |
+
|
349 |
+
public function processColumnList(&$cols,$params=null)
|
350 |
+
{
|
351 |
+
if(!in_array("options_container",$cols))
|
352 |
+
{
|
353 |
+
$cols=array_unique(array_merge($cols,array("options_container")));
|
354 |
+
$this->_use_defaultopc=true;
|
355 |
+
$this->log("no options_container set, defaulting to :Block after product info","startup");
|
356 |
+
}
|
357 |
+
}
|
358 |
+
|
359 |
+
public function getPluginParamNames()
|
360 |
+
{
|
361 |
+
return array("CFGR:simplesbeforeconf","CFGR:updsimplevis","CFGR:nolink");
|
362 |
+
}
|
363 |
+
|
364 |
+
static public function getCategory()
|
365 |
+
{
|
366 |
+
return "Product Type Import";
|
367 |
+
}
|
368 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/configurables/options_panel.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugins handles configurable import
|
3 |
+
</div>
|
4 |
+
|
5 |
+
<ul class="formline">
|
6 |
+
<li class="label" style="width:360px">Perform simples/configurable link</li>
|
7 |
+
<li class="value">
|
8 |
+
<select name="CFGR:nolink">
|
9 |
+
<option value="0" <?php if ($this->getParam("CFGR:nolink",0)==0){?>selected="selected"<?php }?>>Yes</option>
|
10 |
+
<option value="1" <?php if ($this->getParam("CFGR:nolink",0)==1){?>selected="selected"<?php }?>>No</option>
|
11 |
+
</select>
|
12 |
+
</li>
|
13 |
+
</ul>
|
14 |
+
<ul class="formline">
|
15 |
+
<li class="label" style="width:360px">auto match simples skus before configurable</li>
|
16 |
+
<li class="value"><select name="CFGR:simplesbeforeconf">
|
17 |
+
<option value="0" <?php if ($this->getParam("CFGR:simplesbeforeconf")==0){?>selected="selected"<?php }?>>No</option>
|
18 |
+
<option value="1" <?php if ($this->getParam("CFGR:simplesbeforeconf")==1){?>selected="selected"<?php }?>>Yes</option></select></li>
|
19 |
+
</ul>
|
20 |
+
<ul class="formline">
|
21 |
+
<li class="label">
|
22 |
+
Force simples visibility
|
23 |
+
</li>
|
24 |
+
<li class="value">
|
25 |
+
<?php $v=$this->getParam("CFGR:updsimplevis",0)?>
|
26 |
+
<select name="CFGR:updsimplevis">
|
27 |
+
<option value="0" <?php if($v==0){?>selected="selected"<?php }?>>No</option>
|
28 |
+
<option value="1" <?php if($v==1){?>selected="selected"<?php }?>>Not Visible Individually</option>
|
29 |
+
<option value="2" <?php if($v==2){?>selected="selected"<?php }?>>Catalog</option>
|
30 |
+
<option value="3" <?php if($v==3){?>selected="selected"<?php }?>>Search</option>
|
31 |
+
<option value="4" <?php if($v==4){?>selected="selected"<?php }?>>Catalog, Search</option>
|
32 |
+
</select>
|
33 |
+
</li>
|
34 |
+
</ul>
|
lib/Magmi/plugins/base/itemprocessors/defaultvalues/00_default_values.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class SampleItemProcessor
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
* This class is a sample for item processing
|
7 |
+
*/
|
8 |
+
class DefaultValuesItemProcessor extends Magmi_ItemProcessor
|
9 |
+
{
|
10 |
+
|
11 |
+
protected $_dset=array();
|
12 |
+
protected $_dcols=array();
|
13 |
+
|
14 |
+
public function getPluginInfo()
|
15 |
+
{
|
16 |
+
return array(
|
17 |
+
"name" => "Default Values setter",
|
18 |
+
"author" => "Dweeves",
|
19 |
+
"version" => "0.0.5",
|
20 |
+
"url" => $this->pluginDocUrl("Default_Values_setter")
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
26 |
+
* @param Magmi_Engine $mmi : reference to magmi engine instance (convenient to perform database operations)
|
27 |
+
* @param unknown_type $item : modifiable reference to item before import
|
28 |
+
* the $item is a key/value array with column names as keys and values as read from csv file.
|
29 |
+
* @return bool :
|
30 |
+
* true if you want the item to be imported after your custom processing
|
31 |
+
* false if you want to skip item import after your processing
|
32 |
+
*/
|
33 |
+
|
34 |
+
|
35 |
+
public function processItemBeforeId(&$item,$params=null)
|
36 |
+
{
|
37 |
+
foreach($this->_dcols as $col)
|
38 |
+
{
|
39 |
+
$item[$col]=$this->_dset[$col];
|
40 |
+
}
|
41 |
+
return true;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function processItemAfterId(&$item,$params=null)
|
45 |
+
{
|
46 |
+
return true;
|
47 |
+
}
|
48 |
+
|
49 |
+
/*
|
50 |
+
public function processItemException(&$item,$params=null)
|
51 |
+
{
|
52 |
+
|
53 |
+
}*/
|
54 |
+
|
55 |
+
public function initialize($params)
|
56 |
+
{
|
57 |
+
foreach($params as $k=>$v)
|
58 |
+
{
|
59 |
+
if(preg_match_all("/^DEFAULT:(.*)$/",$k,$m) && $k!="DEFAULT:columnlist")
|
60 |
+
{
|
61 |
+
$this->_dset[$m[1][0]]=$params[$k];
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
65 |
+
|
66 |
+
public function getPluginParams($params)
|
67 |
+
{
|
68 |
+
$pp=array();
|
69 |
+
foreach($params as $k=>$v)
|
70 |
+
{
|
71 |
+
if(preg_match("/^DEFAULT:.*$/",$k))
|
72 |
+
{
|
73 |
+
$pp[$k]=$v;
|
74 |
+
}
|
75 |
+
}
|
76 |
+
return $pp;
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
public function processColumnList(&$cols,$params=null)
|
81 |
+
{
|
82 |
+
$dcols=array_diff(array_keys($this->_dset),array_intersect($cols,array_keys($this->_dset)));
|
83 |
+
foreach($dcols as $col)
|
84 |
+
{
|
85 |
+
if(!empty($this->_dset[$col]))
|
86 |
+
{
|
87 |
+
$cols[]=$col;
|
88 |
+
$this->_dcols[]=$col;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
$this->log("Adding Columns ".implode(",",$dcols),"startup");
|
92 |
+
|
93 |
+
return true;
|
94 |
+
}
|
95 |
+
|
96 |
+
static public function getCategory()
|
97 |
+
{
|
98 |
+
return "Input Data Preprocessing";
|
99 |
+
}
|
100 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/defaultvalues/options_panel.php
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php $clist=$this->fixListParam($this->getParam("DEFAULT:columnlist"))?>
|
2 |
+
<div class="plugin_description">
|
3 |
+
This plugin enables to set some default item values if not found in input source.
|
4 |
+
enter columns to set default value for in default attribute list field, separated by commas (,)
|
5 |
+
when leaving the field, new fields will be inserted for filling default values.
|
6 |
+
</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" name="DEFAULT:columnlist" size="80" value="<?php echo $clist?>" onblur="default_mf.buildparamlist()"></input></li>
|
11 |
+
</ul>
|
12 |
+
<div style="position:relative">
|
13 |
+
<div id="DEFAULT:columnsetup">
|
14 |
+
</div>
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
<script type="text/javascript">
|
18 |
+
var df_vals=<?php echo tdarray_to_js($this,'DEFAULT:columnlist','DEFAULT')?>;
|
19 |
+
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>';
|
20 |
+
default_mf=new magmi_multifield('DEFAULT:columnlist','DEFAULT:columnsetup',df_linetpl,df_vals);
|
21 |
+
default_mf.buildparamlist();
|
22 |
+
</script>
|
lib/Magmi/plugins/base/itemprocessors/genericmapper/02_genericmapper.php
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class SampleItemProcessor
|
4 |
+
* @author dweeves
|
5 |
+
*
|
6 |
+
* This class is a sample for item processing
|
7 |
+
*/
|
8 |
+
class GenericMapperProcessor extends Magmi_ItemProcessor
|
9 |
+
{
|
10 |
+
protected $_mapping;
|
11 |
+
|
12 |
+
public function getPluginInfo()
|
13 |
+
{
|
14 |
+
return array(
|
15 |
+
"name" => "Generic mapper",
|
16 |
+
"author" => "Dweeves",
|
17 |
+
"version" => "0.0.6a",
|
18 |
+
"url" => $this->pluginDocUrl("Generic_mapper")
|
19 |
+
);
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* you can add/remove columns for the item passed since it is passed by reference
|
24 |
+
* @param Magmi_Engine $mmi : reference to magmi engine instance (convenient to perform database operations)
|
25 |
+
* @param unknown_type $item : 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 |
+
|
32 |
+
|
33 |
+
public function processItemBeforeId(&$item,$params=null)
|
34 |
+
{
|
35 |
+
foreach(array_keys($item) as $k)
|
36 |
+
{
|
37 |
+
$mapped=false;
|
38 |
+
if(isset($this->_mapping["$k.csv"]))
|
39 |
+
{
|
40 |
+
$mpd=$this->_mapping["$k.csv"]["DIRECT"];
|
41 |
+
if(isset($mpd[$item[$k]]))
|
42 |
+
{
|
43 |
+
$item[$k]=$mpd[$item[$k]];
|
44 |
+
$mapped=true;
|
45 |
+
}
|
46 |
+
else
|
47 |
+
{
|
48 |
+
$mpr=$this->_mapping["$k.csv"]["RE"];
|
49 |
+
foreach($mpr as $re=>$value)
|
50 |
+
{
|
51 |
+
if(preg_match("|$re|msi",$item[$k]))
|
52 |
+
{
|
53 |
+
$item[$k]=preg_replace("|$re|",$value,$item[$k]);
|
54 |
+
$mapped=true;
|
55 |
+
break;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
}
|
60 |
+
}
|
61 |
+
#if not found,try common mappings
|
62 |
+
if(!$mapped)
|
63 |
+
{
|
64 |
+
$mpd=$this->_mapping["__common__.csv"]["DIRECT"];
|
65 |
+
if(isset($mpd[$item[$k]]))
|
66 |
+
{
|
67 |
+
$item[$k]=$mpd[$item[$k]];
|
68 |
+
}
|
69 |
+
}
|
70 |
+
}
|
71 |
+
return true;
|
72 |
+
}
|
73 |
+
|
74 |
+
|
75 |
+
|
76 |
+
public function initialize($params)
|
77 |
+
{
|
78 |
+
$this->_mapping=array();
|
79 |
+
|
80 |
+
$dlist=glob(dirname(__file__)."/mappings/default/*.csv");
|
81 |
+
if($dlist==false)
|
82 |
+
{
|
83 |
+
$dlist=array();
|
84 |
+
$this->log("No default mapping found","warning");
|
85 |
+
}
|
86 |
+
$slist=glob(dirname(__file__)."/mappings/*.csv");
|
87 |
+
if($slist==false)
|
88 |
+
{
|
89 |
+
$slist=array();
|
90 |
+
$this->log("No custom mapping found","startup");
|
91 |
+
}
|
92 |
+
$flist=array_merge($dlist,$slist);
|
93 |
+
foreach($flist as $fname)
|
94 |
+
{
|
95 |
+
$idx=basename($fname);
|
96 |
+
if(!isset($this->_mapping[$idx]))
|
97 |
+
{
|
98 |
+
$this->_mapping[$idx]=array("DIRECT"=>array(),"RE"=>array());
|
99 |
+
}
|
100 |
+
$mf=fopen("$fname","r");
|
101 |
+
while (($data = fgetcsv($mf, 1000, ",")) !== FALSE)
|
102 |
+
{
|
103 |
+
if(substr($data[0],0,4)=="_RE:")
|
104 |
+
{
|
105 |
+
$target="RE";
|
106 |
+
$key=substr($data[0],4);
|
107 |
+
}
|
108 |
+
else
|
109 |
+
{
|
110 |
+
$target="DIRECT";
|
111 |
+
$key=$data[0];
|
112 |
+
}
|
113 |
+
$this->_mapping[$idx][$target][$key]=$data[1];
|
114 |
+
}
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
static public function getCategory()
|
119 |
+
{
|
120 |
+
return "Input Data Preprocessing";
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/__common__.csv
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
"Yes",1
|
2 |
+
"No",0
|
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"
|
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"
|
lib/Magmi/plugins/base/itemprocessors/genericmapper/mappings/default/status.csv
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
"Enabled",1
|
2 |
+
"Disabled",2
|
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
|
lib/Magmi/plugins/base/itemprocessors/genericmapper/options_panel.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin provides value mapping for csv values before they are handled by magmi
|
3 |
+
typically visibility & page_layout need mapping for magmi to process them correctly.
|
4 |
+
to change the mappings accordingly to your config,please edit the csv files located at :
|
5 |
+
<pre>[magmi_dir]/plugins/itemprocessors/genericmapper/mappings</pre>
|
6 |
+
the csv files have the following names [column_to_map].csv
|
7 |
+
</div>
|
lib/Magmi/plugins/base/itemprocessors/grouped/alpine_groupedprocessor.php
ADDED
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The MIT License (MIT)
|
4 |
+
* Copyright (c) 2012 Alpine Consulting, Inc
|
5 |
+
*
|
6 |
+
* Permission is hereby granted, free of charge, to any person obtaining
|
7 |
+
* a copy of this software and associated documentation files (the
|
8 |
+
* "Software"), to deal in the Software without restriction, including
|
9 |
+
* without limitation the rights to use, copy, modify, merge, publish,
|
10 |
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
11 |
+
* permit persons to whom the Software is furnished to do so, subject to
|
12 |
+
* the following conditions:
|
13 |
+
*
|
14 |
+
* The above copyright notice and this permission notice shall be included
|
15 |
+
* in all copies or substantial portions of the Software.
|
16 |
+
*
|
17 |
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
18 |
+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19 |
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20 |
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
21 |
+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
22 |
+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
23 |
+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24 |
+
* SOFTWARE.
|
25 |
+
*
|
26 |
+
* Grouped Item processor
|
27 |
+
* Based on magmi_configurableprocessor by dweeves
|
28 |
+
*
|
29 |
+
* @author Alpine Consulting, Inc
|
30 |
+
*
|
31 |
+
* This imports grouped products and associates the simple products to
|
32 |
+
* the group
|
33 |
+
*/
|
34 |
+
class Magmi_GroupedItemProcessor extends Magmi_ItemProcessor
|
35 |
+
{
|
36 |
+
|
37 |
+
public static $_VERSION = '1.1';
|
38 |
+
private $_use_defaultopc = false;
|
39 |
+
private $_optpriceinfo = array();
|
40 |
+
private $_currentgrouped = array();
|
41 |
+
private $_linktype=null;
|
42 |
+
|
43 |
+
public function getPluginUrl()
|
44 |
+
{
|
45 |
+
return $this->pluginDocUrl('Grouped_Item_processor');
|
46 |
+
}
|
47 |
+
|
48 |
+
public function getPluginVersion()
|
49 |
+
{
|
50 |
+
return self::$_VERSION;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function getPluginName()
|
54 |
+
{
|
55 |
+
return 'Grouped Item processor';
|
56 |
+
}
|
57 |
+
|
58 |
+
public function getPluginAuthor()
|
59 |
+
{
|
60 |
+
return 'Alpine Consulting, Inc & Dweeves';
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Links the simple products to the group
|
65 |
+
*
|
66 |
+
* @param type $pid
|
67 |
+
* @param type $cond
|
68 |
+
* @param type $conddata
|
69 |
+
*/
|
70 |
+
public function dolink($pid, $cond, $conddata = array())
|
71 |
+
{
|
72 |
+
$cpl = $this->tablename("catalog_product_link");
|
73 |
+
$cpsl = $this->tablename("catalog_product_super_link");
|
74 |
+
$cpr = $this->tablename("catalog_product_relation");
|
75 |
+
$cpe = $this->tablename("catalog_product_entity");
|
76 |
+
$cplt = $this->tablename("catalog_product_link_type");
|
77 |
+
|
78 |
+
$sql = "DELETE cpsl.*,cpsr.* FROM $cpsl as cpsl
|
79 |
+
JOIN $cpr as cpsr ON cpsr.parent_id=cpsl.parent_id
|
80 |
+
WHERE cpsl.parent_id=?";
|
81 |
+
$this->delete($sql, array($pid));
|
82 |
+
$sql = "DELETE FROM $cpl
|
83 |
+
WHERE product_id=?";
|
84 |
+
$this->delete($sql, array($pid));
|
85 |
+
//recreate associations
|
86 |
+
$sql = "INSERT INTO $cpsl (`parent_id`,`product_id`)
|
87 |
+
SELECT cpec.entity_id as parent_id,cpes.entity_id as product_id
|
88 |
+
FROM $cpe as cpec
|
89 |
+
JOIN $cpe as cpes ON cpes.sku $cond
|
90 |
+
WHERE cpec.entity_id=?";
|
91 |
+
$this->insert($sql, array_merge($conddata, array($pid)));
|
92 |
+
if($this->_linktype==NULL)
|
93 |
+
{
|
94 |
+
$sql = "select link_type_id from $cplt where code=?";
|
95 |
+
$this->_linktype = $this->selectone($sql, 'super', 'link_type_id');
|
96 |
+
}
|
97 |
+
$sql = "INSERT INTO $cpl (`product_id`,`linked_product_id`, `link_type_id`)
|
98 |
+
SELECT cpec.entity_id as parent_id,cpes.entity_id as product_id, ?
|
99 |
+
FROM $cpe as cpec
|
100 |
+
JOIN $cpe as cpes ON cpes.sku $cond
|
101 |
+
WHERE cpec.entity_id=?";
|
102 |
+
$this->insert($sql, array_merge(array($this->_linktype),$conddata, array($pid)));
|
103 |
+
$sql = "INSERT INTO $cpr (`parent_id`,`child_id`)
|
104 |
+
SELECT cpec.entity_id as parent_id,cpes.entity_id as child_id
|
105 |
+
FROM $cpe as cpec
|
106 |
+
JOIN $cpe as cpes ON cpes.sku $cond
|
107 |
+
WHERE cpec.entity_id=?";
|
108 |
+
$this->insert($sql, array_merge($conddata, array($pid)));
|
109 |
+
unset($conddata);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Wrapper for dolink
|
114 |
+
*
|
115 |
+
* @see dolink($pid, $cond, $conddata = array())
|
116 |
+
* @param type $pid
|
117 |
+
*/
|
118 |
+
public function autoLink($pid)
|
119 |
+
{
|
120 |
+
$this->dolink($pid, "LIKE CONCAT(cpec.sku,'%')");
|
121 |
+
}
|
122 |
+
|
123 |
+
public function updSimpleVisibility($pid)
|
124 |
+
{
|
125 |
+
$vis = $this->getParam("APIGRP:updgroupedvis", 0);
|
126 |
+
if ($vis != 0) {
|
127 |
+
$attinfo = $this->getAttrInfo("visibility");
|
128 |
+
$sql = "UPDATE " . $this->tablename("catalog_product_entity_int") . " as cpei
|
129 |
+
JOIN " . $this->tablename("catalog_product_super_link") . " as cpsl ON cpsl.parent_id=?
|
130 |
+
JOIN " . $this->tablename("catalog_product_entity") . " as cpe ON cpe.entity_id=cpsl.product_id
|
131 |
+
SET cpei.value=?
|
132 |
+
WHERE cpei.entity_id=cpe.entity_id AND attribute_id=?";
|
133 |
+
$this->update($sql, array($pid, $vis, $attinfo["attribute_id"]));
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Wrapper for dolink
|
139 |
+
*
|
140 |
+
* @see dolink($pid, $cond, $conddata = array())
|
141 |
+
* @param type $pid
|
142 |
+
* @param type $skulist
|
143 |
+
*/
|
144 |
+
public function fixedLink($pid, $skulist)
|
145 |
+
{
|
146 |
+
$this->dolink($pid, "IN (" . $this->arr2values($skulist) . ")", $skulist);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Determines which method is being used for linking the simple products
|
151 |
+
* to the group
|
152 |
+
*
|
153 |
+
* @param type $item
|
154 |
+
* @return string
|
155 |
+
*/
|
156 |
+
public function getMatchMode($item)
|
157 |
+
{
|
158 |
+
$matchmode = "auto";
|
159 |
+
if ($this->getParam('APIGRP:nolink', 0)) {
|
160 |
+
$matchmode = "none";
|
161 |
+
} else {
|
162 |
+
if ($this->getParam("APIGRP:groupedbeforegrp") == 1) {
|
163 |
+
$matchmode = "cursimples";
|
164 |
+
}
|
165 |
+
if (isset($item["grouped_skus"]) && trim($item["grouped_skus"]) != "") {
|
166 |
+
$matchmode = "fixed";
|
167 |
+
}
|
168 |
+
}
|
169 |
+
return $matchmode;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function processItemAfterId(&$item, $params = null) {
|
173 |
+
//if item is not grouped, nothing to do
|
174 |
+
if ($item["type"] !== "grouped") {
|
175 |
+
if ($this->getParam("APIGRP:groupedbeforegrp") == 1) {
|
176 |
+
$this->_currentgrouped[] = $item["sku"];
|
177 |
+
}
|
178 |
+
return true;
|
179 |
+
}
|
180 |
+
|
181 |
+
$pid = $params["product_id"];
|
182 |
+
$matchmode = $this->getMatchMode($item);
|
183 |
+
switch ($matchmode)
|
184 |
+
{
|
185 |
+
case "none":
|
186 |
+
break;
|
187 |
+
case "auto":
|
188 |
+
//destroy old associations
|
189 |
+
$this->autoLink($pid);
|
190 |
+
$this->updSimpleVisibility($pid);
|
191 |
+
break;
|
192 |
+
case "cursimples":
|
193 |
+
$this->fixedLink($pid, $this->_currentgrouped);
|
194 |
+
$this->updSimpleVisibility($pid);
|
195 |
+
break;
|
196 |
+
case "fixed":
|
197 |
+
$sskus = explode(",", $item["grouped_skus"]);
|
198 |
+
$this->trimarray($sskus);
|
199 |
+
$this->fixedLink($pid, $sskus);
|
200 |
+
$this->updSimpleVisibility($pid);
|
201 |
+
unset($item["simples_skus"]);
|
202 |
+
break;
|
203 |
+
default:
|
204 |
+
break;
|
205 |
+
}
|
206 |
+
//always clear current simples
|
207 |
+
if (count($this->_currentgrouped) > 0) {
|
208 |
+
unset($this->_currentgrouped);
|
209 |
+
$this->_currentgrouped = array();
|
210 |
+
}
|
211 |
+
return true;
|
212 |
+
}
|
213 |
+
|
214 |
+
public function getPluginParamNames() {
|
215 |
+
return array("APIGRP:groupedbeforegrp", "APIGRP:updgroupedvis", "APIGRP:nolink");
|
216 |
+
}
|
217 |
+
|
218 |
+
static public function getCategory() {
|
219 |
+
return "Product Type Import";
|
220 |
+
}
|
221 |
+
|
222 |
+
private function trimarray(&$arr) {
|
223 |
+
for ($i=0;$i<count($arr);$i++) {
|
224 |
+
$arr[$i]=trim($arr[$i]);
|
225 |
+
}
|
226 |
+
}
|
227 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/grouped/options_panel.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The MIT License (MIT)
|
4 |
+
* Copyright (c) 2012 Alpine Consulting, Inc
|
5 |
+
*
|
6 |
+
* Permission is hereby granted, free of charge, to any person obtaining
|
7 |
+
* a copy of this software and associated documentation files (the
|
8 |
+
* "Software"), to deal in the Software without restriction, including
|
9 |
+
* without limitation the rights to use, copy, modify, merge, publish,
|
10 |
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
11 |
+
* permit persons to whom the Software is furnished to do so, subject to
|
12 |
+
* the following conditions:
|
13 |
+
*
|
14 |
+
* The above copyright notice and this permission notice shall be included
|
15 |
+
* in all copies or substantial portions of the Software.
|
16 |
+
*
|
17 |
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
18 |
+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19 |
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20 |
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
21 |
+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
22 |
+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
23 |
+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
24 |
+
* SOFTWARE.
|
25 |
+
*
|
26 |
+
*/?>
|
27 |
+
<div class="plugin_description">
|
28 |
+
This plugins handles grouped item import
|
29 |
+
</div>
|
30 |
+
|
31 |
+
<ul class="formline">
|
32 |
+
<li class="label" style="width:360px">Perform simples/group link</li>
|
33 |
+
<li class="value">
|
34 |
+
<select name="APIGRP:nolink">
|
35 |
+
<option value="0" <?php if ($this->getParam("APIGRP:nolink",0)==0){?>selected="selected"<?php }?>>Yes</option>
|
36 |
+
<option value="1" <?php if ($this->getParam("APIGRP:nolink",0)==1){?>selected="selected"<?php }?>>No</option>
|
37 |
+
</select>
|
38 |
+
</li>
|
39 |
+
</ul>
|
40 |
+
<ul class="formline">
|
41 |
+
<li class="label" style="width:360px">auto match simples skus before grouped</li>
|
42 |
+
<li class="value"><select name="APIGRP:groupedbeforegrp">
|
43 |
+
<option value="0" <?php if ($this->getParam("APIGRP:groupedbeforegrp")==0){?>selected="selected"<?php }?>>No</option>
|
44 |
+
<option value="1" <?php if ($this->getParam("APIGRP:groupedbeforegrp")==1){?>selected="selected"<?php }?>>Yes</option></select></li>
|
45 |
+
</ul>
|
46 |
+
<ul class="formline">
|
47 |
+
<li class="label">
|
48 |
+
Force simples visibility
|
49 |
+
</li>
|
50 |
+
<li class="value">
|
51 |
+
<?php $v=$this->getParam("APIGRP:updgroupedvis",0)?>
|
52 |
+
<select name="APIGRP:updgroupedvis">
|
53 |
+
<option value="0" <?php if($v==0){?>selected="selected"<?php }?>>No</option>
|
54 |
+
<option value="1" <?php if($v==1){?>selected="selected"<?php }?>>Not Visible Individually</option>
|
55 |
+
<option value="2" <?php if($v==2){?>selected="selected"<?php }?>>Catalog</option>
|
56 |
+
<option value="3" <?php if($v==3){?>selected="selected"<?php }?>>Search</option>
|
57 |
+
<option value="4" <?php if($v==4){?>selected="selected"<?php }?>>Catalog, Search</option>
|
58 |
+
</select>
|
59 |
+
</li>
|
60 |
+
</ul>
|
lib/Magmi/plugins/base/itemprocessors/importlimiter/01_importlimiter.php
ADDED
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class ImportLimiter extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
protected $_recranges;
|
5 |
+
protected $_rmax=-1;
|
6 |
+
protected $_filters;
|
7 |
+
protected $_col_filter=NULL;
|
8 |
+
|
9 |
+
public function getPluginInfo()
|
10 |
+
{
|
11 |
+
return array("name"=>"Magmi Import Limiter",
|
12 |
+
"author"=>"Dweeves",
|
13 |
+
"version"=>"0.0.6",
|
14 |
+
"url"=>$this->pluginDocUrl("Magmi_Import_Limiter"));
|
15 |
+
}
|
16 |
+
|
17 |
+
|
18 |
+
public function filtermatch($item,$fltdef)
|
19 |
+
{
|
20 |
+
$negate=0;
|
21 |
+
$field=$fltdef[0];
|
22 |
+
$match=false;
|
23 |
+
if($field[0]=="!")
|
24 |
+
{
|
25 |
+
$field=substr($field,1);
|
26 |
+
$negate=1;
|
27 |
+
}
|
28 |
+
$re=$fltdef[1];
|
29 |
+
if(in_array($field,array_keys($item)))
|
30 |
+
{
|
31 |
+
$v=$item[$field];
|
32 |
+
$match=preg_match("|$re|",$v);
|
33 |
+
if($negate)
|
34 |
+
{
|
35 |
+
$match=!$match;
|
36 |
+
}
|
37 |
+
if($match)
|
38 |
+
{
|
39 |
+
$this->log("skipping sku {$item['sku']} => Filter '$field::$re'","info");
|
40 |
+
}
|
41 |
+
}
|
42 |
+
return $match;
|
43 |
+
}
|
44 |
+
public function processItemBeforeId(&$item,$params=null)
|
45 |
+
{
|
46 |
+
$crow=$this->getCurrentRow();
|
47 |
+
$ok=(count($this->_recranges)==0);
|
48 |
+
|
49 |
+
if(!$ok)
|
50 |
+
{
|
51 |
+
if($this->_rmax>-1 && $crow==$this->_rmax)
|
52 |
+
{
|
53 |
+
$this->setLastItem($item);
|
54 |
+
}
|
55 |
+
foreach($this->_recranges as $rr)
|
56 |
+
{
|
57 |
+
$ok=($crow>=$rr[0] && ($crow<=$rr[1] || $rr[1]==-1));
|
58 |
+
if($ok)
|
59 |
+
{
|
60 |
+
break;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
if($ok)
|
67 |
+
{
|
68 |
+
foreach($this->_filters as $fltdef)
|
69 |
+
{
|
70 |
+
//negative filters
|
71 |
+
$ok=$ok && (!$this->filtermatch($item,$fltdef));
|
72 |
+
if(!$ok)
|
73 |
+
{
|
74 |
+
break;
|
75 |
+
}
|
76 |
+
}
|
77 |
+
}
|
78 |
+
else
|
79 |
+
{
|
80 |
+
$this->log("Filtered row $crow not in range ".$this->getParam("LIMITER:ranges",""));
|
81 |
+
}
|
82 |
+
|
83 |
+
return $ok;
|
84 |
+
}
|
85 |
+
|
86 |
+
public function parseFilters($fltstr)
|
87 |
+
{
|
88 |
+
$this->_filters=array();
|
89 |
+
if($fltstr=="")
|
90 |
+
{
|
91 |
+
return;
|
92 |
+
}
|
93 |
+
$fltlist=explode(";;",$fltstr);
|
94 |
+
foreach($fltlist as $fltdef)
|
95 |
+
{
|
96 |
+
$fltinf=explode("::",$fltdef);
|
97 |
+
$this->_filters[]=$fltinf;
|
98 |
+
}
|
99 |
+
|
100 |
+
}
|
101 |
+
|
102 |
+
public function parseRanges($rangestr)
|
103 |
+
{
|
104 |
+
$this->_recranges=array();
|
105 |
+
if($rangestr=="")
|
106 |
+
{
|
107 |
+
return;
|
108 |
+
}
|
109 |
+
$rangelist=explode(",",$rangestr);
|
110 |
+
foreach($rangelist as $rdef)
|
111 |
+
{
|
112 |
+
$rlist=explode("-",$rdef);
|
113 |
+
if($rlist[0]=="")
|
114 |
+
{
|
115 |
+
$rlist[0]=-1;
|
116 |
+
}
|
117 |
+
else
|
118 |
+
{
|
119 |
+
$rmin=$rlist[0];
|
120 |
+
}
|
121 |
+
if(count($rlist)>1)
|
122 |
+
{
|
123 |
+
if($rlist[1]=="")
|
124 |
+
{
|
125 |
+
$rlist[1]=-1;
|
126 |
+
}
|
127 |
+
else
|
128 |
+
{
|
129 |
+
$rmax=$rlist[1];
|
130 |
+
if($rmax>$this->_rmax && $this->_rmax!=-1)
|
131 |
+
{
|
132 |
+
$this->_rmax=$rmax;
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
else
|
137 |
+
{
|
138 |
+
$rmax=$rmin;
|
139 |
+
}
|
140 |
+
$this->_recranges[]=array($rmin,$rmax);
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
public function processColumnList(&$cols,$params=null)
|
145 |
+
{
|
146 |
+
if(count($this->_col_filter)>0)
|
147 |
+
{
|
148 |
+
$this->log("limiting columns to :".implode(",",$this->_col_filter),"startup");
|
149 |
+
$cols=$this->_col_filter;
|
150 |
+
}
|
151 |
+
|
152 |
+
}
|
153 |
+
|
154 |
+
public function initialize($params)
|
155 |
+
{
|
156 |
+
$this->parseRanges($this->getParam("LIMITER:ranges",""));
|
157 |
+
$this->parseFilters($this->getParam("LIMITER:filters",""));
|
158 |
+
$this->_col_filter=explode(",",$this->getParam("LIMITER:col_filter"));
|
159 |
+
return true;
|
160 |
+
|
161 |
+
}
|
162 |
+
|
163 |
+
public function getPluginParamNames()
|
164 |
+
{
|
165 |
+
return array('LIMITER:ranges','LIMITER:filters','LIMITER:col_filter');
|
166 |
+
}
|
167 |
+
|
168 |
+
static public function getCategory()
|
169 |
+
{
|
170 |
+
return "Input Data Preprocessing";
|
171 |
+
}
|
172 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/importlimiter/options_panel.php
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugin is made to limit magmi import to selected record ranges or matching values.
|
3 |
+
ranges are ranges of rows to be imported
|
4 |
+
filters are regexps or strings that if matched will exclude record from import
|
5 |
+
</div>
|
6 |
+
|
7 |
+
<div class="ifield">
|
8 |
+
<span class="">Column filter:</span><input type="text" name="LIMITER:col_filter" size="80" value="<?php echo $this->getParam("LIMITER:col_filter")?>"></input>
|
9 |
+
<div class="fieldhelp"></div>
|
10 |
+
<div class="fieldinfo">
|
11 |
+
This field defines what columns should be imported
|
12 |
+
<div class="fieldsyntax" style="display:none">
|
13 |
+
<pre>
|
14 |
+
You should put column names, comma separated ie : sku,qty
|
15 |
+
</pre>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
|
20 |
+
<div class="ifield">
|
21 |
+
<span class="">Limiter ranges:</span><input type="text" name="LIMITER:ranges" size="80" value="<?php echo $this->getParam("LIMITER:ranges")?>"></input>
|
22 |
+
<div class="fieldhelp"></div>
|
23 |
+
<div class="fieldinfo">
|
24 |
+
This field defines what lines should be imported
|
25 |
+
<div class="fieldsyntax" style="display:none">
|
26 |
+
<pre>
|
27 |
+
1-100 : for the first 100 records of csv
|
28 |
+
100- : for all records after 100 (including 100th)
|
29 |
+
1-10,40-50,67,78,89 : for records 1 to 10,40 to 50 , 67 , 78 & 89
|
30 |
+
</pre>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
<div class="ifield">
|
35 |
+
|
36 |
+
<span class="">Limiter filters:</span><input type="text" name="LIMITER:filters" size="80" value="<?php echo $this->getParam("LIMITER:filters")?>"></input>
|
37 |
+
<div class="fieldhelp"></div>
|
38 |
+
<div class="fieldinfo">
|
39 |
+
This field defines what content should not be imported with a regexp like syntax.
|
40 |
+
<div class="fieldsyntax" style="display:none">
|
41 |
+
<pre>
|
42 |
+
sku::00.* : exclude all skus that begin with 00
|
43 |
+
!name::.*blue.* : exclude all items with name not blue (see the ! before the "name" field to negate the filter)
|
44 |
+
sku:00.*;;!name::.*blue.* : exclude all items with skus that begin with 00 which name does not contain blue
|
45 |
+
</pre>
|
46 |
+
</div>
|
47 |
+
</div>
|
48 |
+
</div>
|
lib/Magmi/plugins/base/itemprocessors/productdeleter/options_panel.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugins should be used to delete existing products
|
3 |
+
</div>
|
4 |
+
<ul class="formline">
|
5 |
+
<li>
|
6 |
+
<input type="checkbox" name="PDEL:delsimples" <?php if($this->getParam("PDEL:delsimples",false)==true){?> checked="checked" <?php }?>>Delete children products
|
7 |
+
</li>
|
8 |
+
|
9 |
+
</ul>
|
lib/Magmi/plugins/base/itemprocessors/productdeleter/productdeleter.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class ProductDeleter extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
public function getPluginInfo()
|
5 |
+
{
|
6 |
+
return array(
|
7 |
+
"name" => "Product Deleter",
|
8 |
+
"author" => "Dweeves",
|
9 |
+
"version" => "0.0.2",
|
10 |
+
"url" => $this->pluginDocUrl("Product_Deleter")
|
11 |
+
);
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getPluginParamNames()
|
15 |
+
{
|
16 |
+
return array("PDEL:delsimples");
|
17 |
+
}
|
18 |
+
|
19 |
+
public function removeFromFlat($pid)
|
20 |
+
{
|
21 |
+
$this->log("Cleaning flat tables before reindex...","info");
|
22 |
+
$stmt=$this->exec_stmt("SHOW TABLES LIKE '".$this->tablename('catalog_product_flat')."%'",NULL,false);
|
23 |
+
while($row=$stmt->fetch(PDO::FETCH_NUM))
|
24 |
+
{
|
25 |
+
$tname=$row[0];
|
26 |
+
//removing records in flat tables that are no more linked to entries in catalog_product_entity table
|
27 |
+
//for some reasons, this seem to happen
|
28 |
+
$sql="DELETE cpf.* FROM $tname as cpf
|
29 |
+
WHERE cpf.entity_id=?";
|
30 |
+
$this->delete($sql,$pid);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
public function processItemAfterId(&$item,$params=null)
|
34 |
+
{
|
35 |
+
|
36 |
+
//get item ids, since we are before id
|
37 |
+
$pid=$params["product_id"];
|
38 |
+
if(isset($item["magmi:delete"]) && $item["magmi:delete"]==1)
|
39 |
+
{
|
40 |
+
$this->log("DELETING SKU '".$item["sku"]."' =>".$pid,"info");
|
41 |
+
//delete simple products if flag set
|
42 |
+
if($this->getParam("PDEL:delsimples",false)==true)
|
43 |
+
{
|
44 |
+
$childrensel="SELECT entity_id FROM ".$this->tablename("catalog_product_entity")." as cpe
|
45 |
+
JOIN ".$this->tablename("catalog_product_super_link")." as cpl ON cpl.parent_id=? AND cpe.entity_id=cpl.product_id";
|
46 |
+
$sql="DELETE cpe.* FROM ".$this->tablename("catalog_product_entity")." cpe WHERE cpe.entity_id IN (SELECT s1.entity_id FROM ($childrensel) as s1)";
|
47 |
+
|
48 |
+
$this->delete($sql,$pid);
|
49 |
+
}
|
50 |
+
//delete from indexes table if store is set
|
51 |
+
$this->removeFromFlat($pid);
|
52 |
+
|
53 |
+
//delete product (this cascades for all eav & relations)
|
54 |
+
$sql="DELETE FROM ".$this->tablename("catalog_product_entity")." WHERE entity_id=?";
|
55 |
+
$this->delete($sql,$pid);
|
56 |
+
$this->log($sql,"info");
|
57 |
+
$item=array();
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/related/related_products.php
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class RelatedProducts extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
|
5 |
+
public function getPluginInfo()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
"name" => "Product relater",
|
9 |
+
"author" => "Dweeves,jwtechniek",
|
10 |
+
"version" => "1.0.3",
|
11 |
+
"url"=>$this->pluginDocUrl("Product_relater")
|
12 |
+
);
|
13 |
+
}
|
14 |
+
|
15 |
+
|
16 |
+
public function checkRelated(&$rinfo)
|
17 |
+
{
|
18 |
+
if(count($rinfo["direct"])>0)
|
19 |
+
{
|
20 |
+
$sql="SELECT testid.sku,cpe.sku as esku FROM ".$this->arr2select($rinfo["direct"],"sku")." AS testid
|
21 |
+
LEFT JOIN ".$this->tablename("catalog_product_entity")." as cpe ON cpe.sku=testid.sku
|
22 |
+
WHERE testid.sku NOT LIKE '%re::%'
|
23 |
+
HAVING esku IS NULL";
|
24 |
+
$result=$this->selectAll($sql,$rinfo["direct"]);
|
25 |
+
|
26 |
+
$to_delete=array();
|
27 |
+
foreach($result as $row)
|
28 |
+
{
|
29 |
+
$this->log("Unknown related sku ".$row["sku"],"warning");
|
30 |
+
$to_delete[]=$row["sku"];
|
31 |
+
}
|
32 |
+
$rinfo["direct"]=array_diff($rinfo["direct"],$to_delete);
|
33 |
+
}
|
34 |
+
return count($rinfo["direct"])+count($rinfo["re"]);
|
35 |
+
|
36 |
+
}
|
37 |
+
|
38 |
+
public function processItemAfterId(&$item,$params=null)
|
39 |
+
{
|
40 |
+
$related=isset($item["re_skus"])?$item["re_skus"]:null;
|
41 |
+
$xrelated=isset($item["xre_skus"])?$item["xre_skus"]:null;
|
42 |
+
$srelated=isset($item["*re_skus"])?$item["*re_skus"]:null;
|
43 |
+
$pid=$params["product_id"];
|
44 |
+
$new=$params["new"];
|
45 |
+
|
46 |
+
if(isset($related) && trim($related)!="")
|
47 |
+
{
|
48 |
+
$rinf=$this->getRelInfos($related);
|
49 |
+
if($new==false)
|
50 |
+
{
|
51 |
+
$this->deleteRelatedItems($item,$rinf["del"]);
|
52 |
+
}
|
53 |
+
$this->setRelatedItems($item,$rinf["add"]);
|
54 |
+
}
|
55 |
+
if(isset($xrelated) && trim($xrelated)!="")
|
56 |
+
{
|
57 |
+
$rinf=$this->getRelInfos($xrelated);
|
58 |
+
if($new==false)
|
59 |
+
{
|
60 |
+
$this->deleteXRelatedItems($item,$rinf["del"]);
|
61 |
+
}
|
62 |
+
$this->setXRelatedItems($item,$rinf["add"]);
|
63 |
+
}
|
64 |
+
|
65 |
+
if(isset($srelated) && trim($srelated)!="")
|
66 |
+
{
|
67 |
+
$rinf=$this->getRelInfos($srelated);
|
68 |
+
if($new==false)
|
69 |
+
{
|
70 |
+
$this->deleteXRelatedItems($item,$rinf["del"],true);
|
71 |
+
}
|
72 |
+
$this->setXRelatedItems($item,$rinf["add"],true);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
public function deleteRelatedItems($item,$inf)
|
77 |
+
{
|
78 |
+
$joininfo=$this->buildJoinCond($item,$inf,"cpe2.sku");
|
79 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
80 |
+
if($j2!="")
|
81 |
+
{
|
82 |
+
$sql="DELETE cplai.*,cpl.*
|
83 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
84 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='relation'
|
85 |
+
JOIN ".$this->tablename("catalog_product_link")." as cpl ON cpl.product_id=cpe.entity_id AND cpl.link_type_id=cplt.link_type_id
|
86 |
+
JOIN ".$this->tablename("catalog_product_link_attribute_int")." as cplai ON cplai.link_id=cpl.link_id
|
87 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.sku!=cpe.sku AND $j2
|
88 |
+
|
89 |
+
WHERE cpe.sku=?";
|
90 |
+
$this->delete($sql,array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"])));
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
public function deleteXRelatedItems($item,$inf,$fullcross=false)
|
95 |
+
{
|
96 |
+
$joininfo=$this->buildJoinCond($item,$inf,"cpe2.sku,cpe.sku");
|
97 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
98 |
+
$j=$joininfo["join"]["cpe.sku"];
|
99 |
+
if($j2!="")
|
100 |
+
{
|
101 |
+
|
102 |
+
$sql="DELETE cplai.*,cpl.*
|
103 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
104 |
+
JOIN ".$this->tablename("catalog_product_link")." as cpl ON cpl.product_id=cpe.entity_id
|
105 |
+
JOIN ".$this->tablename("catalog_product_link_attribute_int")." as cplai ON cplai.link_id=cpl.link_id
|
106 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.sku!=cpe.sku AND (cpe2.sku=? OR $j2)
|
107 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='relation'
|
108 |
+
WHERE cpe.sku=? OR $j";
|
109 |
+
$this->delete($sql,array_merge(array($item["sku"]),$joininfo["data"]["cpe2.sku"],array($item["sku"]),$joininfo["data"]["cpe.sku"]));
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
public function getDirection(&$inf)
|
114 |
+
{
|
115 |
+
$dir="+";
|
116 |
+
if($inf[0]=="-" || $inf[0]=="+")
|
117 |
+
{
|
118 |
+
$dir=$inf[0];
|
119 |
+
$inf=substr($inf,1);
|
120 |
+
}
|
121 |
+
return $dir;
|
122 |
+
|
123 |
+
}
|
124 |
+
public function getRelInfos($relationdef)
|
125 |
+
{
|
126 |
+
$relinfos=explode(",",$relationdef);
|
127 |
+
$relskusadd=array("direct"=>array(),"re"=>array());
|
128 |
+
$relskusdel=array("direct"=>array(),"re"=>array());
|
129 |
+
foreach($relinfos as $relinfo)
|
130 |
+
{
|
131 |
+
$rinf=explode("::",$relinfo);
|
132 |
+
if(count($rinf)==1)
|
133 |
+
{
|
134 |
+
if($this->getDirection($rinf[0])=="+")
|
135 |
+
{
|
136 |
+
$relskusadd["direct"][]=$rinf[0];
|
137 |
+
}
|
138 |
+
else
|
139 |
+
{
|
140 |
+
$relskusdel["direct"][]=$rinf[0];
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
if(count($rinf)==2)
|
145 |
+
{
|
146 |
+
$dir=$this->getDirection($rinf[0]);
|
147 |
+
if($dir=="+")
|
148 |
+
{
|
149 |
+
switch($rinf[0])
|
150 |
+
{
|
151 |
+
case "re":
|
152 |
+
$relskusadd["re"][]=$rinf[1];
|
153 |
+
break;
|
154 |
+
}
|
155 |
+
}
|
156 |
+
else
|
157 |
+
{
|
158 |
+
switch($rinf[0])
|
159 |
+
{
|
160 |
+
case "re":
|
161 |
+
$relskusdel["re"][]=$rinf[1];
|
162 |
+
break;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
return array("add"=>$relskusadd,"del"=>$relskusdel);
|
169 |
+
}
|
170 |
+
|
171 |
+
public function buildJoinCond($item,$rinfo,$keys)
|
172 |
+
{
|
173 |
+
$joinconds=array();
|
174 |
+
$joins=array();
|
175 |
+
$klist=explode(",",$keys);
|
176 |
+
foreach($klist as $key)
|
177 |
+
{
|
178 |
+
$data[$key]=array();
|
179 |
+
$joinconds[$key]=array();
|
180 |
+
if(count($rinfo["direct"])>0)
|
181 |
+
{
|
182 |
+
$joinconds[$key][]="$key IN (".$this->arr2values($rinfo["direct"]).")";
|
183 |
+
$data[$key]=array_merge($data[$key],$rinfo["direct"]);
|
184 |
+
}
|
185 |
+
if(count($rinfo["re"])>0)
|
186 |
+
{
|
187 |
+
foreach($rinfo["re"] as $rinf)
|
188 |
+
{
|
189 |
+
$joinconds[$key][]="$key REGEXP ?";
|
190 |
+
$data[$key][]=$rinf;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
$joins[$key] = implode(" OR ",$joinconds[$key]);
|
194 |
+
if($joins[$key]!="")
|
195 |
+
{
|
196 |
+
$joins[$key]="({$joins[$key]})";
|
197 |
+
}
|
198 |
+
|
199 |
+
}
|
200 |
+
return array("join"=>$joins,"data"=>$data);
|
201 |
+
}
|
202 |
+
|
203 |
+
|
204 |
+
public function setRelatedItems($item,$rinfo)
|
205 |
+
{
|
206 |
+
if($this->checkRelated($rinfo)>0)
|
207 |
+
|
208 |
+
{
|
209 |
+
$joininfo=$this->buildJoinCond($item,$rinfo,"cpe2.sku");
|
210 |
+
$jinf=$joininfo["join"]["cpe2.sku"];
|
211 |
+
if($jinf!="")
|
212 |
+
{
|
213 |
+
//insert into link table
|
214 |
+
$bsql="SELECT cplt.link_type_id,cpe.entity_id as product_id,cpe2.entity_id as linked_product_id
|
215 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
216 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.sku!=cpe.sku AND $jinf
|
217 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='relation'
|
218 |
+
WHERE cpe.sku=?";
|
219 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link")." (link_type_id,product_id,linked_product_id) $bsql";
|
220 |
+
$data=array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"]));
|
221 |
+
$this->insert($sql,$data);
|
222 |
+
$this->updateLinkAttributeTable($item["sku"],$joininfo);
|
223 |
+
}
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
public function setXRelatedItems($item,$rinfo,$fullrel=false)
|
228 |
+
{
|
229 |
+
if($this->checkRelated($rinfo)>0)
|
230 |
+
{
|
231 |
+
$joininfo=$this->buildJoinCond($item,$rinfo,"cpe.sku,cpe2.sku");
|
232 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
233 |
+
$j=$joininfo["join"]["cpe.sku"];
|
234 |
+
if($j2!="")
|
235 |
+
{
|
236 |
+
//insert into link table
|
237 |
+
$bsql="SELECT cplt.link_type_id,cpe.entity_id as product_id,cpe2.entity_id as linked_product_id
|
238 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
239 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.entity_id!=cpe.entity_id AND (cpe2.sku=? OR $j2)
|
240 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='relation'
|
241 |
+
WHERE cpe.sku=? OR $j ";
|
242 |
+
if(!$fullrel)
|
243 |
+
{
|
244 |
+
$bsql.=" AND NOT($j AND $j2)";
|
245 |
+
}
|
246 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link")." (link_type_id,product_id,linked_product_id) $bsql";
|
247 |
+
$data=array_merge(array($item["sku"]),$joininfo["data"]["cpe2.sku"],array($item["sku"]),$joininfo["data"]["cpe.sku"]);
|
248 |
+
if(!$fullrel)
|
249 |
+
{
|
250 |
+
$data=array_merge($data,$joininfo["data"]["cpe.sku"],$joininfo["data"]["cpe.sku"]);
|
251 |
+
}
|
252 |
+
$this->insert($sql,$data);
|
253 |
+
$this->updateLinkAttributeTable($item["sku"],$joininfo);
|
254 |
+
}
|
255 |
+
}
|
256 |
+
}
|
257 |
+
|
258 |
+
public function updateLinkAttributeTable($sku,$joininfo)
|
259 |
+
{
|
260 |
+
//insert into attribute link attribute int table,reusing the same relations
|
261 |
+
$ji=$joininfo["join"];
|
262 |
+
$data=array($sku);
|
263 |
+
$addcond="";
|
264 |
+
if(isset($ji["cpe.sku"]))
|
265 |
+
{
|
266 |
+
$addcond="OR ".$joininfo["join"]["cpe.sku"];
|
267 |
+
$data=array_merge($data,$joininfo["data"]["cpe.sku"]);
|
268 |
+
}
|
269 |
+
//this enable to mass add
|
270 |
+
$bsql="SELECT cpl.link_id,cpla.product_link_attribute_id,0 as value
|
271 |
+
FROM ".$this->tablename("catalog_product_entity")." AS cpe
|
272 |
+
JOIN ".$this->tablename("catalog_product_entity")." AS cpe2 ON cpe2.entity_id!=cpe.entity_id
|
273 |
+
JOIN ".$this->tablename("catalog_product_link_type")." AS cplt ON cplt.code='relation'
|
274 |
+
JOIN ".$this->tablename("catalog_product_link_attribute")." AS cpla ON cpla.product_link_attribute_code='position' AND cpla.link_type_id=cplt.link_type_id
|
275 |
+
JOIN ".$this->tablename("catalog_product_link") ." AS cpl ON cpl.link_type_id=cplt.link_type_id AND cpl.product_id=cpe.entity_id AND cpl.linked_product_id=cpe2.entity_id
|
276 |
+
WHERE cpe.sku=? $addcond";
|
277 |
+
|
278 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link_attribute_int")." (link_id,product_link_attribute_id,value) $bsql";
|
279 |
+
$this->insert($sql,$data);
|
280 |
+
}
|
281 |
+
|
282 |
+
public function afterImport()
|
283 |
+
{
|
284 |
+
//remove maybe inserted doubles
|
285 |
+
$cplai=$this->tablename("catalog_product_link_attribute_int");
|
286 |
+
$sql="DELETE cplaix FROM $cplai as cplaix
|
287 |
+
WHERE cplaix.value_id IN
|
288 |
+
(SELECT s1.value_id FROM
|
289 |
+
(SELECT cplai.link_id,cplai.value_id,MAX(cplai.value_id) as latest
|
290 |
+
FROM $cplai as cplai
|
291 |
+
GROUP BY cplai.link_id
|
292 |
+
HAVING cplai.value_id!=latest)
|
293 |
+
as s1)";
|
294 |
+
$this->delete($sql);
|
295 |
+
}
|
296 |
+
|
297 |
+
static public function getCategory()
|
298 |
+
{
|
299 |
+
return "Related Products";
|
300 |
+
}
|
301 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/skufinder/001_skufinder.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class SkuFinderItemProcessor extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
private $_compchecked=FALSE;
|
5 |
+
|
6 |
+
public function getPluginInfo()
|
7 |
+
{
|
8 |
+
return array(
|
9 |
+
"name" => "SKU Finder",
|
10 |
+
"author" => "Dweeves",
|
11 |
+
"version" => "0.0.1",
|
12 |
+
"url"=>$this->pluginDocUrl("SKU_Finder")
|
13 |
+
);
|
14 |
+
}
|
15 |
+
|
16 |
+
public function processItemBeforeId(&$item,$params=null)
|
17 |
+
{
|
18 |
+
|
19 |
+
$matchfield=trim($this->getParam("SKUF:matchfield"));
|
20 |
+
//protection from tricky testers ;)
|
21 |
+
if($matchfield=="sku")
|
22 |
+
{
|
23 |
+
return true;
|
24 |
+
}
|
25 |
+
$attinfo=$this->getAttrInfo($matchfield);
|
26 |
+
if($this->_compchecked==FALSE)
|
27 |
+
{
|
28 |
+
//Checking attribute compatibility with sku matching
|
29 |
+
if($attinfo==NULL)
|
30 |
+
{
|
31 |
+
$this->log("$matchfield is not a valid attribute","error");
|
32 |
+
$item["__MAGMI_LAST__"]=1;
|
33 |
+
return false;
|
34 |
+
}
|
35 |
+
if($attinfo["is_unique"]==0 || $attinfo["is_global"]==0)
|
36 |
+
{
|
37 |
+
$this->log("sku matching attribute $matchfield must be unique & global scope");
|
38 |
+
$item["__MAGMI_LAST__"]=1;
|
39 |
+
return false;
|
40 |
+
}
|
41 |
+
if($attinfo["backend_type"]=="static")
|
42 |
+
{
|
43 |
+
$this->log("$matchfield is ".$attinfo["backend_type"].", it cannot be used as sku matching field.","error");
|
44 |
+
$item["__MAGMI_LAST__"]=1;
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
if($attinfo["frontend_input"]=="select" || $attinfo["frontend_input"]=="multiselect" )
|
48 |
+
{
|
49 |
+
$this->log("$matchfield is ".$attinfo["frontend_input"].", it cannot be used as sku matching field.","error");
|
50 |
+
$item["__MAGMI_LAST__"]=1;
|
51 |
+
return false;
|
52 |
+
}
|
53 |
+
$this->_compchecked=true;
|
54 |
+
}
|
55 |
+
|
56 |
+
//no item data for selected matching field, skipping
|
57 |
+
if(!isset($item[$matchfield]) && trim($item["matchfield"])!=='')
|
58 |
+
{
|
59 |
+
$this->log("No value for $matchfield in datasource","error");
|
60 |
+
return false;
|
61 |
+
}
|
62 |
+
//now find sku
|
63 |
+
$sql="SELECT sku FROM ".$this->tablename("catalog_product_entity")." as cpe JOIN
|
64 |
+
catalog_product_entity_".$attinfo["backend_type"]. "ON value=? AND attribute_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 |
+
}
|
lib/Magmi/plugins/base/itemprocessors/skufinder/options_panel.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="plugin_description">
|
2 |
+
This plugins can be used in <b>update</b> mode to find sku from custom column in datasource.
|
3 |
+
this column <b>MUST</b> be an attribute code
|
4 |
+
</div>
|
5 |
+
<ul class="formline">
|
6 |
+
<li class="label">
|
7 |
+
<span>sku find attribute code</span>
|
8 |
+
</li>
|
9 |
+
<li class="value">
|
10 |
+
<input type="text" name="SKUF:matchfield" value="<?php $this->getParam("SKUF:matchfield","")?>">
|
11 |
+
</li>
|
12 |
+
|
13 |
+
</ul>
|
lib/Magmi/plugins/base/itemprocessors/upcross_sell/crossupsell_products.php
ADDED
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class CrossUpsellProducts extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
|
5 |
+
public function getPluginInfo()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
"name" => "Cross/Upsell Importer",
|
9 |
+
"author" => "Dweeves",
|
10 |
+
"version" => "1.0.3",
|
11 |
+
"url"=>$this->pluginDocUrl("Cross/Upsell_Importer")
|
12 |
+
);
|
13 |
+
}
|
14 |
+
|
15 |
+
public function checkRelated(&$rinfo)
|
16 |
+
{
|
17 |
+
if(count($rinfo["direct"])>0)
|
18 |
+
{
|
19 |
+
$sql="SELECT testid.sku,cpe.sku as esku FROM ".$this->arr2select($rinfo["direct"],"sku")." AS testid
|
20 |
+
LEFT JOIN ".$this->tablename("catalog_product_entity")." as cpe ON cpe.sku=testid.sku
|
21 |
+
WHERE testid.sku NOT LIKE '%re::%'
|
22 |
+
HAVING esku IS NULL";
|
23 |
+
$result=$this->selectAll($sql,$rinfo["direct"]);
|
24 |
+
|
25 |
+
$to_delete=array();
|
26 |
+
foreach($result as $row)
|
27 |
+
{
|
28 |
+
$this->log("Unknown related sku ".$row["sku"],"warning");
|
29 |
+
$to_delete[]=$row["sku"];
|
30 |
+
}
|
31 |
+
$rinfo["direct"]=array_diff($rinfo["direct"],$to_delete);
|
32 |
+
}
|
33 |
+
return count($rinfo["direct"])+count($rinfo["re"]);
|
34 |
+
}
|
35 |
+
|
36 |
+
public function processItemAfterId(&$item,$params=null)
|
37 |
+
{
|
38 |
+
$usell=isset($item["us_skus"])?$item["us_skus"]:null;
|
39 |
+
$csell=isset($item["cs_skus"])?$item["cs_skus"]:null;
|
40 |
+
$pid=$params["product_id"];
|
41 |
+
$new=$params["new"];
|
42 |
+
|
43 |
+
if(isset($usell) && trim($usell)!="")
|
44 |
+
{
|
45 |
+
$rinf=$this->getRelInfos($usell);
|
46 |
+
if($new==false)
|
47 |
+
{
|
48 |
+
$this->deleteUsellItems($item,$rinf["del"]);
|
49 |
+
}
|
50 |
+
$this->setUsellItems($item,$rinf["add"]);
|
51 |
+
}
|
52 |
+
if(isset($csell) && trim($csell)!="")
|
53 |
+
{
|
54 |
+
$rinf=$this->getRelInfos($csell);
|
55 |
+
if($new==false)
|
56 |
+
{
|
57 |
+
$this->deleteCSellItems($item,$rinf["del"]);
|
58 |
+
}
|
59 |
+
$this->setCSellItems($item,$rinf["add"]);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
public function deleteUSellItems($item,$inf)
|
64 |
+
{
|
65 |
+
$joininfo=$this->buildJoinCond($item,$inf,"cpe2.sku");
|
66 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
67 |
+
if($j2!="")
|
68 |
+
{
|
69 |
+
$sql="DELETE cplai.*,cpl.*
|
70 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
71 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='up_sell'
|
72 |
+
JOIN ".$this->tablename("catalog_product_link")." as cpl ON cpl.product_id=cpe.entity_id AND cpl.link_type_id=cplt.link_type_id
|
73 |
+
JOIN ".$this->tablename("catalog_product_link_attribute_int")." as cplai ON cplai.link_id=cpl.link_id
|
74 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.entity_id!=cpe.entity_id AND $j2
|
75 |
+
WHERE cpe.sku=?";
|
76 |
+
$this->delete($sql,array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"])));
|
77 |
+
}
|
78 |
+
}
|
79 |
+
|
80 |
+
public function deleteCSellItems($item,$inf)
|
81 |
+
{
|
82 |
+
$joininfo=$this->buildJoinCond($item,$inf,"cpe2.sku");
|
83 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
84 |
+
if($j2!="")
|
85 |
+
{
|
86 |
+
|
87 |
+
$sql="DELETE cplai.*,cpl.*
|
88 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
89 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='cross_sell'
|
90 |
+
JOIN ".$this->tablename("catalog_product_link")." as cpl ON cpl.product_id=cpe.entity_id AND cpl.link_type_id=cplt.link_type_id
|
91 |
+
JOIN ".$this->tablename("catalog_product_link_attribute_int")." as cplai ON cplai.link_id=cpl.link_id
|
92 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.entity_id!=cpe.entity_id AND $j2
|
93 |
+
WHERE cpe.sku=?";
|
94 |
+
$this->delete($sql,array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"])));
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
public function getDirection(&$inf)
|
99 |
+
{
|
100 |
+
$dir="+";
|
101 |
+
if($inf[0]=="-" || $inf[0]=="+")
|
102 |
+
{
|
103 |
+
$dir=$inf[0];
|
104 |
+
$inf=substr($inf,1);
|
105 |
+
}
|
106 |
+
return $dir;
|
107 |
+
|
108 |
+
}
|
109 |
+
public function getRelInfos($relationdef)
|
110 |
+
{
|
111 |
+
$relinfos=explode(",",$relationdef);
|
112 |
+
$relskusadd=array("direct"=>array(),"re"=>array());
|
113 |
+
$relskusdel=array("direct"=>array(),"re"=>array());
|
114 |
+
foreach($relinfos as $relinfo)
|
115 |
+
{
|
116 |
+
$rinf=explode("::",$relinfo);
|
117 |
+
if(count($rinf)==1)
|
118 |
+
{
|
119 |
+
if($this->getDirection($rinf[0])=="+")
|
120 |
+
{
|
121 |
+
$relskusadd["direct"][]=$rinf[0];
|
122 |
+
}
|
123 |
+
else
|
124 |
+
{
|
125 |
+
$relskusdel["direct"][]=$rinf[0];
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
if(count($rinf)==2)
|
130 |
+
{
|
131 |
+
$dir=$this->getDirection($rinf[0]);
|
132 |
+
if($dir=="+")
|
133 |
+
{
|
134 |
+
switch($rinf[0])
|
135 |
+
{
|
136 |
+
case "re":
|
137 |
+
$relskusadd["re"][]=$rinf[1];
|
138 |
+
break;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
else
|
142 |
+
{
|
143 |
+
switch($rinf[0])
|
144 |
+
{
|
145 |
+
case "re":
|
146 |
+
$relskusdel["re"][]=$rinf[1];
|
147 |
+
break;
|
148 |
+
}
|
149 |
+
}
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
return array("add"=>$relskusadd,"del"=>$relskusdel);
|
154 |
+
}
|
155 |
+
|
156 |
+
public function buildJoinCond($item,$rinfo,$keys)
|
157 |
+
{
|
158 |
+
$joinconds=array();
|
159 |
+
$joins=array();
|
160 |
+
$klist=explode(",",$keys);
|
161 |
+
foreach($klist as $key)
|
162 |
+
{
|
163 |
+
$data[$key]=array();
|
164 |
+
$joinconds[$key]=array();
|
165 |
+
if(count($rinfo["direct"])>0)
|
166 |
+
{
|
167 |
+
$joinconds[$key][]="$key IN (".$this->arr2values($rinfo["direct"]).")";
|
168 |
+
$data[$key]=array_merge($data[$key],$rinfo["direct"]);
|
169 |
+
}
|
170 |
+
if(count($rinfo["re"])>0)
|
171 |
+
{
|
172 |
+
foreach($rinfo["re"] as $rinf)
|
173 |
+
{
|
174 |
+
if($rinf!=".*")
|
175 |
+
{
|
176 |
+
$joinconds[$key][]="$key REGEXP ?";
|
177 |
+
$data[$key][]=$rinf;
|
178 |
+
}
|
179 |
+
else
|
180 |
+
{
|
181 |
+
$joinconds[$key][]="?";
|
182 |
+
$data[$key][]=1;
|
183 |
+
|
184 |
+
}
|
185 |
+
}
|
186 |
+
}
|
187 |
+
$joins[$key] = implode(" OR ",$joinconds[$key]);
|
188 |
+
if($joins[$key]!="")
|
189 |
+
{
|
190 |
+
$joins[$key]="({$joins[$key]})";
|
191 |
+
}
|
192 |
+
|
193 |
+
}
|
194 |
+
return array("join"=>$joins,"data"=>$data);
|
195 |
+
}
|
196 |
+
|
197 |
+
|
198 |
+
public function setUSellItems($item,$rinfo)
|
199 |
+
{
|
200 |
+
if($this->checkRelated($rinfo)>0)
|
201 |
+
|
202 |
+
{
|
203 |
+
$joininfo=$this->buildJoinCond($item,$rinfo,"cpe2.sku");
|
204 |
+
$jinf=$joininfo["join"]["cpe2.sku"];
|
205 |
+
if($jinf!="")
|
206 |
+
{
|
207 |
+
//insert into link table
|
208 |
+
$bsql="SELECT cplt.link_type_id,cpe.entity_id as product_id,cpe2.entity_id as linked_product_id
|
209 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
210 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.entity_id!=cpe.entity_id AND $jinf
|
211 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='up_sell'
|
212 |
+
WHERE cpe.sku=?";
|
213 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link")." (link_type_id,product_id,linked_product_id) $bsql";
|
214 |
+
$data=array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"]));
|
215 |
+
$this->insert($sql,$data);
|
216 |
+
$this->updateLinkAttributeTable($item["sku"],$joininfo,'up_sell');
|
217 |
+
}
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
public function setCSellItems($item,$rinfo)
|
222 |
+
{
|
223 |
+
if($this->checkRelated($rinfo)>0)
|
224 |
+
|
225 |
+
{
|
226 |
+
$joininfo=$this->buildJoinCond($item,$rinfo,"cpe2.sku");
|
227 |
+
$j2=$joininfo["join"]["cpe2.sku"];
|
228 |
+
if($j2!="")
|
229 |
+
{
|
230 |
+
//insert into link table
|
231 |
+
$bsql="SELECT cplt.link_type_id,cpe.entity_id as product_id,cpe2.entity_id as linked_product_id
|
232 |
+
FROM ".$this->tablename("catalog_product_entity")." as cpe
|
233 |
+
JOIN ".$this->tablename("catalog_product_entity")." as cpe2 ON cpe2.entity_id!=cpe.entity_id AND $j2
|
234 |
+
JOIN ".$this->tablename("catalog_product_link_type")." as cplt ON cplt.code='cross_sell'
|
235 |
+
WHERE cpe.sku=?";
|
236 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link")." (link_type_id,product_id,linked_product_id) $bsql";
|
237 |
+
$data=array_merge($joininfo["data"]["cpe2.sku"],array($item["sku"]));
|
238 |
+
$this->insert($sql,$data);
|
239 |
+
$this->updateLinkAttributeTable($item["sku"],$joininfo,'cross_sell');
|
240 |
+
}
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
public function updateLinkAttributeTable($sku,$joininfo,$reltype)
|
245 |
+
{
|
246 |
+
//insert into attribute link attribute int table,reusing the same relations
|
247 |
+
//this enable to mass add
|
248 |
+
$bsql="SELECT cpl.link_id,cpla.product_link_attribute_id,0 as value
|
249 |
+
FROM ".$this->tablename("catalog_product_entity")." AS cpe
|
250 |
+
JOIN ".$this->tablename("catalog_product_entity")." AS cpe2 ON cpe2.entity_id!=cpe.entity_id
|
251 |
+
JOIN ".$this->tablename("catalog_product_link_type")." AS cplt ON cplt.code=?
|
252 |
+
JOIN ".$this->tablename("catalog_product_link_attribute")." AS cpla ON cpla.product_link_attribute_code='position' AND cpla.link_type_id=cplt.link_type_id
|
253 |
+
JOIN ".$this->tablename("catalog_product_link") ." AS cpl ON cpl.link_type_id=cplt.link_type_id AND cpl.product_id=cpe.entity_id AND cpl.linked_product_id=cpe2.entity_id
|
254 |
+
WHERE cpe.sku=?";
|
255 |
+
$sql="INSERT IGNORE INTO ".$this->tablename("catalog_product_link_attribute_int")." (link_id,product_link_attribute_id,value) $bsql";
|
256 |
+
$this->insert($sql,array($reltype,$sku));
|
257 |
+
|
258 |
+
}
|
259 |
+
|
260 |
+
public function afterImport()
|
261 |
+
{
|
262 |
+
//remove maybe inserted doubles
|
263 |
+
$cplai=$this->tablename("catalog_product_link_attribute_int");
|
264 |
+
$sql="DELETE cplaix FROM $cplai as cplaix
|
265 |
+
WHERE cplaix.value_id IN
|
266 |
+
(SELECT s1.value_id FROM
|
267 |
+
(SELECT cplai.link_id,cplai.value_id,MAX(cplai.value_id) as latest
|
268 |
+
FROM $cplai as cplai
|
269 |
+
GROUP BY cplai.link_id
|
270 |
+
HAVING cplai.value_id!=latest)
|
271 |
+
as s1)";
|
272 |
+
$this->delete($sql);
|
273 |
+
}
|
274 |
+
|
275 |
+
static public function getCategory()
|
276 |
+
{
|
277 |
+
return "Related Products";
|
278 |
+
}
|
279 |
+
}
|
lib/Magmi/plugins/inc/magmi_datasource.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
abstract class Magmi_DataSource extends Magmi_GeneralImportPlugin
|
10 |
+
{
|
11 |
+
|
12 |
+
public function getColumnNames($prescan=false)
|
13 |
+
{
|
14 |
+
|
15 |
+
}
|
16 |
+
public function getRecordsCount()
|
17 |
+
{
|
18 |
+
|
19 |
+
}
|
20 |
+
|
21 |
+
public function getNextRecord()
|
22 |
+
{
|
23 |
+
|
24 |
+
}
|
25 |
+
|
26 |
+
public function onException($e)
|
27 |
+
{
|
28 |
+
|
29 |
+
}
|
30 |
+
}
|
lib/Magmi/plugins/inc/magmi_default_options_panel.php
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<span>Plugin has no configurable parameters</span>
|
lib/Magmi/plugins/inc/magmi_defaultattributehandler.php
ADDED
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_DefaultAttributeItemProcessor extends Magmi_ItemProcessor
|
3 |
+
{
|
4 |
+
protected $_basecols=array("store"=>"admin","type"=>"simple");
|
5 |
+
protected $_baseattrs=array("status"=>1,"visibility"=>4,"page_layout"=>"");
|
6 |
+
protected $_forcedefault=array("store"=>"admin");
|
7 |
+
protected $_missingcols=array();
|
8 |
+
protected $_missingattrs=array();
|
9 |
+
|
10 |
+
public function initialize($params)
|
11 |
+
{
|
12 |
+
$this->registerAttributeHandler($this,array("attribute_code:.*"));
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getPluginInfo()
|
16 |
+
{
|
17 |
+
return array(
|
18 |
+
"name" => "Standard Attribute Import",
|
19 |
+
"author" => "Dweeves",
|
20 |
+
"version" => "1.0.5"
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
public function processColumnList(&$cols)
|
25 |
+
{
|
26 |
+
$this->_missingcols=array_diff(array_keys($this->_basecols),$cols);
|
27 |
+
$this->_missingattrs=array_diff(array_keys($this->_baseattrs),$cols);
|
28 |
+
$m=$this->getMode();
|
29 |
+
if($m=="create" || $m=="xcreate")
|
30 |
+
{
|
31 |
+
$cols=array_merge($cols,$this->_missingcols,$this->_missingattrs);
|
32 |
+
$this->log("Newly created items will have default values for columns:".implode(",",array_merge($this->_missingcols,$this->_missingattrs)),"startup");
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
|
37 |
+
public function initializeBaseCols(&$item)
|
38 |
+
{
|
39 |
+
foreach($this->_missingcols as $missing)
|
40 |
+
{
|
41 |
+
$item[$missing]=$this->_basecols[$missing];
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
public function initializeBaseAttrs(&$item)
|
46 |
+
{
|
47 |
+
foreach($this->_missingattrs as $missing)
|
48 |
+
{
|
49 |
+
$item[$missing]=$this->_baseattrs[$missing];
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
+
|
55 |
+
public function processItemAfterId(&$item,$params=null)
|
56 |
+
{
|
57 |
+
if($params["new"]==true)
|
58 |
+
{
|
59 |
+
$this->initializeBaseCols($item);
|
60 |
+
$this->initializeBaseAttrs($item);
|
61 |
+
}
|
62 |
+
//forcing default values for mandatory processing columns
|
63 |
+
foreach($this->_forcedefault as $k=>$v)
|
64 |
+
{
|
65 |
+
if(isset($item[$k]) && trim($item[$k])=="")
|
66 |
+
{
|
67 |
+
$item[$k]=$v;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
return true;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* attribute handler for decimal attributes
|
75 |
+
* @param int $pid : product id
|
76 |
+
* @param int $ivalue : initial value of attribute
|
77 |
+
* @param array $attrdesc : attribute description
|
78 |
+
* @return mixed : false if no further processing is needed,
|
79 |
+
* string (magento value) for the decimal attribute otherwise
|
80 |
+
*/
|
81 |
+
public function handleDecimalAttribute($pid,&$item,$storeid,$attrcode,$attrdesc,$ivalue)
|
82 |
+
{
|
83 |
+
//force convert decimal separator to dot
|
84 |
+
$ivalue=str_replace(",",".",$ivalue);
|
85 |
+
$ovalue=deleteifempty($ivalue);
|
86 |
+
return $ovalue;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* attribute handler for datetime attributes
|
91 |
+
* @param int $pid : product id
|
92 |
+
* @param int $ivalue : initial value of attribute
|
93 |
+
* @param array $attrdesc : attribute description
|
94 |
+
* @return mixed : false if no further processing is needed,
|
95 |
+
* string (magento value) for the datetime attribute otherwise
|
96 |
+
*/
|
97 |
+
public function handleDatetimeAttribute($pid,&$item,$storeid,$attrcode,$attrdesc,$ivalue)
|
98 |
+
{
|
99 |
+
$ovalue=deleteifempty(trim($ivalue));
|
100 |
+
//Handle european date format or other common separators
|
101 |
+
if(preg_match("|([0-9]){1,2}\D([0-9]){1,2}\D([0-9]){4}|",$ovalue,$matches))
|
102 |
+
{
|
103 |
+
$ovalue=sprintf("%4d-%2d-%2d",$matches[3],$matches[2],$matches[1]);
|
104 |
+
}
|
105 |
+
return $ovalue;
|
106 |
+
}
|
107 |
+
|
108 |
+
public function handleTextAttribute($pid,&$item,$storeid,$attrcode,$attrdesc,$ivalue)
|
109 |
+
{
|
110 |
+
$ovalue=(empty($ivalue)?'':$ivalue);
|
111 |
+
return $ovalue;
|
112 |
+
}
|
113 |
+
|
114 |
+
public function checkInt($value)
|
115 |
+
{
|
116 |
+
return is_int($value) || (is_string($value) && is_numeric($value) && (int)$value==$value);
|
117 |
+
}
|
118 |
+
/**
|
119 |
+
* attribute handler for int typed attributes
|
120 |
+
* @param int $pid : product id
|
121 |
+
* @param int $ivalue : initial value of attribute
|
122 |
+
* @param array $attrdesc : attribute description
|
123 |
+
* @return mixed : false if no further processing is needed,
|
124 |
+
* int (magento value) for the int attribute otherwise
|
125 |
+
*/
|
126 |
+
public function handleIntAttribute($pid,&$item,$storeid,$attrcode,$attrdesc,$ivalue)
|
127 |
+
{
|
128 |
+
$ovalue=$ivalue;
|
129 |
+
$attid=$attrdesc["attribute_id"];
|
130 |
+
//if we've got a select type value
|
131 |
+
if($attrdesc["frontend_input"]=="select")
|
132 |
+
{
|
133 |
+
//we need to identify its type since some have no options
|
134 |
+
switch($attrdesc["source_model"])
|
135 |
+
{
|
136 |
+
//if its status, default to 1 (Enabled) if not correcly mapped
|
137 |
+
case "catalog/product_status":
|
138 |
+
if(!$this->checkInt($ivalue) ){
|
139 |
+
$ovalue=1;
|
140 |
+
}
|
141 |
+
break;
|
142 |
+
//do not create options for boolean values tagged as select ,default to 0 if not correcly mapped
|
143 |
+
case "eav/entity_attribute_source_boolean":
|
144 |
+
if(!$this->checkInt($ivalue)){
|
145 |
+
$ovalue=0;
|
146 |
+
}
|
147 |
+
break;
|
148 |
+
//if visibility no options either,default to 4 if not correctly mapped
|
149 |
+
case "catalog/product_visibility":
|
150 |
+
if(!$this->checkInt($ivalue)){
|
151 |
+
$ovalue=4;
|
152 |
+
}
|
153 |
+
|
154 |
+
break;
|
155 |
+
//if it's tax_class, get tax class id from item value
|
156 |
+
case "tax/class_source_product":
|
157 |
+
$ovalue=$this->getTaxClassId($ivalue);
|
158 |
+
break;
|
159 |
+
//otherwise, standard option behavior
|
160 |
+
//get option id for value, create it if does not already exist
|
161 |
+
//do not insert if empty
|
162 |
+
default:
|
163 |
+
if($ivalue=="" && $this->getMode()=="update")
|
164 |
+
{
|
165 |
+
return "__MAGMI_DELETE__";
|
166 |
+
}
|
167 |
+
$oids=$this->getOptionIds($attid,$storeid,array($ivalue));
|
168 |
+
$ovalue=$oids[0];
|
169 |
+
unset($oids);
|
170 |
+
break;
|
171 |
+
}
|
172 |
+
}
|
173 |
+
return $ovalue;
|
174 |
+
}
|
175 |
+
|
176 |
+
|
177 |
+
/**
|
178 |
+
* attribute handler for varchar based attributes
|
179 |
+
* @param int $pid : product id
|
180 |
+
* @param string $ivalue : attribute value
|
181 |
+
* @param array $attrdesc : attribute description
|
182 |
+
*/
|
183 |
+
public function handleVarcharAttribute($pid,&$item,$storeid,$attrcode,$attrdesc,$ivalue)
|
184 |
+
{
|
185 |
+
|
186 |
+
if($storeid!==0 && empty($ivalue) && $this->getImportMode()=="create")
|
187 |
+
{
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
if($ivalue=="" && $this->getImportMode()=="update")
|
191 |
+
{
|
192 |
+
return "__MAGMI_DELETE__";
|
193 |
+
}
|
194 |
+
|
195 |
+
$ovalue=$ivalue;
|
196 |
+
$attid=$attrdesc["attribute_id"];
|
197 |
+
//--- Contribution From mennos , optimized by dweeves ----
|
198 |
+
//Added to support multiple select attributes
|
199 |
+
//(as far as i could figure out) always stored as varchars
|
200 |
+
//if it's a multiselect value
|
201 |
+
if($attrdesc["frontend_input"]=="multiselect")
|
202 |
+
{
|
203 |
+
//if empty delete entry
|
204 |
+
if($ivalue=="")
|
205 |
+
{
|
206 |
+
return "__MAGMI_DELETE__";
|
207 |
+
}
|
208 |
+
//magento uses "," as separator for different multiselect values
|
209 |
+
$sep=Magmi_Config::getInstance()->get("GLOBAL","multiselect_sep",",");
|
210 |
+
$multiselectvalues=explode($sep,$ivalue);
|
211 |
+
$oids=$this->getOptionIds($attid,$storeid,$multiselectvalues);
|
212 |
+
$ovalue=implode(",",$oids);
|
213 |
+
unset($oids);
|
214 |
+
}
|
215 |
+
return $ovalue;
|
216 |
+
}
|
217 |
+
|
218 |
+
}
|
lib/Magmi/plugins/inc/magmi_generalimport_plugin.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_plugin.php");
|
3 |
+
abstract class Magmi_GeneralImportPlugin extends Magmi_Plugin
|
4 |
+
{
|
5 |
+
public function beforeImport()
|
6 |
+
{
|
7 |
+
return true;
|
8 |
+
}
|
9 |
+
|
10 |
+
public function afterImport()
|
11 |
+
{
|
12 |
+
return true;
|
13 |
+
}
|
14 |
+
|
15 |
+
}
|
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 |
+
}
|
lib/Magmi/plugins/inc/magmi_plugin.php
ADDED
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
require_once("magmi_config.php");
|
3 |
+
require_once("magmi_mixin.php");
|
4 |
+
class Magmi_PluginConfig extends ProfileBasedConfig
|
5 |
+
{
|
6 |
+
protected $_prefix;
|
7 |
+
protected $_conffile;
|
8 |
+
public function __construct($pname,$profile=null)
|
9 |
+
{
|
10 |
+
$this->_prefix=$pname;
|
11 |
+
parent::__construct("$this->_prefix.conf",$profile);
|
12 |
+
}
|
13 |
+
|
14 |
+
public function getConfDir()
|
15 |
+
{
|
16 |
+
return dirname($this->_confname);
|
17 |
+
}
|
18 |
+
|
19 |
+
public function load($name=null)
|
20 |
+
{
|
21 |
+
$cname=($name==null?$this->_confname:$name);
|
22 |
+
if(file_exists($cname))
|
23 |
+
{
|
24 |
+
parent::load($cname);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getIniStruct($arr)
|
29 |
+
{
|
30 |
+
$conf=array();
|
31 |
+
foreach($arr as $k=>$v)
|
32 |
+
{
|
33 |
+
$k=$this->_prefix.":".$k;
|
34 |
+
list($section,$value)=explode(":",$k,2);
|
35 |
+
if(!isset($conf[$section]))
|
36 |
+
{
|
37 |
+
$conf[$section]=array();
|
38 |
+
}
|
39 |
+
$conf[$section][$value]=$v;
|
40 |
+
}
|
41 |
+
return $conf;
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
public function getConfig()
|
46 |
+
{
|
47 |
+
return parent::getsection($this->_prefix);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
class Magmi_PluginOptionsPanel
|
52 |
+
{
|
53 |
+
private $_plugin;
|
54 |
+
private $_defaulthtml="";
|
55 |
+
private $_file=null;
|
56 |
+
public function __construct($pinst,$file=null)
|
57 |
+
{
|
58 |
+
$this->_plugin=$pinst;
|
59 |
+
$this->_file=($file==null?"options_panel.php":$file);
|
60 |
+
$this->initDefaultHtml();
|
61 |
+
|
62 |
+
}
|
63 |
+
|
64 |
+
public function getFile()
|
65 |
+
{
|
66 |
+
return $this->_file;
|
67 |
+
}
|
68 |
+
|
69 |
+
public final function initDefaultHtml()
|
70 |
+
{
|
71 |
+
$panelfile=dirname(__FILE__)."/magmi_default_options_panel.php";
|
72 |
+
ob_start();
|
73 |
+
require($panelfile);
|
74 |
+
$this->_defaulthtml = ob_get_contents();
|
75 |
+
ob_end_clean();
|
76 |
+
|
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 |
+
public function __construct()
|
114 |
+
{
|
115 |
+
}
|
116 |
+
|
117 |
+
public function pluginDocUrl($urlk)
|
118 |
+
{
|
119 |
+
return "http://sourceforge.net/apps/mediawiki/magmi/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 |
+
|
128 |
+
public function setParam($pname,$value)
|
129 |
+
{
|
130 |
+
$this->_params[$pname]=$value;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function fixListParam($pvalue)
|
134 |
+
{
|
135 |
+
$iarr=explode(",",$pvalue);
|
136 |
+
$oarr=array();
|
137 |
+
foreach($iarr as $v)
|
138 |
+
{
|
139 |
+
if($v!="")
|
140 |
+
{
|
141 |
+
$oarr[]=$v;
|
142 |
+
}
|
143 |
+
}
|
144 |
+
$val=implode(",",$oarr);
|
145 |
+
unset($iarr);
|
146 |
+
unset($oarr);
|
147 |
+
return $val;
|
148 |
+
}
|
149 |
+
public function getPluginParamNames()
|
150 |
+
{
|
151 |
+
return array();
|
152 |
+
}
|
153 |
+
|
154 |
+
public function getPluginInfo()
|
155 |
+
{
|
156 |
+
return array("name"=>$this->getPluginName(),
|
157 |
+
"version"=>$this->getPluginVersion(),
|
158 |
+
"author"=>$this->getPluginAuthor(),
|
159 |
+
"url"=>$this->getPluginUrl());
|
160 |
+
}
|
161 |
+
|
162 |
+
public function getPluginUrl()
|
163 |
+
{
|
164 |
+
return null;
|
165 |
+
}
|
166 |
+
|
167 |
+
public function getPluginVersion()
|
168 |
+
{
|
169 |
+
return null;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function getPluginName()
|
173 |
+
{
|
174 |
+
return null;
|
175 |
+
}
|
176 |
+
|
177 |
+
|
178 |
+
public function getPluginAuthor()
|
179 |
+
{
|
180 |
+
return null;
|
181 |
+
}
|
182 |
+
|
183 |
+
public function log($data,$type='std',$useprefix=true)
|
184 |
+
{
|
185 |
+
$pinf=$this->getPluginInfo();
|
186 |
+
if($useprefix)
|
187 |
+
{
|
188 |
+
$data="{$pinf["name"]} v{$pinf["version"]} - ".$data;
|
189 |
+
}
|
190 |
+
$this->_caller_log($data,"plugin;$this->_class;$type");
|
191 |
+
}
|
192 |
+
|
193 |
+
public function pluginHello()
|
194 |
+
{
|
195 |
+
$info=$this->getPluginInfo();
|
196 |
+
$hello=array(!isset($info["name"])?"":$info["name"]);
|
197 |
+
$hello[]=!isset($info["version"])?"":$info["version"];
|
198 |
+
$hello[]=!isset($info["author"])?"":$info["author"];
|
199 |
+
$hello[]=!isset($info["url"])?"":$info["url"];
|
200 |
+
$hellostr=implode("-",$hello);
|
201 |
+
$base=get_parent_class($this);
|
202 |
+
$this->log("$hellostr ","pluginhello",false);
|
203 |
+
|
204 |
+
}
|
205 |
+
|
206 |
+
public function initialize($params)
|
207 |
+
{
|
208 |
+
|
209 |
+
}
|
210 |
+
|
211 |
+
public function getConfig()
|
212 |
+
{
|
213 |
+
return $this->_config;
|
214 |
+
}
|
215 |
+
|
216 |
+
public function getMagmiConfig()
|
217 |
+
{
|
218 |
+
return $this->_magmiconfig;
|
219 |
+
}
|
220 |
+
|
221 |
+
public final function pluginInit($mmi,$meta,$params=null,$doinit=true,$profile=null)
|
222 |
+
{
|
223 |
+
$this->bind($mmi);
|
224 |
+
$this->_pluginmeta=$meta;
|
225 |
+
$this->_class=get_class($this);
|
226 |
+
$this->_config=new Magmi_PluginConfig(get_class($this),$profile);
|
227 |
+
$this->_config->load();
|
228 |
+
$this->_magmiconfig=Magmi_Config::getInstance();
|
229 |
+
|
230 |
+
$this->_params=($params!=null?array_merge($this->_config->getConfig(),$params):$this->_config->getConfig());
|
231 |
+
|
232 |
+
if(isset($mmi))
|
233 |
+
{
|
234 |
+
$this->pluginHello();
|
235 |
+
}
|
236 |
+
|
237 |
+
if($doinit)
|
238 |
+
{
|
239 |
+
$this->initialize($this->_params);
|
240 |
+
}
|
241 |
+
}
|
242 |
+
|
243 |
+
|
244 |
+
public function getPluginParamsNoCurrent($params)
|
245 |
+
{
|
246 |
+
$arr=array();
|
247 |
+
$paramkeys=$this->getPluginParamNames();
|
248 |
+
foreach($paramkeys as $pk)
|
249 |
+
{
|
250 |
+
if(isset($params[$pk]))
|
251 |
+
{
|
252 |
+
$arr[$pk]=$params[$pk];
|
253 |
+
}
|
254 |
+
else
|
255 |
+
{
|
256 |
+
$arr[$pk]=0;
|
257 |
+
}
|
258 |
+
}
|
259 |
+
return $arr;
|
260 |
+
}
|
261 |
+
public function getPluginParams($params)
|
262 |
+
{
|
263 |
+
$arr=array();
|
264 |
+
$paramkeys=$this->getPluginParamNames();
|
265 |
+
foreach($paramkeys as $pk)
|
266 |
+
{
|
267 |
+
if(isset($params[$pk]))
|
268 |
+
{
|
269 |
+
$arr[$pk]=$params[$pk];
|
270 |
+
}
|
271 |
+
else
|
272 |
+
{
|
273 |
+
if(isset($this->_params[$pk]))
|
274 |
+
{
|
275 |
+
$arr[$pk]=$this->_params[$pk];
|
276 |
+
}
|
277 |
+
}
|
278 |
+
}
|
279 |
+
return $arr;
|
280 |
+
}
|
281 |
+
|
282 |
+
public function persistParams($plist)
|
283 |
+
{
|
284 |
+
if(count($plist)>0)
|
285 |
+
{
|
286 |
+
$this->_config->setPropsFromFlatArray($plist);
|
287 |
+
return $this->_config->save();
|
288 |
+
}
|
289 |
+
return true;
|
290 |
+
}
|
291 |
+
|
292 |
+
public function getOptionsPanel($file=null)
|
293 |
+
{
|
294 |
+
return new Magmi_PluginOptionsPanel($this,$file);
|
295 |
+
}
|
296 |
+
|
297 |
+
public function getShortDescription()
|
298 |
+
{
|
299 |
+
$panel=$this->getOptionsPanel()->getHtml();
|
300 |
+
$info=null;
|
301 |
+
if(preg_match('|<div class="plugin_description">(.*?)</div>|smi',$panel,$match))
|
302 |
+
{
|
303 |
+
|
304 |
+
$info=$match[1];
|
305 |
+
$delims=array(".",":");
|
306 |
+
foreach($delims as $delim)
|
307 |
+
{
|
308 |
+
$p=strpos($info,$delim);
|
309 |
+
if($p!==false)
|
310 |
+
{
|
311 |
+
$info=substr($info,0,$p);
|
312 |
+
break;
|
313 |
+
}
|
314 |
+
}
|
315 |
+
|
316 |
+
}
|
317 |
+
return $info;
|
318 |
+
}
|
319 |
+
|
320 |
+
static public function getCategory()
|
321 |
+
{
|
322 |
+
return "common";
|
323 |
+
}
|
324 |
+
|
325 |
+
public function getPluginDir()
|
326 |
+
{
|
327 |
+
return $this->_pluginmeta["dir"];
|
328 |
+
}
|
329 |
+
|
330 |
+
public function getPluginMeta()
|
331 |
+
{
|
332 |
+
return $this->_pluginmeta;
|
333 |
+
}
|
334 |
+
|
335 |
+
public function getPluginClass()
|
336 |
+
{
|
337 |
+
return $this->_class;
|
338 |
+
}
|
339 |
+
|
340 |
+
public function isRunnable()
|
341 |
+
{
|
342 |
+
return array(true,"");
|
343 |
+
}
|
344 |
+
|
345 |
+
|
346 |
+
}
|
lib/Magmi/plugins/inc/magmi_utility_plugin.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Magmi_UtilityPlugin extends Magmi_Plugin
|
3 |
+
{
|
4 |
+
public function runUtility()
|
5 |
+
{
|
6 |
+
//Put Running code
|
7 |
+
}
|
8 |
+
|
9 |
+
public function getWarning()
|
10 |
+
{
|
11 |
+
return null;
|
12 |
+
}
|
13 |
+
}
|
package.xml
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>magento-full-catalog-translate</name>
|
4 |
+
<version>0.2.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>A module to translate all your products automatically using Google Translate API.</summary>
|
10 |
+
<description>When you install the module it will create a new product attribute called "Translate automatically?" (you'll find it in the "General" tab for all of your products).
|
11 |
+
<br /><br />
|
12 |
+
Let's say you have your main store in English, then you create a storeview in Italian, now all of your products in the Italian store view have the English texts. What you want is to quickly have them in Italian. Be sure the locales are correctly configured for all the stores/storeviews you're going to use in the process (this module will automatically read the language settings from the storeviews).
|
13 |
+
<br /><br />
|
14 |
+
So go in your "Catalog -> Manage products" mask in the Magento backend, select the Italian store view (or anyway the one you want to translate), then with the mass action tools selects all the products and "update attributes", now set the "Translate automatically?" attribute to yes. This means that these products for this store view neeed to be translated (we'll see later how and from what language to what language).
|
15 |
+
<br /><br />
|
16 |
+
Now we have products in English and products marked as "to be translated" in our Italian storeview.
|
17 |
+
<br /><br />
|
18 |
+
Let's step back a little bit: configuration. Before actually translating our contents you need to review come configurations of the module, go to the Magento backend mask "System -> Configuration -> Services -> Fballiano Full Catalog Translate". Here can decide which product attributes have to be translated (defaults: name, short_description, description, meta_title, meta_keyword, meta_description) but most importantly you'll have to fill your Google Translate API key (without it nothing will actually work).
|
19 |
+
<br /><br />
|
20 |
+
Open the console and navigate to the "shell" directory. Now we'll start the actual translate process.
|
21 |
+
<br /><br />
|
22 |
+
php fballiano_full_catalog_translate.php sourcestorecode targetstorecode
|
23 |
+
<br /><br />
|
24 |
+
in out case it could be:
|
25 |
+
<br /><br />
|
26 |
+
php fballiano_full_catalog_translate.php default storeviewita
|
27 |
+
<br /><br />
|
28 |
+
The process will gather all the products that need to be translated (from the target storeview), gather the untranslated text (from the source storeview), call Google Translate API for every attribute, import the translated text into the target store view, set the record to "not to be translated" (again, into the target storeview).</description>
|
29 |
+
<notes>First public release</notes>
|
30 |
+
<authors><author><name>Fabrizio Balliano</name><user>fballiano</user><email>fabrizio@fabrizioballiano.it</email></author></authors>
|
31 |
+
<date>2014-06-13</date>
|
32 |
+
<time>07:06:58</time>
|
33 |
+
<contents><target name="mage"><dir name="app"><dir name="code"><dir name="community"><dir name="Fballiano"><dir name="FullCatalogTranslate"><dir name="Helper"><file name="Data.php" hash="fed4f9d970da860ee349d8de2bb752ac"/></dir><dir name="etc"><file name="adminhtml.xml" hash="db29c60a26c76fc43d89a6aad45b8c0d"/><file name="config.xml" hash="9aaed4e0d405c4c93747359babf4db5a"/><file name="system.xml" hash="a525da02ee6ea44ccde8ee29d5942ee2"/></dir><dir name="sql"><dir name="fballiano_fullcatalogtranslate_setup"><file name="install-0.1.0.php" hash="39142871be423777adec9c76372a9731"/></dir></dir></dir></dir></dir></dir><dir name="etc"><dir name="modules"><file name="Fballiano_FullCatalogTranslate.xml" hash="7763d2974b52ca32136a0260a426f090"/></dir></dir></dir><dir name="lib"><dir name="Magmi"><file name="ReleaseNotes.txt" hash="0ac67ff0b1bd147e09aacc854113309d"/><dir name="conf"><file name="magmi.ini" hash="17ad89d67997e66c499c673e3e8af291"/><file name="plugins.conf" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir><dir name="engines"><file name="magmi_productimportengine.php" hash="8897589287f42e89a4c13dae04c5c152"/><file name="magmi_utilityengine.php" hash="d0ca093690e95caea5864d2fd4321104"/></dir><dir name="inc"><file name="dbhelper.class.php" hash="9d08f9e386e482048335c35069175e1c"/><file name="dbhelper.class.php~" hash="59098f2580e780f55bd99f0602e78b2d"/><file name="fshelper.php" hash="b191c2c916cf3dca5055bd96c93b8945"/><file name="license.txt" hash="d69f02f4db9d64af32ac1a390d2a9574"/><file name="magmi_config.php" hash="aea8a1efdeca49f2405f473c1f0b9a23"/><file name="magmi_csvreader.php" hash="895070e4753f1e77d1702f9de5652d03"/><file name="magmi_defs.php" hash="50a8feecdfb43dde843bd7e36fddc413"/><file name="magmi_engine.php" hash="f0b097072ec83b7b50b4e243a6bfb9be"/><file name="magmi_loggers.php" hash="27e74b06ce160c6e07f9da614503bfba"/><file name="magmi_mixin.php" hash="95ac60575fcda43174fa545f2e4c0217"/><file name="magmi_pluginhelper.php" hash="75d5ba334c43f545cdc38d274341b423"/><file name="magmi_postinstall.php" hash="3bef1b9a85d364d0858502e0d5b3cd87"/><file name="magmi_statemanager.php" hash="a56c33fe73c871338853c25933c2a280"/><file name="magmi_utils.php" hash="9694d4ffdb23c1ca2b350dad99d08e96"/><file name="magmi_version.php" hash="1a18210c3c8b7884c596a2d350ebc7ae"/><file name="properties.php" hash="1a57150735e51255fff575b8f1df5e91"/></dir><dir name="integration"><dir name="inc"><file name="magmi_datapump.php" hash="5446ff3f4dd82086d10d81c8f32bba05"/><file name="magmi_datapumpdatasource.php" hash="98113a6bc3d3617da7655c850596c36b"/><file name="productimport_datapump.php" hash="b5bfa0ce6aa4e7b56f70bd3da623e428"/><file name="pumpfactory.ini" hash="b4beac3e561fcf91a416eb52c76ce4e3"/></dir><dir name="samples"><file name="sample.php" hash="89df4a819a4396ab981092cae130eaa9"/><file name="sample2_configurables.php" hash="4ab28a07812ae27c9ad26bf3edbb68fd"/></dir></dir><dir name="plugins"><dir name="base"><dir name="datasources"><dir name="__magento"><file name="magmi_magentodatasource.php" hash="7994fe4f0ffdbe6d2d5881d31597319a"/><file name="options_panel.php" hash="1c1cf71c5ca55933b1c39e4040d1865e"/></dir><dir name="csv"><file name="csvds_filelist.php" hash="737e882668364fd8fe517f6fb94d3deb"/><file name="magmi_csvdatasource.php" hash="d6d78948b50669161fd8bb615dab8de1"/><file name="options_panel.php" hash="0addabcc9d0469cfd6a86b0cbda63418"/></dir><dir name="genericsql"><file name="mysql_options.php" hash="ca0c24ee9397fcdfba2b75063ef28901"/><file name="options_panel.php" hash="fe738f8d7f861eba725a4cd7a6798809"/><file name="other_options.php" hash="f47deb1e13a7e5bfaade5b878f9f1065"/><file name="sql_datasource.php" hash="f1e6b42056630739bcb38df8e74f121e"/></dir></dir><dir name="general"><dir name="emailreport"><file name="emailreport.php" hash="6bda450b7141cdcdb7b0e7b184cca8bd"/><file name="options_panel.php" hash="72c1ac4891219fa1a87f8b03a15dc0c6"/></dir><dir name="importurl"><file name="importurl_plugin.php" hash="3b3226fb553a03a2bfff8d45babf4f02"/><file name="options_panel.php" hash="3f4131f0c50b22af8d5762eae25a8561"/></dir><dir name="optimizer"><file name="magmi_optimizer_plugin.php" hash="2c0a9f084c93ac6052a115eaac5cb398"/></dir><dir name="reindex"><file name="magmi_reindexing_plugin.php" hash="2552a823150c881b877035d79824565f"/><file name="options_panel.php" hash="eb077f772e34bdbf75c79ce882cd0f07"/></dir></dir><dir name="itemprocessors"><dir name="columnmapper"><file name="000_columnmapper.php" hash="7a0ae78ee3ab4f38431c07f8ed46bd6d"/><file name="options_panel.php" hash="44b2ab98da57a5354cd22c1d7f5a8e0f"/></dir><dir name="configurables"><file name="magmi_configurableprocessor.php" hash="93f7f7da42a017e77a3293e825bb2048"/><file name="options_panel.php" hash="4ffc870e5ff6bc33a02e972a2f614707"/></dir><dir name="defaultvalues"><file name="00_default_values.php" hash="d8e94a904b9b4a03304785ec2d5a9d9d"/><file name="options_panel.php" hash="b951c2d3487d694597c416a1ff3dafa1"/></dir><dir name="genericmapper"><file name="02_genericmapper.php" hash="5890de9499085267cde209a07aabb9d0"/><dir name="mappings"><dir name="default"><file name="__common__.csv" hash="51f076b2137b08cbcec63bcfa046ad7a"/><file name="options_container.csv" hash="bb84f94e68900c1aafc66ce2c2461d06"/><file name="page_layout.csv" hash="0f6ac4af46d4090cb22497d172bad2f8"/><file name="status.csv" hash="dc5569042656c4163fea1cd74e8ed6d8"/><file name="visibility.csv" hash="462fe1effcdb1ab3942677a011019f15"/></dir></dir><file name="options_panel.php" hash="06477d262c34d194da52d533af8d270f"/></dir><dir name="grouped"><file name="alpine_groupedprocessor.php" hash="570fd184740e822b6b4489cd3a30324a"/><file name="options_panel.php" hash="746c1d9e4e3248ab768f2da7002d0ac4"/></dir><dir name="importlimiter"><file name="01_importlimiter.php" hash="770310a86b9bd7b8a03889c60d4b82d2"/><file name="options_panel.php" hash="cb52e5ac4bc489c50b2b5768608bcf0b"/></dir><dir name="productdeleter"><file name="options_panel.php" hash="4252b3a975efc6bc42ec3903a1f9158f"/><file name="productdeleter.php" hash="d9390afd593ed793a5ce13f3877d2f70"/></dir><dir name="related"><file name="related_products.php" hash="c9623952da7d17e76d8e6483b7327f80"/></dir><dir name="skufinder"><file name="001_skufinder.php" hash="a5dbdaed122087f6c0a68e024556fae4"/><file name="options_panel.php" hash="fe48ad7baac974583c41eb762dbe4e1c"/></dir><dir name="upcross_sell"><file name="crossupsell_products.php" hash="23eec787b46fcb0463367090e47e97e4"/></dir></dir></dir><dir name="inc"><file name="magmi_datasource.php" hash="255921bd1b5879e77a3a16f762781ac0"/><file name="magmi_default_options_panel.php" hash="b35c690a790c77b97124c3bd395b176d"/><file name="magmi_defaultattributehandler.php" hash="4f6ce8c7286aca015bef34366c11899d"/><file name="magmi_generalimport_plugin.php" hash="e5a337ee90873ee82c6ecb7ed38af647"/><file name="magmi_item_processor.php" hash="1bd368a6970940206724284a299f028b"/><file name="magmi_plugin.php" hash="c3a09fef3804f0b56b3123494e47239c"/><file name="magmi_utility_plugin.php" hash="8b0aaa8700a9337a206d72ded13bfa9b"/></dir></dir></dir></dir><dir name="shell"><file name="fballiano_full_catalog_translate.php" hash="e87ba031e963a459a5f22edf30902900"/></dir></target></contents>
|
34 |
+
<compatible/>
|
35 |
+
<dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
|
36 |
+
</package>
|
shell/fballiano_full_catalog_translate.php
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* FBalliano
|
4 |
+
*
|
5 |
+
* NOTICE OF LICENSE
|
6 |
+
*
|
7 |
+
* This source file is subject to the Open Software License (OSL 3.0)
|
8 |
+
* that is bundled with this package in the file LICENSE.txt.
|
9 |
+
* It is also available through the world-wide-web at this URL:
|
10 |
+
* http://opensource.org/licenses/osl-3.0.php
|
11 |
+
*
|
12 |
+
* DISCLAIMER
|
13 |
+
*
|
14 |
+
* Do not edit or add to this file if you wish to upgrade this Module to
|
15 |
+
* newer versions in the future.
|
16 |
+
*
|
17 |
+
* @category FBalliano
|
18 |
+
* @package FBalliano_FullCatalogTranslate
|
19 |
+
* @copyright Copyright (c) 2014 Fabrizio Balliano (http://fabrizioballiano.it)
|
20 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
21 |
+
*/
|
22 |
+
|
23 |
+
require_once 'abstract.php';
|
24 |
+
|
25 |
+
class Fballiano_FullCatalogTranslate_Shell extends Mage_Shell_Abstract
|
26 |
+
{
|
27 |
+
protected $helper = null;
|
28 |
+
protected $api_key = null;
|
29 |
+
protected $store_source = null;
|
30 |
+
protected $store_dest = null;
|
31 |
+
protected $language_source = null;
|
32 |
+
protected $language_dest = null;
|
33 |
+
protected $ws_url = "https://www.googleapis.com/language/translate/v2";
|
34 |
+
protected $attributes_to_translate = null;
|
35 |
+
protected $datapump = null;
|
36 |
+
|
37 |
+
public function run()
|
38 |
+
{
|
39 |
+
$this->helper = Mage::helper("fballiano_fullcatalogtranslate");
|
40 |
+
$this->attributes_to_translate = $this->helper->getAttributesToTranslate();
|
41 |
+
$this->api_key = $this->helper->getApiKey();
|
42 |
+
if (!$this->api_key) die("Please set your API key in the Magento admin configuration.\n");
|
43 |
+
$this->ws_url .= "?key={$this->api_key}";
|
44 |
+
|
45 |
+
$args = array_keys($this->_args);
|
46 |
+
$this->store_source = @$args[0];
|
47 |
+
$this->store_dest = @$args[1];
|
48 |
+
if (!$this->store_source or !$this->store_dest) die($this->usageHelp());
|
49 |
+
|
50 |
+
require_once "Magmi/inc/magmi_defs.php";
|
51 |
+
require_once "Magmi/integration/inc/magmi_datapump.php";
|
52 |
+
require_once "Magmi/integration/inc/productimport_datapump.php";
|
53 |
+
require_once "Magmi/integration/inc/productimport_datapump.php";
|
54 |
+
$this->datapump = new Magmi_ProductImport_Datapump();
|
55 |
+
$this->datapump->beginImportSession("default", "create");
|
56 |
+
|
57 |
+
$appEmulation = Mage::getSingleton("core/app_emulation");
|
58 |
+
|
59 |
+
try {
|
60 |
+
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($this->store_dest);
|
61 |
+
} catch (Mage_Core_Model_Store_Exception $e) {
|
62 |
+
die("Target store view \"{$this->store_dest}\" doesn't seem to exist\n" . $this->usageHelp());
|
63 |
+
}
|
64 |
+
|
65 |
+
$store_id_dest = Mage::app()->getStore()->getId();
|
66 |
+
$this->language_dest = substr(Mage::app()->getLocale()->getLocaleCode(), 0, 2);
|
67 |
+
$this->ws_url .= "&target={$this->language_dest}";
|
68 |
+
|
69 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
70 |
+
|
71 |
+
$attribute_id = Mage::getModel("catalog/entity_attribute")->loadByCode(Mage_Catalog_Model_Product::ENTITY, "fb_translate")->getId();
|
72 |
+
$table_name = Mage::getSingleton("core/resource")->getTableName("catalog_product_entity_int");
|
73 |
+
$products = Mage::getSingleton("core/resource")->getConnection("core_read")->fetchCol("SELECT entity_id FROM {$table_name} WHERE attribute_id={$attribute_id} AND store_id={$store_id_dest} AND value=1");
|
74 |
+
|
75 |
+
try {
|
76 |
+
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($this->store_source);
|
77 |
+
} catch (Mage_Core_Model_Store_Exception $e) {
|
78 |
+
die("Source store \"{$this->store_source}\" view doesn't seem to exist\n" . $this->usageHelp());
|
79 |
+
}
|
80 |
+
|
81 |
+
$this->language_source = substr(Mage::app()->getLocale()->getLocaleCode(), 0, 2);
|
82 |
+
$this->ws_url .= "&source={$this->language_source}";
|
83 |
+
|
84 |
+
$product = Mage::getModel("catalog/product");
|
85 |
+
foreach ($products as $product_id) {
|
86 |
+
$product->load($product_id);
|
87 |
+
$row = $product->getData();
|
88 |
+
|
89 |
+
echo "Translating {$row["sku"]} from {$this->language_source} to {$this->language_dest}... ";
|
90 |
+
$translated_row = array();
|
91 |
+
$translated_row["store"] = (string)$this->store_dest;
|
92 |
+
$translated_row["sku"] = (string)$row["sku"];
|
93 |
+
$translated_row["fb_translate"] = "0"; //leave it as string otherwise magmi won't save it
|
94 |
+
foreach ($this->attributes_to_translate as $attribute) {
|
95 |
+
if (strlen($row[$attribute])) {
|
96 |
+
$ws_url = "{$this->ws_url}&q=" . urlencode($row[$attribute]);
|
97 |
+
$translated = json_decode(file_get_contents($ws_url), true);
|
98 |
+
$translated = $translated["data"]["translations"][0]["translatedText"];
|
99 |
+
$translated_row[$attribute] = (string)$translated;
|
100 |
+
}
|
101 |
+
}
|
102 |
+
$this->datapump->ingest($translated_row);
|
103 |
+
echo "OK\n";
|
104 |
+
}
|
105 |
+
|
106 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
107 |
+
$this->datapump->endImportSession();
|
108 |
+
echo "Terminated\n";
|
109 |
+
}
|
110 |
+
|
111 |
+
public function productCollectionWalkCallback($args)
|
112 |
+
{
|
113 |
+
$row = $args["row"];
|
114 |
+
echo "Translating {$row["sku"]} from {$this->language_source} to {$this->language_dest}... ";
|
115 |
+
$translated_row = array();
|
116 |
+
$translated_row["store"] = $this->store_dest;
|
117 |
+
$translated_row["sku"] = $row["sku"];
|
118 |
+
$translated_row["fb_translate"] = 0;
|
119 |
+
foreach ($this->attributes_to_translate as $attribute) {
|
120 |
+
if (strlen($row[$attribute])) {
|
121 |
+
$ws_url = "{$this->ws_url}&q=" . urlencode($row[$attribute]);
|
122 |
+
$translated = json_decode(file_get_contents($ws_url), true);
|
123 |
+
$translated = $translated["data"]["translations"][0]["translatedText"];
|
124 |
+
$translated_row[$attribute] = $translated;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
$this->datapump->ingest($translated_row);
|
129 |
+
echo "OK\n";
|
130 |
+
}
|
131 |
+
|
132 |
+
public function usageHelp()
|
133 |
+
{
|
134 |
+
return <<<USAGE
|
135 |
+
|
136 |
+
Usage: php -f fballiano_full_catalog_translate.php source_store_view_code target_store_view_code
|
137 |
+
|
138 |
+
USAGE;
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
$shell = new Fballiano_FullCatalogTranslate_Shell();
|
143 |
+
$shell->run();
|