· 9 years ago · Oct 29, 2016, 05:26 PM
1<?php
2
3class Magmi_DefaultAttributeItemProcessor extends Magmi_ItemProcessor
4{
5 protected $_basecols = array("store"=>"admin","type"=>"simple");
6 protected $_baseattrs = array("status"=>1,"visibility"=>4,"page_layout"=>"","tax_class_id"=>"Taxable Goods");
7 protected $_forcedefault = array("store"=>"admin");
8 protected $_missingcols = array();
9 protected $_missingattrs = array();
10 protected $_hasurlkeytable=false;
11 protected $_urlkeytablename="";
12 /**
13 * (non-PHPdoc)
14 *
15 * @see Magmi_Plugin::initialize()
16 */
17 public function initialize($params)
18 {
19 $this->_urlkeytablename=$this->tablename('catalog_product_entity_url_key');
20 $this->registerAttributeHandler($this, array("attribute_code:.*"));
21 $sql="SHOW TABLES LIKE ?";
22 $result=$this->selectAll($sql, array($this->_urlkeytablename));
23 $this->_hasurlkeytable=(count($result)>0);
24 }
25
26 /**
27 * (non-PHPdoc)
28 *
29 * @see Magmi_Plugin::getPluginInfo()
30 */
31 public function getPluginInfo()
32 {
33 return array("name"=>"Standard Attribute Import","author"=>"Dweeves","version"=>"1.1");
34 }
35
36 /**
37 * callback for column list processing
38 *
39 * @param unknown $cols
40 */
41 public function processColumnList(&$cols)
42 {
43 // This will not change the column list
44 // this will only log the list of columns that will be added to newly created items
45 $this->_missingcols = array_diff(array_keys($this->_basecols), $cols);
46 $this->_missingattrs = array_diff(array_keys($this->_baseattrs), $cols);
47 $m = $this->getMode();
48 if ($m == "create" || $m == "xcreate") {
49 $cols = array_merge($cols, $this->_missingcols, $this->_missingattrs);
50 $this->log(
51 "Newly created items will have default values for columns:" .
52 implode(",", array_merge($this->_missingcols, $this->_missingattrs)), "startup");
53 }
54 }
55
56 /**
57 * initializes extra columns if needed
58 *
59 * @param unknown $item
60 */
61 public function initializeBaseCols(&$item)
62 {
63 foreach ($this->_missingcols as $missing) {
64 $item[$missing] = $this->_basecols[$missing];
65 }
66 }
67
68 /**
69 * Initialized base attributes to retrieve from a given item description
70 *
71 * @param unknown $item
72 */
73 public function initializeBaseAttrs(&$item)
74 {
75 foreach ($this->_missingattrs as $missing) {
76 $item[$missing] = $this->_baseattrs[$missing];
77 }
78 }
79
80 /**
81 * (non-PHPdoc)
82 *
83 * @see Magmi_ItemProcessor::processItemAfterId()
84 */
85 public function preprocessItemAfterId(&$item, $params = null)
86 {
87 if ($params["new"] == true) {
88 $this->initializeBaseCols($item);
89 $this->initializeBaseAttrs($item);
90 //force url key for new items for magento > 1.7.x
91 if ($this->checkMagentoVersion("1.7.x", ">") && empty($item['url_key'])) {
92 $item["url_key"]=Slugger::slug($item["name"]);
93 }
94 } else {
95 //if we have an existing item, get some structural info from identification meta
96 if (!isset($item["type"])) {
97 $item["type"]=$params["type"];
98 }
99 }
100 // forcing default values for mandatory processing columns
101 foreach ($this->_forcedefault as $k => $v) {
102 if (isset($item[$k]) && trim($item[$k]) == "") {
103 $item[$k] = $v;
104 }
105 }
106 return true;
107 }
108
109 /**
110 * returns magento default value if applicable
111 * - item should not exist yet
112 * - default value should be set in magento
113 * - ivalue should be empty
114 *
115 * @param array $attrdesc
116 * : attribute description table
117 * @param mixed $ivalue
118 * : input value
119 * @return magento default value or NULL if not applicable
120 */
121 public function getDefaultValue($attrdesc, $ivalue)
122 {
123 $exists = $this->currentItemExists();
124 // check for new item default value in DB for new items
125 if (!$exists && isset($attrdesc["default_value"]) && !empty($attrdesc["default_value"]) && empty($ivalue)) {
126 return $attrdesc["default_value"];
127 }
128 return null;
129 }
130
131 /**
132 * attribute handler for Decimal attributes
133 *
134 * @param int $pid
135 * : product id
136 * @param array $item
137 * : item to inges
138 * @param int $storeid
139 * : store for attribute value storage
140 * @param int $attrcode
141 * : attribute code
142 * @param array $attrdesc
143 * : attribute metadata
144 * @param mixed $ivalue
145 * : input value to import
146 * @return new decimal value to set
147 */
148 public function handleDecimalAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
149 {
150 $dval = $this->getDefaultValue($attrdesc, $ivalue);
151 if ($dval !== null) {
152 return $dval;
153 }
154 // force convert decimal separator to dot
155 $ivalue = str_replace(",", ".", $ivalue);
156 $ovalue = deleteifempty($ivalue);
157 return $ovalue;
158 }
159
160 /**
161 * attribute handler for DateTime attributes
162 *
163 * @param int $pid
164 * : product id
165 * @param array $item
166 * : item to inges
167 * @param int $storeid
168 * : store for attribute value storage
169 * @param int $attrcode
170 * : attribute code
171 * @param array $attrdesc
172 * : attribute metadata
173 * @param mixed $ivalue
174 * : input value to import
175 * @return new datetime value to set
176 */
177 public function handleDatetimeAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
178 {
179 $dval = $this->getDefaultValue($attrdesc, $ivalue);
180 if ($dval !== null) {
181 return $dval;
182 }
183 $ovalue = deleteifempty(trim($ivalue));
184 // Handle european date format or other common separators
185 if (preg_match("|(\d{1,2})\D(\d{1,2})\D(\d{4})\s*(\d{2}:\d{2}:\d{2})?|", $ovalue, $matches)) {
186 $hms = count($matches) > 4 ? $matches[4] : "";
187 $ovalue = trim(sprintf("%4d-%2d-%2d %s", $matches[3], $matches[2], $matches[1], $hms));
188 }
189 return $ovalue;
190 }
191
192 /**
193 * attribute handler for Text attributes
194 *
195 * @param int $pid
196 * : product id
197 * @param array $item
198 * : item to inges
199 * @param int $storeid
200 * : store for attribute value storage
201 * @param int $attrcode
202 * : attribute code
203 * @param array $attrdesc
204 * : attribute metadata
205 * @param mixed $ivalue
206 * : input value to import
207 * @return new text value to set
208 */
209 public function handleTextAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
210 {
211 $dval = $this->getDefaultValue($attrdesc, $ivalue);
212 if ($dval !== null) {
213 return $dval;
214 }
215 $ovalue = deleteifempty($ivalue);
216 $attid = $attrdesc["attribute_id"];
217 // --- ExtensionsMall multiselect 1.9.3 varchar -> text ----
218 if ($attrdesc["frontend_input"] == "multiselect") {
219 // if empty delete entry
220 if ($ivalue == "") {
221 return "__MAGMI_DELETE__";
222 }
223 // magento uses "," as separator for different multiselect values
224 $sep = Magmi_Config::getInstance()->get("GLOBAL", "multiselect_sep", ",");
225 $multiselectvalues = explode($sep, $ivalue);
226 $oids = $this->getOptionIds($attid, $storeid, $multiselectvalues);
227 $ovalue = implode(",", array_values($oids));
228 unset($oids);
229 }
230 return $ovalue;
231 }
232
233 /**
234 * check if a value is integer
235 *
236 * @param mixed $value
237 * @return true if integer, false if not
238 */
239 public function checkInt($value)
240 {
241 return is_int($value) || (is_string($value) && is_numeric($value) && (int) $value == $value);
242 }
243
244 /**
245 * attribute handler for Int typed attributes
246 *
247 * @param int $pid
248 * : product id
249 * @param array $item
250 * : item to inges
251 * @param int $storeid
252 * : store for attribute value storage
253 * @param int $attrcode
254 * : attribute code
255 * @param array $attrdesc
256 * : attribute metadata
257 * @param mixed $ivalue
258 * : input value to import
259 * @return new int value to set
260 *
261 * Many attributes are int typed, so we need to handle all cases like :
262 * - select
263 * - tax id
264 * - boolean
265 * - status
266 * - visibility
267 */
268 public function handleIntAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
269 {
270 $ovalue = $ivalue;
271
272 // default value exists, return it
273 $dval = $this->getDefaultValue($attrdesc, $ivalue);
274 if ($dval !== null) {
275 return intval($dval);
276 }
277
278 $attid = $attrdesc["attribute_id"];
279 // if we've got a select type value
280 if ($attrdesc["frontend_input"] == "select") {
281 $smodel=$attrdesc["source_model"];
282 // we need to identify its type since some have no options
283 switch ($smodel) {
284 // if its status, default to 1 (Enabled) if not correcly mapped
285 case "catalog/product_status":
286 if (!$this->checkInt($ivalue)) {
287 $ovalue = 1;
288 }
289 break;
290 // do not create options for boolean values tagged as select ,default to 0 if not correcly mapped
291 case "eav/entity_attribute_source_boolean":
292 if (!$this->checkInt($ivalue)) {
293 $ovalue = 0;
294 }
295 break;
296 // if visibility no options either,default to 4 if not correctly mapped
297 case "catalog/product_visibility":
298 if (!$this->checkInt($ivalue)) {
299 $ovalue = 4;
300 }
301
302 break;
303 // if it's tax_class, get tax class id from item value
304 case "tax/class_source_product":
305 $ovalue = $this->getTaxClassId($ivalue);
306 break;
307 // otherwise, standard option behavior
308 // get option id for value, create it if does not already exist
309 // do not insert if empty
310 default:
311 $exists = $this->currentItemExists();
312 if ($ivalue == "" && $exists) {
313 return "__MAGMI_DELETE__";
314 }
315 $oids = $this->getOptionIds($attid, $storeid, array($ivalue));
316 //the new oids is a key/value array
317 //in case of translate, the oids key is only the admin value, but the values are ok
318 //this would also work for multiselect
319 $ovalue = implode(",", array_unique(array_values($oids)));
320 unset($oids);
321 break;
322 }
323 }
324 return $ovalue;
325 }
326
327 /**
328 * attribute handler for "url_key" attribute
329 *
330 * @param int $pid
331 * : product id
332 * @param array $item
333 * : item to inges
334 * @param int $storeid
335 * : store for attribute value storage
336 * @param int $attrcode
337 * : attribute code
338 * @param array $attrdesc
339 * : attribute metadata
340 * @param mixed $ivalue
341 * : input value to import
342 * @return new int value to set
343 *
344 */
345 public function handleUrl_keyAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
346 {
347 //specific behaviour for url key table if exists
348 //no more conflict checking at this point, will only do for url rewrite
349 $urlk=$ivalue;
350 if ($this->_hasurlkeytable) {
351 $sql = 'INSERT INTO ' . $this->_urlkeytablename . ' (entity_type_id,attribute_id,entity_id,store_id,value) VALUES (?,?,?,?,?)';
352 #fix for url key "unique store value index"
353 $sql.=' ON DUPLICATE KEY UPDATE value=VALUES(value) ';
354 $this->insert($sql, array($this->getProductEntityType(), $attrdesc["attribute_id"], $pid, $storeid, $ivalue));
355 }
356 return $urlk;
357 }
358
359 /**
360 * attribute handler for Varchar typed attributes
361 *
362 * @param int $pid
363 * : product id
364 * @param array $item
365 * : item to inges
366 * @param int $storeid
367 * : store for attribute value storage
368 * @param int $attrcode
369 * : attribute code
370 * @param array $attrdesc
371 * : attribute metadata
372 * @param mixed $ivalue
373 * : input value to import
374 * @return new int value to set
375 *
376 * Special case for multiselect
377 */
378 public function handleVarcharAttribute($pid, &$item, $storeid, $attrcode, $attrdesc, $ivalue)
379 {
380 $exists = $this->currentItemExists();
381 // Check store specific value & empty & new item => ignore
382 if ($storeid !== 0 && empty($ivalue) && !$exists) {
383 return false;
384 }
385 // item exists , empty value, remove value, back to admin
386 if ($ivalue == "" && $exists) {
387 return "__MAGMI_DELETE__";
388 }
389 // default value exists, return it
390 $dval = $this->getDefaultValue($attrdesc, $ivalue);
391 if ($dval !== null) {
392 return $dval;
393 }
394
395 $ovalue = $ivalue;
396 $attid = $attrdesc["attribute_id"];
397 // --- Contribution From mennos , optimized by dweeves ----
398 // Added to support multiple select attributes
399 // (as far as i could figure out) always stored as varchars
400 // if it's a multiselect value
401 if ($attrdesc["frontend_input"] == "multiselect") {
402 // if empty delete entry
403 if ($ivalue == "") {
404 return "__MAGMI_DELETE__";
405 }
406 // magento uses "," as separator for different multiselect values
407 $sep = Magmi_Config::getInstance()->get("GLOBAL", "multiselect_sep", ",");
408 $multiselectvalues = explode($sep, $ivalue);
409 $oids = $this->getOptionIds($attid, $storeid, $multiselectvalues);
410 $ovalue = implode(",", array_values($oids));
411 unset($oids);
412 }
413
414 return $ovalue;
415 }
416}