1
|
|
|
<?php
|
2
|
|
|
/**
|
3
|
|
|
* @author Alexey Tatarinov <[email protected]>
|
4
|
|
|
* @link https://github.com/shogodev/argilla/
|
5
|
|
|
* @copyright Copyright © 2003-2015 Shogo
|
6
|
|
|
* @license http://argilla.ru/LICENSE
|
7
|
|
|
*/
|
8
|
|
|
|
9
|
|
|
Yii::import('frontend.share.helpers.*');
|
10
|
|
|
Yii::import('backend.modules.product.modules.import.components.exceptions.*');
|
11
|
|
|
Yii::import('backend.modules.product.modules.import.components.abstracts.AbstractImportWriter');
|
12
|
|
|
|
13
|
|
|
/**
|
14
|
|
|
* Class ImageWriter
|
15
|
|
|
* @property string $sourcePath
|
16
|
|
|
* @property bool $replaceFile default false
|
17
|
|
|
*/
|
18
|
|
|
class ImageWriter extends AbstractImportWriter
|
19
|
|
|
{
|
20
|
|
|
public $previews = array();
|
21
|
|
|
|
22
|
|
|
public $defaultJpegQuality = 90;
|
23
|
|
|
|
24
|
|
|
/**
|
25
|
|
|
* @var EPhpThumb
|
26
|
|
|
*/
|
27
|
|
|
protected $phpThumb;
|
28
|
|
|
|
29
|
|
|
protected $productIdsCache;
|
30
|
|
|
|
31
|
|
|
protected $tables = array(
|
32
|
|
|
'product' => '{{product}}',
|
33
|
|
|
'productImage' => '{{product_img}}'
|
34
|
|
|
);
|
35
|
|
|
|
36
|
|
|
protected $basePath = 'f/product';
|
37
|
|
|
|
38
|
|
|
protected $sourcePath = 'src';
|
39
|
|
|
|
40
|
|
|
protected $replaceFile = false;
|
41
|
|
|
|
42
|
|
|
/**
|
43
|
|
|
* @var CDbCommandBuilder $commandBuilder
|
44
|
|
|
*/
|
45
|
|
|
protected $commandBuilder;
|
46
|
|
|
|
47
|
|
|
public function __construct(ConsoleFileLogger $logger)
|
48
|
|
|
{
|
49
|
|
|
parent::__construct($logger);
|
50
|
|
|
|
51
|
|
|
$this->basePath = realpath(Yii::getPathOfAlias('frontend').'/..').ImportHelper::wrapInSlash($this->basePath);
|
52
|
|
|
|
53
|
|
|
$this->sourcePath = $this->basePath.ImportHelper::wrapInSlashEnd($this->sourcePath);
|
54
|
|
|
|
55
|
|
|
$this->commandBuilder = Yii::app()->db->schema->commandBuilder;
|
56
|
|
|
|
57
|
|
|
$this->phpThumb = Yii::createComponent(array(
|
58
|
|
|
'class' => 'ext.phpthumb.EPhpThumb',
|
59
|
|
|
'options' => array(
|
60
|
|
|
'jpegQuality' => $this->defaultJpegQuality,
|
61
|
|
|
),
|
62
|
|
|
));
|
63
|
|
|
|
64
|
|
|
$this->phpThumb->init();
|
65
|
|
|
}
|
66
|
|
|
|
67
|
|
View Code Duplication |
public function writeAll(array $data)
|
|
|
|
|
68
|
|
|
{
|
69
|
|
|
$itemsAmount = count($data);
|
70
|
|
|
if( $itemsAmount == 0 )
|
71
|
|
|
return;
|
72
|
|
|
|
73
|
|
|
$progress = new ConsoleProgressBar($itemsAmount);
|
74
|
|
|
$this->logger->log('Начало обработки файлов');
|
75
|
|
|
$progress->start();
|
76
|
|
|
foreach($data as $uniqueAttributeValue => $images)
|
77
|
|
|
{
|
78
|
|
|
$this->safeWriteItem($uniqueAttributeValue, $images);
|
79
|
|
|
$progress->setValueMap('memory', Yii::app()->format->formatSize(memory_get_usage()));
|
80
|
|
|
$progress->advance();
|
81
|
|
|
}
|
82
|
|
|
$progress->finish();
|
83
|
|
|
$this->logger->log('Обработка файлов завершена');
|
84
|
|
|
}
|
85
|
|
|
|
86
|
|
|
public function writePartial(array $data)
|
87
|
|
|
{
|
88
|
|
|
foreach($data as $uniqueAttributeValue => $images)
|
89
|
|
|
{
|
90
|
|
|
$this->safeWriteItem($uniqueAttributeValue, $images);
|
91
|
|
|
}
|
92
|
|
|
}
|
93
|
|
|
|
94
|
|
|
public function showStatistics()
|
95
|
|
|
{
|
96
|
|
|
|
97
|
|
|
}
|
98
|
|
|
|
99
|
|
|
protected function setSourcePath($path)
|
100
|
|
|
{
|
101
|
|
|
$this->sourcePath = $this->basePath.ImportHelper::wrapInSlashEnd($path);
|
102
|
|
|
}
|
103
|
|
|
|
104
|
|
|
protected function setReplaceFile($replace)
|
105
|
|
|
{
|
106
|
|
|
$this->replaceFile = $replace;
|
107
|
|
|
}
|
108
|
|
|
|
109
|
|
|
protected function safeWriteItem($uniqueAttributeValue, $images)
|
110
|
|
|
{
|
111
|
|
|
try
|
112
|
|
|
{
|
113
|
|
|
$this->write($uniqueAttributeValue, $images);
|
114
|
|
|
}
|
115
|
|
|
catch(WarningException $e)
|
116
|
|
|
{
|
117
|
|
|
$this->logger->warning($e->getMessage());
|
118
|
|
|
}
|
119
|
|
|
}
|
120
|
|
|
|
121
|
|
|
protected function write($uniqueAttributeValue, array $images)
|
122
|
|
|
{
|
123
|
|
|
if( !($productId = $this->getProductIdByAttribute($this->uniqueAttribute, $uniqueAttributeValue)) )
|
124
|
|
|
throw new WarningException('Не удалсь найти продукт по атрибуту '.$this->uniqueAttribute.' = '.$uniqueAttributeValue);
|
125
|
|
|
|
126
|
|
|
foreach($images as $image)
|
127
|
|
|
{
|
128
|
|
|
$file = $this->sourcePath.$image;
|
129
|
|
|
|
130
|
|
|
if( !file_exists($file) )
|
131
|
|
|
throw new WarningException('Файл '.$file.' не найден');
|
132
|
|
|
|
133
|
|
|
$type = ($image == reset($images) ? 'main' : 'gallery');
|
134
|
|
|
|
135
|
|
|
try
|
136
|
|
|
{
|
137
|
|
|
$this->beginTransaction();
|
138
|
|
|
$newFileName = $this->createProductImageRecord($file, $productId, $type);
|
139
|
|
|
$this->createImages($file, $newFileName);
|
140
|
|
|
$this->commitTransaction();
|
141
|
|
|
}
|
142
|
|
|
catch(Exception $e)
|
143
|
|
|
{
|
144
|
|
|
$this->rollbackTransaction();
|
145
|
|
|
throw $e;
|
146
|
|
|
}
|
147
|
|
|
}
|
148
|
|
|
}
|
149
|
|
|
|
150
|
|
|
protected function createImages($file, $newFileName)
|
151
|
|
|
{
|
152
|
|
|
foreach($this->previews as $preview => $sizes)
|
153
|
|
|
{
|
154
|
|
|
$newPath = $this->basePath.($preview === 'origin' ? "" : $preview.'_').$newFileName;
|
155
|
|
|
|
156
|
|
|
if( !$this->replaceFile && file_exists($newPath) )
|
157
|
|
|
throw new WarningException('Файл '.$newPath.' существует (старое имя '.$file.')');
|
158
|
|
|
|
159
|
|
|
$thumb = $this->phpThumb->create($file);
|
160
|
|
|
$thumb->resize($sizes[0], $sizes[1]);
|
161
|
|
|
$thumb->save($newPath);
|
162
|
|
|
chmod($newPath, 0775);
|
163
|
|
|
}
|
164
|
|
|
}
|
165
|
|
|
|
166
|
|
|
/**
|
167
|
|
|
* @param $file
|
168
|
|
|
* @param $productId
|
169
|
|
|
* @param $type
|
170
|
|
|
*
|
171
|
|
|
* @return BProductImg
|
172
|
|
|
* @throws CDbException
|
173
|
|
|
* @throws WarningException
|
174
|
|
|
* @internal param $filePath
|
175
|
|
|
* @internal param string $file
|
176
|
|
|
*/
|
177
|
|
|
protected function createProductImageRecord($file, $productId, $type)
|
178
|
|
|
{
|
179
|
|
|
$fileName = pathinfo($file, PATHINFO_BASENAME);
|
180
|
|
|
$fileName = $this->normalizeFileName($fileName);
|
181
|
|
|
|
182
|
|
|
$criteria = new CDbCriteria();
|
183
|
|
|
$criteria->compare('name', $fileName);
|
184
|
|
|
$command = $this->commandBuilder->createFindCommand($this->tables['productImage'], $criteria);
|
185
|
|
|
$result = $command->queryRow();
|
186
|
|
|
|
187
|
|
|
if( !$result )
|
188
|
|
|
{
|
189
|
|
|
$command = $this->commandBuilder->createInsertCommand($this->tables['productImage'], array(
|
190
|
|
|
'parent' => $productId,
|
191
|
|
|
'name' => $fileName,
|
192
|
|
|
'type' => $type
|
193
|
|
|
));
|
194
|
|
|
|
195
|
|
|
if( !$command->execute() )
|
196
|
|
|
{
|
197
|
|
|
throw new WarningException('Ошибака записи файла '.$fileName.' в БД product_id = '.$productId);
|
198
|
|
|
}
|
199
|
|
|
}
|
200
|
|
|
|
201
|
|
|
return $fileName;
|
202
|
|
|
}
|
203
|
|
|
|
204
|
|
|
protected function getProductIdByAttribute($attribute, $value)
|
205
|
|
|
{
|
206
|
|
|
if( is_null($this->productIdsCache) )
|
207
|
|
|
{
|
208
|
|
|
$this->productIdsCache = array();
|
209
|
|
|
|
210
|
|
|
$criteria = new CDbCriteria();
|
211
|
|
|
$criteria->select = array($attribute, 'id');
|
212
|
|
|
$command = $this->commandBuilder->createFindCommand($this->tables['product'], $criteria);
|
213
|
|
|
|
214
|
|
|
foreach($command->queryAll() as $data)
|
215
|
|
|
$this->productIdsCache[$data['id']] = $data[$attribute];
|
216
|
|
|
}
|
217
|
|
|
|
218
|
|
|
return array_search($value, $this->productIdsCache);
|
219
|
|
|
}
|
220
|
|
|
|
221
|
|
|
protected function normalizeFileName($file)
|
222
|
|
|
{
|
223
|
|
|
$name = pathinfo($file, PATHINFO_FILENAME);
|
224
|
|
|
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
225
|
|
|
|
226
|
|
|
return strtolower(Utils::translite($name)).'.'.$ext;
|
227
|
|
|
}
|
228
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.