ExplicitSubscriber   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 7
Bugs 2 Features 2
Metric Value
c 7
b 2
f 2
dl 0
loc 149
wmc 20
lcom 1
cbo 8
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getSubscribedEvents() 0 7 1
A configureOptions() 0 15 1
B handlePersist() 0 54 8
A renameNode() 0 8 2
A resolveParent() 0 10 2
B validateOptions() 0 14 5
1
<?php
2
3
/*
4
 * This file is part of Sulu.
5
 *
6
 * (c) MASSIVE ART WebServices GmbH
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Sulu\Component\DocumentManager\Subscriber\Behavior\Path;
13
14
use PHPCR\NodeInterface;
15
use PHPCR\Util\PathHelper;
16
use Sulu\Component\DocumentManager\DocumentHelper;
17
use Sulu\Component\DocumentManager\DocumentStrategyInterface;
18
use Sulu\Component\DocumentManager\Event\ConfigureOptionsEvent;
19
use Sulu\Component\DocumentManager\Event\PersistEvent;
20
use Sulu\Component\DocumentManager\Events;
21
use Sulu\Component\DocumentManager\Exception\DocumentManagerException;
22
use Sulu\Component\DocumentManager\NodeManager;
23
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
24
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
25
26
/**
27
 * Populates or creates the node and/or parent node based on explicit
28
 * options.
29
 */
30
class ExplicitSubscriber implements EventSubscriberInterface
31
{
32
    /**
33
     * @var DocumentStrategyInterface
34
     */
35
    private $strategy;
36
37
    /**
38
     * @var NodeManager
39
     */
40
    private $nodeManager;
41
42
    /**
43
     * @param DocumentStrategyInterface $strategy
44
     * @param NodeManager $nodeManager
45
     */
46
    public function __construct(
47
        DocumentStrategyInterface $strategy,
48
        NodeManager $nodeManager
49
    ) {
50
        $this->strategy = $strategy;
51
        $this->nodeManager = $nodeManager;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57
    public static function getSubscribedEvents()
58
    {
59
        return [
60
            Events::PERSIST => ['handlePersist', 485],
61
            Events::CONFIGURE_OPTIONS => 'configureOptions',
62
        ];
63
    }
64
65
    /**
66
     * @param ConfigureOptionsEvent $event
67
     */
68
    public function configureOptions(ConfigureOptionsEvent $event)
69
    {
70
        $options = $event->getOptions();
71
        $options->setDefaults([
72
            'path' => null,
73
            'node_name' => null,
74
            'parent_path' => null,
75
            'auto_create' => false,
76
        ]);
77
78
        $options->setAllowedTypes('path', ['null', 'string']);
79
        $options->setAllowedTypes('node_name', ['null', 'string']);
80
        $options->setAllowedTypes('parent_path', ['null', 'string']);
81
        $options->setAllowedTypes('auto_create', 'bool');
82
    }
83
84
    /**
85
     * @param PersistEvent $event
86
     *
87
     * @throws DocumentManagerException
88
     */
89
    public function handlePersist(PersistEvent $event)
90
    {
91
        $options = $event->getOptions();
92
        $this->validateOptions($options);
0 ignored issues
show
Documentation introduced by
$options is of type object<Symfony\Component...solver\OptionsResolver>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
93
        $document = $event->getDocument();
94
        $parentPath = null;
95
        $nodeName = null;
96
97
        if ($options['path']) {
98
            $parentPath = PathHelper::getParentPath($options['path']);
99
            $nodeName = PathHelper::getNodeName($options['path']);
100
        }
101
102
        if ($options['parent_path']) {
103
            $parentPath = $options['parent_path'];
104
        }
105
106
        if ($parentPath) {
107
            $event->setParentNode(
108
                $this->resolveParent($parentPath, $options)
0 ignored issues
show
Documentation introduced by
$options is of type object<Symfony\Component...solver\OptionsResolver>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
109
            );
110
        }
111
112
        if ($options['node_name']) {
113
            if (!$event->hasParentNode()) {
114
                throw new DocumentManagerException(sprintf(
115
                    'The "node_name" option can only be used either with the "parent_path" option ' .
116
                    'or when a parent node has been established by a previous subscriber. ' .
117
                    'When persisting document: %s',
118
                    DocumentHelper::getDebugTitle($document)
119
                ));
120
            }
121
122
            $nodeName = $options['node_name'];
123
        }
124
125
        if (!$nodeName) {
126
            return;
127
        }
128
129
        if ($event->hasNode()) {
130
            $this->renameNode($event->getNode(), $nodeName);
131
132
            return;
133
        }
134
135
        $node = $this->strategy->createNodeForDocument(
136
            $document,
137
            $event->getParentNode(),
138
            $nodeName
139
        );
140
141
        $event->setNode($node);
142
    }
143
144
    private function renameNode(NodeInterface $node, $nodeName)
145
    {
146
        if ($node->getName() == $nodeName) {
147
            return;
148
        }
149
150
        $node->rename($nodeName);
151
    }
152
153
    private function resolveParent($parentPath, array $options)
154
    {
155
        $autoCreate = $options['auto_create'];
156
157
        if ($autoCreate) {
158
            return $this->nodeManager->createPath($parentPath);
159
        }
160
161
        return $this->nodeManager->find($parentPath);
162
    }
163
164
    private function validateOptions(array $options)
165
    {
166
        if ($options['path'] && $options['node_name']) {
167
            throw new InvalidOptionsException(
168
                'Options "path" and "name" are mutually exclusive'
169
            );
170
        }
171
172
        if ($options['path'] && $options['parent_path']) {
173
            throw new InvalidOptionsException(
174
                'Options "path" and "parent_path" are mutually exclusive'
175
            );
176
        }
177
    }
178
}
179