Completed
Push — develop ( e70242...efddeb )
by Mathias
65:39 queued 53:48
created

PurgeController   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 6
dl 0
loc 170
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A setLoadEvents() 0 6 1
D indexAction() 0 97 15
B listAction() 0 21 8
A entityToString() 0 14 3
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2018 Cross Solution <http://cross-solution.de>
8
 */
9
  
10
/** */
11
namespace Core\Controller\Console;
12
13
use Core\Console\ProgressBar;
14
use Core\Controller\Plugin\EntityEraser;
15
use Core\Entity\EntityInterface;
16
use Core\Service\EntityEraser\LoadEvent;
17
use Zend\Console\ColorInterface;
18
use Zend\EventManager\EventManagerInterface;
19
use Zend\Mvc\Console\Controller\AbstractConsoleController;
20
21
/**
22
 * Purge console action controller
23
 * 
24
 * @author Mathias Gelhausen <[email protected]>
25
 * @todo write test 
26
 */
27
class PurgeController extends AbstractConsoleController
28
{
29
    /**
30
     *
31
     *
32
     * @var \Core\EventManager\EventManager
33
     */
34
    private $loadEvents;
35
36
    /**
37
     * @param \Core\EventManager\EventManager $loadEvents
38
     *
39
     * @return self
40
     */
41
    public function setLoadEvents($loadEvents)
42
    {
43
        $this->loadEvents = $loadEvents;
44
45
        return $this;
46
    }
47
48
49
    /**
50
     * @return void
51
     */
52
    public function indexAction()
53
    {
54
        // console purge <entity> <id>
55
56
        /* @var EntityEraser $eraser */
57
58
        $console  = $this->getConsole();
59
        $eraser   = $this->plugin(EntityEraser::class);
60
        $options  = \Zend\Json\Json::decode($this->params('options', '{}'), \Zend\Json\Json::TYPE_ARRAY);
61
        $eraser->setOptions($options);
62
        $entities = $eraser->loadEntities($this->params('entity'), $this->params('id'));
0 ignored issues
show
Bug introduced by
The method loadEntities() does not seem to exist on object<Zend\Stdlib\DispatchableInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
63
64
        $found = count($entities);
65
        $console->writeLine(sprintf('Found %s entities to purge.', $found));
66
67
        if (0 == $found) {
68
            return;
69
        }
70
71
        if (!$this->params('no-check')) {
72
73
74
            $console->writeLine('Checking dependencies ... ' . PHP_EOL);
75
76
            $eraser = $this->plugin(EntityEraser::class);
77
            $counts = [];
78
            $totalCount = 0;
79
            foreach ($entities as $entity) {
80
                $console->writeLine('    ' . $this->entityToString($entity));
81
                $totalCount += 1;
82
                $dependencies = $eraser->checkDependencies($entity);
0 ignored issues
show
Bug introduced by
The method checkDependencies() does not seem to exist on object<Zend\Stdlib\DispatchableInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
83
84
                foreach ($dependencies as $dependencyList) {
85
                    if ($dependencyList->isCount()) {
86
                        $entitiesCount = $dependencyList->getEntities();
87
                        $dependendEntities = [];
88
                    } else {
89
                        $dependendEntities = $dependencyList->getEntities();
90
                        $entitiesCount = count($dependendEntities);
91
                    }
92
93
                    $console->writeLine('        ' . $entitiesCount . ' ' . $dependencyList->getName() . ': ' . $dependencyList->getDescription());
94
95
                    $totalCount += $entitiesCount;
96
                    if (!isset($counts[$dependencyList->getName()])) { $counts[$dependencyList->getName()] = 0; }
97
                    $counts[$dependencyList->getName()] += $entitiesCount;
98
99
                    foreach ($dependendEntities as $dependendEntity) {
100
                        $console->writeLine('        - ' . $this->entityToString($dependendEntity));
101
                    }
102
                    $console->writeLine(' ');
103
                }
104
                $console->writeLine('');
105
            }
106
107
            $console->writeLine($totalCount . ' entities affected:');
108
            $console->writeLine('    ' . count($entities) . ' ' . $this->params('entity'));
109
            foreach ($counts as $name => $count) {
110
                $console->writeLine('    ' . $count . ' ' . $name);
111
            }
112
113
            $console->writeLine('');
114
            $confirmed = \Zend\Console\Prompt\Confirm::prompt('Proceed? [y/n] ');
115
116
            if (!$confirmed) {
117
                $console->writeLine('Aborted.');
118
                exit(1);
119
            }
120
        }
121
122
123
        $totalCount = 0;
124
        $counts = [];
125
126
        $progress     = new ProgressBar(count($entities));
127
        $i = 0;
128
        foreach ($entities as $entity) {
129
            $progress->update(++$i, $entity->getId());
130
            $dependencies = $eraser->erase($entity);
0 ignored issues
show
Bug introduced by
The method erase() does not seem to exist on object<Zend\Stdlib\DispatchableInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
131
132
            $totalCount += 1;
133
            foreach ($dependencies as $list) {
134
                $entitiesCount = $list->isCount() ? $list->getEntities() : count($list->getEntities());
135
                $totalCount += $entitiesCount;
136
                if (!isset($counts[$list->getName()])) { $counts[$list->getName()] = [0, $list->getDescription()]; }
137
                $counts[$list->getName()][0] += $entitiesCount;
138
            }
139
        }
140
141
        $progress->finish();
142
        $console->writeLine('');
143
        $console->writeLine('Processed ' . $totalCount . ' entities.');
144
        $console->writeLine('    ' . count($entities) . ' ' . $this->params('entity') . ' deleted.');
145
        foreach ($counts as $name => $count) {
146
            $console->writeLine('    ' . $count[0] . ' ' . $name . ' ' . $count[1]);
147
        }
148
    }
149
150
    public function listAction()
151
    {
152
        $responses = $this->loadEvents->trigger(LoadEvent::FETCH_LIST, $this);
153
        $console = $this->getConsole();
154
155
        $console->writeLine('');
156
        foreach ($responses as $response) {
157
            if (!is_array($response) || !isset($response['key'])) { continue; }
158
159
            $console->writeLine(sprintf("%-20s %s", $response['key'], isset($response['description']) ? $response['description'] : ''), ColorInterface::BLUE);
160
161
            if (isset($response['options']) && is_array($response['options'])) {
162
                $console->writeLine('');
163
                foreach ($response['options'] as $name => $desc) {
164
                    $console->writeLine(sprintf("%20s- %-15s %s", ' ', $name, $desc));
165
                }
166
            }
167
            $console->writeLine('');
168
        }
169
        $console->writeLine();
170
    }
171
172
    /**
173
     * Get a string representation from an entity.
174
     *
175
     * Uses the entitys' __toString method, if available.
176
     * Otherwise just returns the class name and if available, the ID.
177
     *
178
     * @param EntityInterface $entity
179
     *
180
     * @return string
181
     */
182
    private function entityToString(EntityInterface $entity)
183
    {
184
        if (method_exists($entity, '__toString')) {
185
            return $entity->__toString();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Core\Entity\EntityInterface as the method __toString() does only exist in the following implementations of said interface: Applications\Entity\Status, Auth\Entity\Status, Core\Entity\AbstractLocation, Core\Entity\Tree\AbstractLeafs, Core\Entity\Tree\AttachedLeafs, Core\Entity\Tree\EmbeddedLeafs, Cv\Entity\Location, Cv\Entity\Status, Jobs\Entity\JobSnapshot, Jobs\Entity\Location, Jobs\Entity\Status.

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...
186
        }
187
188
        $str = get_class($entity);
189
190
        if ($entity instanceOf \Core\Entity\IdentifiableEntityInterface) {
191
            $str .= '( ' . $entity->getId() . ' )';
192
        }
193
194
        return $str;
195
    }
196
}
197