Completed
Push — develop ( 9659b8...659b85 )
by Mathias
13:02
created

PurgeController   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

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

4 Methods

Rating   Name   Duplication   Size   Complexity  
A setLoadEvents() 0 6 1
C indexAction() 0 89 13
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
                    $console->writeLine('        ' . $dependencyList->getName() . ': ' . $dependencyList->getDescription());
86
                    $dependendEntities = $dependencyList->getEntities();
87
                    $totalCount += count($dependendEntities);
88
                    if (!isset($counts[$dependencyList->getName()])) { $counts[$dependencyList->getName()] = 0; }
89
                    $counts[$dependencyList->getName()] += count($dependendEntities);
90
91
                    foreach ($dependendEntities as $dependendEntity) {
92
                        $console->writeLine('        - ' . $this->entityToString($dependendEntity));
93
                    }
94
                    $console->writeLine(' ');
95
                }
96
                $console->writeLine('');
97
            }
98
99
            $console->writeLine($totalCount . ' entities affected:');
100
            $console->writeLine('    ' . count($entities) . ' ' . $this->params('entity'));
101
            foreach ($counts as $name => $count) {
102
                $console->writeLine('    ' . $count . ' ' . $name);
103
            }
104
105
            $console->writeLine('');
106
            $confirmed = \Zend\Console\Prompt\Confirm::prompt('Proceed? [y/n] ');
107
108
            if (!$confirmed) {
109
                $console->writeLine('Aborted.');
110
                exit(1);
111
            }
112
        }
113
114
115
        $totalCount = 0;
116
        $counts = [];
117
118
        $progress     = new ProgressBar(count($entities));
119
        $i = 0;
120
        foreach ($entities as $entity) {
121
            $progress->update(++$i, $entity->getId());
122
            $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...
123
124
            $totalCount += 1;
125
            foreach ($dependencies as $list) {
126
                $totalCount += count($list->getEntities());
127
                if (!isset($counts[$list->getName()])) { $counts[$list->getName()] = [0, $list->getDescription()]; }
128
                $counts[$list->getName()][0] += count($list->getEntities());
129
            }
130
        }
131
132
        $progress->finish();
133
        $console->writeLine('');
134
        $console->writeLine('Processed ' . $totalCount . ' entities.');
135
        $console->writeLine('    ' . count($entities) . ' ' . $this->params('entity') . ' deleted.');
136
        foreach ($counts as $name => $count) {
137
            $console->writeLine('    ' . $count[0] . ' ' . $name . ' ' . $count[1]);
138
        }
139
140
    }
141
142
    public function listAction()
143
    {
144
        $responses = $this->loadEvents->trigger(LoadEvent::FETCH_LIST, $this);
145
        $console = $this->getConsole();
146
147
        $console->writeLine('');
148
        foreach ($responses as $response) {
149
            if (!is_array($response) || !isset($response['key'])) { continue; }
150
151
            $console->writeLine(sprintf("%-20s %s", $response['key'], isset($response['description']) ? $response['description'] : ''), ColorInterface::BLUE);
152
153
            if (isset($response['options']) && is_array($response['options'])) {
154
                $console->writeLine('');
155
                foreach ($response['options'] as $name => $desc) {
156
                    $console->writeLine(sprintf("%20s- %-15s %s", ' ', $name, $desc));
157
                }
158
            }
159
            $console->writeLine('');
160
        }
161
        $console->writeLine();
162
    }
163
164
    /**
165
     * Get a string representation from an entity.
166
     *
167
     * Uses the entitys' __toString method, if available.
168
     * Otherwise just returns the class name and if available, the ID.
169
     *
170
     * @param EntityInterface $entity
171
     *
172
     * @return string
173
     */
174
    private function entityToString(EntityInterface $entity)
175
    {
176
        if (method_exists($entity, '__toString')) {
177
            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\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...
178
        }
179
180
        $str = get_class($entity);
181
182
        if ($entity instanceOf \Core\Entity\IdentifiableEntityInterface) {
183
            $str .= '( ' . $entity->getId() . ' )';
184
        }
185
186
        return $str;
187
    }
188
}
189