Failed Conditions
Pull Request — experimental/sf (#3236)
by Kentaro
144:19 queued 116:23
created

Category   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 455
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 5

Test Coverage

Coverage 74.26%

Importance

Changes 0
Metric Value
dl 0
loc 455
ccs 75
cts 101
cp 0.7426
rs 9.36
c 0
b 0
f 0
wmc 38
lcom 4
cbo 5

31 Methods

Rating   Name   Duplication   Size   Complexity  
A __toString() 0 4 1
A countBranches() 0 10 2
A calcChildrenSortNo() 0 11 2
A getParents() 0 7 1
A getPath() 0 17 4
A getNameWithLevel() 0 4 1
A getDescendants() 0 16 3
A getSelfAndDescendants() 0 4 1
A hasProductCategories() 0 9 1
A __construct() 0 5 1
A getId() 0 4 1
A setName() 0 6 1
A getName() 0 4 1
A setHierarchy() 0 6 1
A getHierarchy() 0 4 1
A setSortNo() 0 6 1
A getSortNo() 0 4 1
A setCreateDate() 0 6 1
A getCreateDate() 0 4 1
A setUpdateDate() 0 6 1
A getUpdateDate() 0 4 1
A addProductCategory() 0 6 1
A removeProductCategory() 0 4 1
A getProductCategories() 0 4 1
A addChild() 0 6 1
A removeChild() 0 4 1
A getChildren() 0 4 1
A setParent() 0 6 1
A getParent() 0 4 1
A setCreator() 0 6 1
A getCreator() 0 4 1
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Entity;
15
16
use Doctrine\Common\Collections\Criteria;
17
use Doctrine\ORM\Mapping as ORM;
18
19
/**
20
 * Category
21
 *
22
 * @ORM\Table(name="dtb_category")
23
 * @ORM\InheritanceType("SINGLE_TABLE")
24
 * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255)
25
 * @ORM\HasLifecycleCallbacks()
26
 * @ORM\Entity(repositoryClass="Eccube\Repository\CategoryRepository")
27
 */
28
class Category extends \Eccube\Entity\AbstractEntity
29
{
30
    /**
31
     * @return string
32
     */
33
    public function __toString()
34
    {
35
        return (string) $this->getName();
36
    }
37
38
    /**
39
     * @return integer
40
     */
41
    public function countBranches()
42
    {
43
        $count = 1;
44
45
        foreach ($this->getChildren() as $Child) {
46
            $count += $Child->countBranches();
47
        }
48
49
        return $count;
50
    }
51
52
    /**
53
     * @param  \Doctrine\ORM\EntityManager $em
54
     * @param  integer                     $sortNo
55
     *
56
     * @return \Eccube\Entity\Category
57
     */
58
    public function calcChildrenSortNo(\Doctrine\ORM\EntityManager $em, $sortNo)
59
    {
60
        $this->setSortNo($this->getSortNo() + $sortNo);
61
        $em->persist($this);
62
63
        foreach ($this->getChildren() as $Child) {
64
            $Child->calcChildrenSortNo($em, $sortNo);
65
        }
66
67
        return $this;
68
    }
69
70 1
    public function getParents()
71
    {
72 1
        $path = $this->getPath();
73 1
        array_pop($path);
74
75 1
        return $path;
76
    }
77
78 19
    public function getPath()
79
    {
80 19
        $path = [];
81 19
        $Category = $this;
82
83 19
        $max = 10;
84 19
        while ($max--) {
85 19
            $path[] = $Category;
86
87 19
            $Category = $Category->getParent();
88 19
            if (!$Category || !$Category->getId()) {
89 19
                break;
90
            }
91
        }
92
93 19
        return array_reverse($path);
94
    }
95
96 133
    public function getNameWithLevel()
97
    {
98 133
        return str_repeat(' ', $this->getHierarchy() - 1).$this->getName();
99
    }
100
101 140
    public function getDescendants()
102
    {
103 140
        $DescendantCategories = [];
104
105 140
        $max = 10;
0 ignored issues
show
Unused Code introduced by
$max is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
106 140
        $ChildCategories = $this->getChildren();
107 140
        foreach ($ChildCategories as $ChildCategory) {
108 138
            $DescendantCategories[$ChildCategory->getId()] = $ChildCategory;
109 138
            $DescendantCategories2 = $ChildCategory->getDescendants();
110 138
            foreach ($DescendantCategories2 as $DescendantCategory) {
111 138
                $DescendantCategories[$DescendantCategory->getId()] = $DescendantCategory;
112
            }
113
        }
114
115 140
        return $DescendantCategories;
116
    }
117
118 140
    public function getSelfAndDescendants()
119
    {
120 140
        return array_merge([$this], $this->getDescendants());
121
    }
122
123
    /**
124
     * カテゴリに紐づく商品があるかどうかを調べる.
125
     *
126
     * ProductCategoriesはExtra Lazyのため, lengthやcountで評価した際にはCOUNTのSQLが発行されるが,
127
     * COUNT自体が重いので, LIMIT 1で取得し存在チェックを行う.
128
     *
129
     * @see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#filtering-collections
130
     *
131
     * @return bool
132
     */
133 1
    public function hasProductCategories()
134
    {
135 1
        $criteria = Criteria::create()
136 1
            ->orderBy(['category_id' => Criteria::ASC])
137 1
            ->setFirstResult(0)
138 1
            ->setMaxResults(1);
139
140 1
        return $this->ProductCategories->matching($criteria)->count() === 1;
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Doctrine\Common\Collections\Collection as the method matching() does only exist in the following implementations of said interface: Doctrine\Common\Collections\ArrayCollection, Doctrine\ORM\LazyCriteriaCollection, Doctrine\ORM\PersistentCollection, Eccube\Service\Calculator\OrderItemCollection, Eccube\Service\PurchaseFlow\ItemCollection.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
141
    }
142
143
    /**
144
     * @var int
145
     *
146
     * @ORM\Column(name="id", type="integer", options={"unsigned":true})
147
     * @ORM\Id
148
     * @ORM\GeneratedValue(strategy="IDENTITY")
149
     */
150
    private $id;
151
152
    /**
153
     * @var string
154
     *
155
     * @ORM\Column(name="category_name", type="string", length=255)
156
     */
157
    private $name;
158
159
    /**
160
     * @var int
161
     *
162
     * @ORM\Column(name="hierarchy", type="integer")
163
     */
164
    private $hierarchy;
165
166
    /**
167
     * @var int
168
     *
169
     * @ORM\Column(name="sort_no", type="integer")
170
     */
171
    private $sort_no;
172
173
    /**
174
     * @var \DateTime
175
     *
176
     * @ORM\Column(name="create_date", type="datetimetz")
177
     */
178
    private $create_date;
179
180
    /**
181
     * @var \DateTime
182
     *
183
     * @ORM\Column(name="update_date", type="datetimetz")
184
     */
185
    private $update_date;
186
187
    /**
188
     * @var \Doctrine\Common\Collections\Collection
189
     *
190
     * @ORM\OneToMany(targetEntity="Eccube\Entity\ProductCategory", mappedBy="Category", fetch="EXTRA_LAZY")
191
     */
192
    private $ProductCategories;
193
194
    /**
195
     * @var \Doctrine\Common\Collections\Collection
196
     *
197
     * @ORM\OneToMany(targetEntity="Eccube\Entity\Category", mappedBy="Parent")
198
     * @ORM\OrderBy({
199
     *     "sort_no"="DESC"
200
     * })
201
     */
202
    private $Children;
203
204
    /**
205
     * @var \Eccube\Entity\Category
206
     *
207
     * @ORM\ManyToOne(targetEntity="Eccube\Entity\Category", inversedBy="Children")
208
     * @ORM\JoinColumns({
209
     *   @ORM\JoinColumn(name="parent_category_id", referencedColumnName="id")
210
     * })
211
     */
212
    private $Parent;
213
214
    /**
215
     * @var \Eccube\Entity\Member
216
     *
217
     * @ORM\ManyToOne(targetEntity="Eccube\Entity\Member")
218
     * @ORM\JoinColumns({
219
     *   @ORM\JoinColumn(name="creator_id", referencedColumnName="id")
220
     * })
221
     */
222
    private $Creator;
223
224
    /**
225
     * Constructor
226
     */
227 33
    public function __construct()
228
    {
229 33
        $this->ProductCategories = new \Doctrine\Common\Collections\ArrayCollection();
230 33
        $this->Children = new \Doctrine\Common\Collections\ArrayCollection();
231
    }
232
233
    /**
234
     * Get id.
235
     *
236
     * @return int
237
     */
238 472
    public function getId()
239
    {
240 472
        return $this->id;
241
    }
242
243
    /**
244
     * Set name.
245
     *
246
     * @param string $name
247
     *
248
     * @return Category
249
     */
250 18
    public function setName($name)
251
    {
252 18
        $this->name = $name;
253
254 18
        return $this;
255
    }
256
257
    /**
258
     * Get name.
259
     *
260
     * @return string
261
     */
262 163
    public function getName()
263
    {
264 163
        return $this->name;
265
    }
266
267
    /**
268
     * Set hierarchy.
269
     *
270
     * @param int $hierarchy
271
     *
272
     * @return Category
273
     */
274 15
    public function setHierarchy($hierarchy)
275
    {
276 15
        $this->hierarchy = $hierarchy;
277
278 15
        return $this;
279
    }
280
281
    /**
282
     * Get hierarchy.
283
     *
284
     * @return int
285
     */
286 143
    public function getHierarchy()
287
    {
288 143
        return $this->hierarchy;
289
    }
290
291
    /**
292
     * Set sortNo.
293
     *
294
     * @param int $sortNo
295
     *
296
     * @return Category
297
     */
298 13
    public function setSortNo($sortNo)
299
    {
300 13
        $this->sort_no = $sortNo;
301
302 13
        return $this;
303
    }
304
305
    /**
306
     * Get sortNo.
307
     *
308
     * @return int
309
     */
310 11
    public function getSortNo()
311
    {
312 11
        return $this->sort_no;
313
    }
314
315
    /**
316
     * Set createDate.
317
     *
318
     * @param \DateTime $createDate
319
     *
320
     * @return Category
321
     */
322 26
    public function setCreateDate($createDate)
323
    {
324 26
        $this->create_date = $createDate;
325
326 26
        return $this;
327
    }
328
329
    /**
330
     * Get createDate.
331
     *
332
     * @return \DateTime
333
     */
334
    public function getCreateDate()
335
    {
336
        return $this->create_date;
337
    }
338
339
    /**
340
     * Set updateDate.
341
     *
342
     * @param \DateTime $updateDate
343
     *
344
     * @return Category
345
     */
346 26
    public function setUpdateDate($updateDate)
347
    {
348 26
        $this->update_date = $updateDate;
349
350 26
        return $this;
351
    }
352
353
    /**
354
     * Get updateDate.
355
     *
356
     * @return \DateTime
357
     */
358 1
    public function getUpdateDate()
359
    {
360 1
        return $this->update_date;
361
    }
362
363
    /**
364
     * Add productCategory.
365
     *
366
     * @param \Eccube\Entity\ProductCategory $productCategory
367
     *
368
     * @return Category
369
     */
370
    public function addProductCategory(\Eccube\Entity\ProductCategory $productCategory)
371
    {
372
        $this->ProductCategories[] = $productCategory;
373
374
        return $this;
375
    }
376
377
    /**
378
     * Remove productCategory.
379
     *
380
     * @param \Eccube\Entity\ProductCategory $productCategory
381
     *
382
     * @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
383
     */
384
    public function removeProductCategory(\Eccube\Entity\ProductCategory $productCategory)
385
    {
386
        return $this->ProductCategories->removeElement($productCategory);
387
    }
388
389
    /**
390
     * Get productCategories.
391
     *
392
     * @return \Doctrine\Common\Collections\Collection
393
     */
394
    public function getProductCategories()
395
    {
396
        return $this->ProductCategories;
397
    }
398
399
    /**
400
     * Add child.
401
     *
402
     * @param \Eccube\Entity\Category $child
403
     *
404
     * @return Category
405
     */
406 21
    public function addChild(\Eccube\Entity\Category $child)
407
    {
408 21
        $this->Children[] = $child;
409
410 21
        return $this;
411
    }
412
413
    /**
414
     * Remove child.
415
     *
416
     * @param \Eccube\Entity\Category $child
417
     *
418
     * @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
419
     */
420
    public function removeChild(\Eccube\Entity\Category $child)
421
    {
422
        return $this->Children->removeElement($child);
423
    }
424
425
    /**
426
     * Get children.
427
     *
428
     * @return \Doctrine\Common\Collections\Collection
429
     */
430 144
    public function getChildren()
431
    {
432 144
        return $this->Children;
433
    }
434
435
    /**
436
     * Set parent.
437
     *
438
     * @param \Eccube\Entity\Category|null $parent
439
     *
440
     * @return Category
441
     */
442 25
    public function setParent(\Eccube\Entity\Category $parent = null)
443
    {
444 25
        $this->Parent = $parent;
445
446 25
        return $this;
447
    }
448
449
    /**
450
     * Get parent.
451
     *
452
     * @return \Eccube\Entity\Category|null
453
     */
454 27
    public function getParent()
455
    {
456 27
        return $this->Parent;
457
    }
458
459
    /**
460
     * Set creator.
461
     *
462
     * @param \Eccube\Entity\Member|null $creator
463
     *
464
     * @return Category
465
     */
466 12
    public function setCreator(\Eccube\Entity\Member $creator = null)
467
    {
468 12
        $this->Creator = $creator;
469
470 12
        return $this;
471
    }
472
473
    /**
474
     * Get creator.
475
     *
476
     * @return \Eccube\Entity\Member|null
477
     */
478
    public function getCreator()
479
    {
480
        return $this->Creator;
481
    }
482
}
483