Completed
Push — master ( e0db1d...82088e )
by Paweł
11:28
created

RulesMatcher::process()   D

Complexity

Conditions 9
Paths 13

Size

Total Lines 45
Code Lines 27

Duplication

Lines 8
Ratio 17.78 %

Importance

Changes 0
Metric Value
dl 8
loc 45
rs 4.909
c 0
b 0
f 0
cc 9
eloc 27
nc 13
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Superdesk Web Publisher Core Bundle.
7
 *
8
 * Copyright 2018 Sourcefabric z.ú. and contributors.
9
 *
10
 * For the full copyright and license information, please see the
11
 * AUTHORS and LICENSE files distributed with this source code.
12
 *
13
 * @copyright 2018 Sourcefabric z.ú
14
 * @license http://www.superdesk.org/license
15
 */
16
17
namespace SWP\Bundle\CoreBundle\Matcher;
18
19
use SWP\Bundle\ContentBundle\Factory\ArticleFactoryInterface;
20
use SWP\Bundle\ContentBundle\Model\ArticleInterface;
21
use SWP\Bundle\CoreBundle\Model\PackageInterface;
22
use SWP\Bundle\CoreBundle\Model\PublishDestinationInterface;
23
use SWP\Bundle\CoreBundle\Processor\RulesProcessorInterface;
24
use SWP\Bundle\CoreBundle\Provider\PublishDestinationProviderInterface;
25
use SWP\Bundle\MultiTenancyBundle\MultiTenancyEvents;
26
use SWP\Component\Rule\Evaluator\RuleEvaluatorInterface;
27
use SWP\Component\Rule\Repository\RuleRepositoryInterface;
28
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
29
30
class RulesMatcher implements RulesMatcherInterface
31
{
32
    /**
33
     * @var EventDispatcherInterface
34
     */
35
    private $eventDispatcher;
36
37
    /**
38
     * @var RuleRepositoryInterface
39
     */
40
    private $ruleRepository;
41
42
    /**
43
     * @var RuleEvaluatorInterface
44
     */
45
    private $ruleEvaluator;
46
47
    /**
48
     * @var RulesProcessorInterface
49
     */
50
    private $rulesProcessor;
51
52
    /**
53
     * @var ArticleFactoryInterface
54
     */
55
    private $articleFactory;
56
57
    /**
58
     * @var PublishDestinationProviderInterface
59
     */
60
    private $publishDestinationProvider;
61
62
    /**
63
     * RulesMatcher constructor.
64
     *
65
     * @param EventDispatcherInterface            $eventDispatcher
66
     * @param RuleRepositoryInterface             $ruleRepository
67
     * @param RuleEvaluatorInterface              $ruleEvaluator
68
     * @param RulesProcessorInterface             $rulesProcessor
69
     * @param ArticleFactoryInterface             $articleFactory
70
     * @param PublishDestinationProviderInterface $publishDestinationProvider
71
     */
72
    public function __construct(
73
        EventDispatcherInterface $eventDispatcher,
74
        RuleRepositoryInterface $ruleRepository,
75
        RuleEvaluatorInterface $ruleEvaluator,
76
        RulesProcessorInterface $rulesProcessor,
77
        ArticleFactoryInterface $articleFactory,
78
        PublishDestinationProviderInterface $publishDestinationProvider
79
    ) {
80
        $this->eventDispatcher = $eventDispatcher;
81
        $this->ruleRepository = $ruleRepository;
82
        $this->ruleEvaluator = $ruleEvaluator;
83
        $this->rulesProcessor = $rulesProcessor;
84
        $this->articleFactory = $articleFactory;
85
        $this->publishDestinationProvider = $publishDestinationProvider;
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function getMatchedRules(PackageInterface $package): array
92
    {
93
        $article = $this->articleFactory->createFromPackage($package);
94
        $this->eventDispatcher->dispatch(MultiTenancyEvents::TENANTABLE_DISABLE);
95
96
        $destinations = $this->publishDestinationProvider->getDestinations($package);
97
        $evaluatedOrganizationRules = $this->processPackageRules($package);
98
        $evaluatedRules = $this->processArticleRules($article, $destinations);
99
        $processedRules = $this->rulesProcessor->process(array_merge($evaluatedOrganizationRules, $evaluatedRules));
100
101
        return $this->process($processedRules, $destinations);
102
    }
103
104
    private function process(array $processedRules, array $destinations): array
105
    {
106
        if (empty((array) $processedRules['tenants'])) {
107 View Code Duplication
            foreach ($destinations as $destination) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
108
                $processedRules['organization'] = $destination->getOrganization();
109
                $processedRules['tenants'][] = $this->createTenantArrayFromDestination($destination);
110
            }
111
112
            return $processedRules;
113
        }
114
115
        if (empty((array) $processedRules['tenants'])) {
116
            return [];
117
        }
118
119
        $rules = [];
120 View Code Duplication
        foreach ($destinations as $destinationKey => $destination) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
121
            $rules['organization'] = $destination->getOrganization();
122
            $rules['tenants'][] = $this->createTenantArrayFromDestination($destination);
123
        }
124
125
        if (empty($rules)) {
126
            return $processedRules;
127
        }
128
129
        foreach ((array) $rules['tenants'] as $key => $rule) {
130
            foreach ((array) $processedRules['tenants'] as $tenant) {
131
                if ($tenant['tenant'] === $rule['tenant']) {
132
                    $rules['tenants'][$key] = $rule;
133
                } else {
134
                    $rules['tenants'][] = $tenant;
135
                }
136
            }
137
        }
138
139
        $ids = array_column($rules['tenants'], 'tenant');
140
        $ids = array_unique($ids);
141
        $tenants = array_filter($rules['tenants'], function ($key, $value) use ($ids) {
142
            return \in_array($value, \array_keys($ids));
143
        }, ARRAY_FILTER_USE_BOTH);
144
145
        $rules['tenants'] = $tenants;
146
147
        return $rules;
148
    }
149
150
    private function createTenantArrayFromDestination(PublishDestinationInterface $destination): array
151
    {
152
        return [
153
            'tenant' => $destination->getTenant(),
154
            'route' => $destination->getRoute(),
155
            'fbia' => $destination->isFbia(),
156
            'published' => $destination->isPublished(),
157
        ];
158
    }
159
160
    private function processPackageRules(PackageInterface $package): array
161
    {
162
        $organizationRules = $this->ruleRepository->findBy(['tenantCode' => null], ['priority' => 'desc']);
163
164
        $evaluatedOrganizationRules = [];
165
        foreach ($organizationRules as $rule) {
166
            if ($this->ruleEvaluator->evaluate($rule, $package)) {
167
                $evaluatedOrganizationRules[] = $rule;
168
            }
169
        }
170
171
        return $evaluatedOrganizationRules;
172
    }
173
174
    private function processArticleRules(ArticleInterface $article, array $destinations): array
175
    {
176
        $qb = $this->ruleRepository->createQueryBuilder('r');
177
178
        if (!empty($destinations)) {
179
            $tenants = [];
180
            foreach ($destinations as $destination) {
181
                $tenants[] = $destination->getTenant()->getCode();
182
            }
183
184
            $qb
185
                ->where('r.tenantCode NOT IN (:tenants)')
186
                ->setParameter('tenants', $tenants);
187
        }
188
189
        $tenantRules = $qb
190
            ->andWhere('r.tenantCode IS NOT NULL')
191
            ->orderBy('r.priority', 'desc')
192
            ->getQuery()
193
            ->getResult();
194
195
        $evaluatedRules = [];
196
        foreach ((array) $tenantRules as $rule) {
197
            if ($this->ruleEvaluator->evaluate($rule, $article)) {
198
                $evaluatedRules[] = $rule;
199
            }
200
        }
201
202
        return $evaluatedRules;
203
    }
204
}
205