Passed
Push — master ( 05f55a...1029e9 )
by
unknown
05:27
created

Document::parseResults()   C

Complexity

Conditions 11
Paths 74

Size

Total Lines 83
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 58
c 0
b 0
f 0
dl 0
loc 83
rs 6.7696
cc 11
nc 74
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*************************************************************************************/
3
/*      This file is part of the Thelia package.                                     */
4
/*                                                                                   */
5
/*      Copyright (c) OpenStudio                                                     */
6
/*      email : [email protected]                                                       */
7
/*      web : http://www.thelia.net                                                  */
8
/*                                                                                   */
9
/*      For the full copyright and license information, please view the LICENSE.txt  */
10
/*      file that was distributed with this source code.                             */
11
/*************************************************************************************/
12
13
namespace Thelia\Core\Template\Loop;
14
15
use Propel\Runtime\ActiveQuery\ModelCriteria;
16
use Thelia\Core\Template\Element\BaseI18nLoop;
17
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
18
use Thelia\Core\Template\Loop\Argument\Argument;
19
use Thelia\Core\Event\Document\DocumentEvent;
20
use Thelia\Core\Event\TheliaEvents;
21
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
22
use Thelia\Model\ProductDocument;
23
use Thelia\Model\ProductDocumentQuery;
24
use Thelia\Type\BooleanOrBothType;
25
use Thelia\Type\TypeCollection;
26
use Thelia\Type\EnumListType;
27
use Propel\Runtime\ActiveQuery\Criteria;
28
use Thelia\Model\ConfigQuery;
29
use Thelia\Core\Template\Element\LoopResultRow;
30
use Thelia\Core\Template\Element\LoopResult;
31
use Thelia\Log\Tlog;
32
33
/**
34
 * The document loop
35
 *
36
 * @author Franck Allimant <[email protected]>
37
 *
38
 * {@inheritdoc}
39
 * @method int[] getId()
40
 * @method int[] getExclude()
41
 * @method bool|string getVisible()
42
 * @method int getLang()
43
 * @method int getCategory()
44
 * @method int getProduct()
45
 * @method int getFolder()
46
 * @method int getContent()
47
 * @method string getSource()
48
 * @method int getSourceId()
49
 * @method bool getNewsletter()
50
 * @method string getQueryNamespace()
51
 * @method string[] getOrder()
52
 */
53
class Document extends BaseI18nLoop implements PropelSearchLoopInterface
54
{
55
    protected $objectType;
56
    protected $objectId;
57
58
    protected $timestampable = true;
59
60
    /**
61
     * @var array Possible standard document sources
62
     */
63
    protected $possible_sources = array('category', 'product', 'folder', 'content', 'brand');
64
65
    /**
66
     * @return \Thelia\Core\Template\Loop\Argument\ArgumentCollection
67
     */
68
    protected function getArgDefinitions()
69
    {
70
        $collection = new ArgumentCollection(
71
            Argument::createIntListTypeArgument('id'),
72
            Argument::createIntListTypeArgument('exclude'),
73
            Argument::createBooleanOrBothTypeArgument('visible', 1),
74
            new Argument(
75
                'order',
76
                new TypeCollection(
77
                    new EnumListType(array('alpha', 'alpha-reverse', 'manual', 'manual-reverse', 'random'))
78
                ),
79
                'manual'
80
            ),
81
            Argument::createIntTypeArgument('lang'),
82
            Argument::createIntTypeArgument('category'),
83
            Argument::createIntTypeArgument('product'),
84
            Argument::createIntTypeArgument('folder'),
85
            Argument::createIntTypeArgument('content'),
86
            Argument::createAnyTypeArgument('source'),
87
            Argument::createIntTypeArgument('source_id'),
88
            Argument::createBooleanTypeArgument('force_return', true),
89
            Argument::createAnyTypeArgument('query_namespace', 'Thelia\\Model'),
90
            Argument::createBooleanTypeArgument('with_prev_next_info', false)
91
        );
92
93
        // Add possible document sources
94
        foreach ($this->possible_sources as $source) {
95
            $collection->addArgument(Argument::createIntTypeArgument($source));
96
        }
97
98
        return $collection;
99
    }
100
101
    /**
102
     * Dynamically create the search query, and set the proper filter and order
103
     *
104
     * @param  string        $source    a valid source identifier (@see $possible_sources)
105
     * @param  int           $object_id the source object ID
106
     * @return ModelCriteria the propel Query object
107
     */
108
    protected function createSearchQuery($source, $object_id)
109
    {
110
        $object = ucfirst($source);
111
112
        $ns = $this->getQueryNamespace();
113
114
        if ('\\' !== $ns[0]) {
115
            $ns = '\\'.$ns;
116
        }
117
118
        $queryClass   = sprintf("%s\\%sDocumentQuery", $ns, $object);
119
        $filterMethod = sprintf("filterBy%sId", $object);
120
121
        // xxxDocumentQuery::create()
122
        $method = new \ReflectionMethod($queryClass, 'create');
123
        $search = $method->invoke(null); // Static !
124
125
        // $query->filterByXXX(id)
126
        if (! \is_null($object_id)) {
0 ignored issues
show
introduced by
The condition is_null($object_id) is always false.
Loading history...
127
            $method = new \ReflectionMethod($queryClass, $filterMethod);
128
            $method->invoke($search, $object_id);
129
        }
130
131
        $orders  = $this->getOrder();
132
133
        // Results ordering
134
        foreach ($orders as $order) {
135
            switch ($order) {
136
                case "alpha":
137
                    $search->addAscendingOrderByColumn('i18n_TITLE');
138
                    break;
139
                case "alpha-reverse":
140
                    $search->addDescendingOrderByColumn('i18n_TITLE');
141
                    break;
142
                case "manual-reverse":
143
                    $search->orderByPosition(Criteria::DESC);
144
                    break;
145
                case "manual":
146
                    $search->orderByPosition(Criteria::ASC);
147
                    break;
148
                case "random":
149
                    $search->clearOrderByColumns();
150
                    $search->addAscendingOrderByColumn('RAND()');
151
                    break(2);
152
                    break;
153
            }
154
        }
155
156
        return $search;
157
    }
158
159
    /**
160
     * Dynamically create the search query, and set the proper filter and order
161
     *
162
     * @param  string        $object_type (returned) the a valid source identifier (@see $possible_sources)
163
     * @param  string        $object_id   (returned) the ID of the source object
164
     * @return ModelCriteria the propel Query object
165
     */
166
    protected function getSearchQuery(&$object_type, &$object_id)
167
    {
168
        $search = null;
169
170
        // Check form source="product" source_id="123" style arguments
171
        $source = $this->getSource();
172
173
        if (! \is_null($source)) {
0 ignored issues
show
introduced by
The condition is_null($source) is always false.
Loading history...
174
            $source_id = $this->getSourceId();
175
            $id = $this->getId();
176
177
            if (\is_null($source_id) && \is_null($id)) {
0 ignored issues
show
introduced by
The condition is_null($source_id) is always false.
Loading history...
178
                throw new \InvalidArgumentException("If 'source' argument is specified, 'id' or 'source_id' argument should be specified");
179
            }
180
181
            $search = $this->createSearchQuery($source, $source_id);
182
183
            $object_type = $source;
184
            $object_id   = $source_id;
185
        } else {
186
            // Check for product="id" folder="id", etc. style arguments
187
            foreach ($this->possible_sources as $source) {
188
                $argValue = \intval($this->getArgValue($source));
189
190
                if ($argValue > 0) {
191
                    $search = $this->createSearchQuery($source, $argValue);
192
193
                    $object_type = $source;
194
                    $object_id   = $argValue;
195
196
                    break;
197
                }
198
            }
199
        }
200
201
        if ($search == null) {
202
            throw new \InvalidArgumentException(sprintf("Unable to find document source. Valid sources are %s", implode(',', $this->possible_sources)));
203
        }
204
205
        return $search;
206
    }
207
208
    public function buildModelCriteria()
209
    {
210
        // Select the proper query to use, and get the object type
211
        $this->objectType = $this->objectId = null;
212
213
        /** @var ProductDocumentQuery $search */
214
        $search = $this->getSearchQuery($this->objectType, $this->objectId);
215
216
        /* manage translations */
217
        $this->configureI18nProcessing($search);
218
219
        $id = $this->getId();
220
221
        if (! \is_null($id)) {
0 ignored issues
show
introduced by
The condition is_null($id) is always false.
Loading history...
222
            $search->filterById($id, Criteria::IN);
223
        }
224
225
        $exclude = $this->getExclude();
226
        if (!\is_null($exclude)) {
0 ignored issues
show
introduced by
The condition is_null($exclude) is always false.
Loading history...
227
            $search->filterById($exclude, Criteria::NOT_IN);
228
        }
229
230
        $visible = $this->getVisible();
231
        if ($visible !== BooleanOrBothType::ANY) {
232
            $search->filterByVisible($visible ? 1 : 0);
233
        }
234
235
        return $search;
236
    }
237
238
    public function parseResults(LoopResult $loopResult)
239
    {
240
        $baseSourceFilePath = ConfigQuery::read('documents_library_path');
241
        if ($baseSourceFilePath === null) {
242
            $baseSourceFilePath = THELIA_LOCAL_DIR . 'media' . DS . 'documents';
243
        } else {
244
            $baseSourceFilePath = THELIA_ROOT . $baseSourceFilePath;
245
        }
246
247
        /** @var ProductDocument $result */
248
        foreach ($loopResult->getResultDataCollection() as $result) {
249
            // Create document processing event
250
            $event = new DocumentEvent();
251
252
            // Put source document file path
253
            $sourceFilePath = sprintf(
254
                '%s/%s/%s',
255
                $baseSourceFilePath,
256
                $this->objectType,
257
                $result->getFile()
258
            );
259
260
            $event->setSourceFilepath($sourceFilePath);
261
            $event->setCacheSubdirectory($this->objectType);
262
263
            try {
264
                // Dispatch document processing event
265
                $this->dispatcher->dispatch(TheliaEvents::DOCUMENT_PROCESS, $event);
266
267
                $loopResultRow = new LoopResultRow($result);
268
269
                $loopResultRow
270
                    ->set("ID", $result->getId())
271
                    ->set("LOCALE", $this->locale)
272
                    ->set("DOCUMENT_FILE", $result->getFile())
273
                    ->set("DOCUMENT_URL", $event->getDocumentUrl())
274
                    ->set("DOCUMENT_PATH", $event->getDocumentPath())
275
                    ->set("ORIGINAL_DOCUMENT_PATH", $sourceFilePath)
276
                    ->set("TITLE", $result->getVirtualColumn('i18n_TITLE'))
277
                    ->set("CHAPO", $result->getVirtualColumn('i18n_CHAPO'))
278
                    ->set("DESCRIPTION", $result->getVirtualColumn('i18n_DESCRIPTION'))
279
                    ->set("POSTSCRIPTUM", $result->getVirtualColumn('i18n_POSTSCRIPTUM'))
280
                    ->set("VISIBLE", $result->getVisible())
281
                    ->set("POSITION", $result->getPosition())
282
                    ->set("OBJECT_TYPE", $this->objectType)
283
                    ->set("OBJECT_ID", $this->objectId)
284
                ;
285
286
                $isBackendContext = $this->getBackendContext();
287
                if ($this->getWithPrevNextInfo()) {
0 ignored issues
show
Bug introduced by
The method getWithPrevNextInfo() does not exist on Thelia\Core\Template\Loop\Document. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

287
                if ($this->/** @scrutinizer ignore-call */ getWithPrevNextInfo()) {
Loading history...
288
                    $previousQuery = $this->getSearchQuery($this->objectType, $this->objectId)
289
                        ->filterByPosition($result->getPosition(), Criteria::LESS_THAN);
290
                    if (! $isBackendContext) {
291
                        $previousQuery->filterByVisible(true);
292
                    }
293
                    $previous = $previousQuery
294
                        ->orderByPosition(Criteria::DESC)
295
                        ->findOne();
296
                    $nextQuery = $this->getSearchQuery($this->objectType, $this->objectId)
297
                        ->filterByPosition($result->getPosition(), Criteria::GREATER_THAN);
298
                    if (! $isBackendContext) {
299
                        $nextQuery->filterByVisible(true);
300
                    }
301
                    $next = $nextQuery
302
                        ->orderByPosition(Criteria::ASC)
303
                        ->findOne();
304
                    $loopResultRow
305
                        ->set("HAS_PREVIOUS", $previous != null ? 1 : 0)
306
                        ->set("HAS_NEXT", $next != null ? 1 : 0)
307
                        ->set("PREVIOUS", $previous != null ? $previous->getId() : -1)
308
                        ->set("NEXT", $next != null ? $next->getId() : -1);
309
                }
310
311
                $this->addOutputFields($loopResultRow, $result);
312
313
                $loopResult->addRow($loopResultRow);
314
            } catch (\Exception $ex) {
315
                // Ignore the result and log an error
316
                Tlog::getInstance()->addError(sprintf("Failed to process document in document loop: %s", $ex->getMessage()));
317
            }
318
        }
319
320
        return $loopResult;
321
    }
322
}
323