Failed Conditions
Pull Request — master (#1)
by Tibor
02:45
created

PathValidatorObserver   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 7
dl 0
loc 121
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
A execute() 0 14 3
A getOtherEntitiesWithPath() 0 16 4
A getErrorMessage() 0 18 2
A getEntityEditUrl() 0 7 1
getCurrentEntityType() 0 1 ?
getEntity() 0 1 ?
getEntityStoreIds() 0 1 ?
getEntityUrlPath() 0 1 ?
1
<?php
2
3
namespace Tkotosz\CatalogRouter\Observer;
4
5
use Magento\Backend\Model\UrlInterface;
6
use Magento\Framework\Event\Observer;
7
use Magento\Framework\Event\ObserverInterface;
8
use Magento\Framework\Exception\AlreadyExistsException;
9
use Magento\Framework\Model\AbstractModel;
10
use Magento\Store\Model\Store;
11
use Magento\Store\Model\StoreManagerInterface;
12
use Tkotosz\CatalogRouter\Api\CatalogUrlPathProviderInterface;
13
use Tkotosz\CatalogRouter\Model\EntityData;
14
use Tkotosz\CatalogRouter\Model\Service\UrlPathUsedCheckerContainer;
15
use Tkotosz\CatalogRouter\Model\UrlPath;
16
17
abstract class PathValidatorObserver implements ObserverInterface
18
{
19
    const ERROR_MESSAGE = 'The "%1" url path already used by a <a href="%2" target="_blank">%3 (id: %4)</a> in the %5 (id: %6) store';
20
21
    /**
22
     * @var UrlPathUsedCheckerContainer
23
     */
24
    protected $urlPathUsedChecker;
25
    
26
    /**
27
     * @var StoreManagerInterface
28
     */
29
    protected $storeManager;
30
    
31
    /**
32
     * @var CatalogUrlPathProviderInterface
33
     */
34
    protected $urlPathProvider;
35
    
36
    /**
37
     * @var UrlInterface
38
     */
39
    protected $urlProvider;
40
    
41
    /**
42
     * @var array
43
     */
44
    protected $entityEditUrls;
45
    
46
    /**
47
     * @param UrlPathUsedCheckerContainer     $urlPathUsedChecker
48
     * @param StoreManagerInterface           $storeManager
49
     * @param CatalogUrlPathProviderInterface $urlPathProvider
50
     * @param UrlInterface                    $urlProvider
51
     * @param array                           $entityEditUrls
52
     */
53
    public function __construct(
54
        UrlPathUsedCheckerContainer $urlPathUsedChecker,
55
        StoreManagerInterface $storeManager,
56
        CatalogUrlPathProviderInterface $urlPathProvider,
57
        UrlInterface $urlProvider,
58
        array $entityEditUrls
59
    ) {
60
        $this->urlPathUsedChecker = $urlPathUsedChecker;
61
        $this->storeManager = $storeManager;
62
        $this->urlPathProvider = $urlPathProvider;
63
        $this->urlProvider = $urlProvider;
64
        $this->entityEditUrls = $entityEditUrls;
65
    }
66
67
    /**
68
     * @param Observer $observer
69
     * @return void
70
     */
71
    public function execute(Observer $observer)
72
    {
73
        $entity = $this->getEntity($observer);
74
75
        foreach ($this->getEntityStoreIds($entity) as $storeId) {
76
            $urlPath = $this->getEntityUrlPath($entity, $storeId);
77
            $resolvedEntities = $this->getOtherEntitiesWithPath($urlPath, $storeId, $entity);
78
79
            if (count($resolvedEntities) > 0) {
80
                $store = $this->storeManager->getStore($storeId);
81
                throw new AlreadyExistsException($this->getErrorMessage($urlPath, $store, $resolvedEntities));
0 ignored issues
show
Compatibility introduced by
$store of type object<Magento\Store\Api\Data\StoreInterface> is not a sub-type of object<Magento\Store\Model\Store>. It seems like you assume a concrete implementation of the interface Magento\Store\Api\Data\StoreInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
82
            }
83
        }
84
    }
85
86
    protected function getOtherEntitiesWithPath(UrlPath $urlPath, int $storeId, AbstractModel $currentEntity)
87
    {
88
        $resolvedEntities = [];
89
90
        $currentEntityData = new EntityData($this->getCurrentEntityType(), $currentEntity->getId(), $urlPath->getLastPart());
91
92
        foreach ($this->urlPathUsedChecker->check($urlPath, $storeId) as $entity) {
93
            if ($entity->getType() == $currentEntityData->getType() && $entity->getId() == $currentEntityData->getId()) {
94
                continue;
95
            }
96
97
            $resolvedEntities[] = $entity;
98
        }
99
100
        return $resolvedEntities;
101
    }
102
103
    protected function getErrorMessage(UrlPath $urlPath, Store $store, array $entities)
104
    {
105
        $messages = [];
106
        
107
        foreach ($entities as $entity) {
108
            $messages[] = __(
109
                self::ERROR_MESSAGE,
110
                $urlPath->getFullPath(),
111
                $this->getEntityEditUrl($entity),
112
                $entity->getType(),
113
                $entity->getId(),
114
                $store->getName(),
115
                $store->getId()
116
            );
117
        }
118
119
        return __(join("<br>", $messages));
120
    }
121
122
    protected function getEntityEditUrl(EntityData $entity)
123
    {
124
        $editUrlPath = $this->entityEditUrls[$entity->getType()]['url_path'];
125
        $idParam = $this->entityEditUrls[$entity->getType()]['id_param'];
126
        
127
        return $this->urlProvider->getUrl($editUrlPath, [$idParam => $entity->getId()]);
128
    }
129
130
    abstract protected function getCurrentEntityType();
131
132
    abstract protected function getEntity(Observer $observer);
133
134
    abstract protected function getEntityStoreIds(AbstractModel $entity);
135
136
    abstract protected function getEntityUrlPath(AbstractModel $entity, int $storeId);
137
}
138