DebugWeavingCommand   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 0
Metric Value
wmc 10
lcom 0
cbo 2
dl 0
loc 97
c 0
b 0
f 0
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 14 1
B execute() 0 45 6
A getProxies() 0 24 3
1
<?php
2
3
declare(strict_types=1);
4
/*
5
 * Go! AOP framework
6
 *
7
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
8
 *
9
 * This source file is subject to the license that is bundled
10
 * with this source code in the file LICENSE.
11
 */
12
13
namespace Go\Console\Command;
14
15
use FilesystemIterator;
16
use Go\Instrument\ClassLoading\CachePathManager;
17
use Go\Instrument\ClassLoading\CacheWarmer;
18
use RecursiveDirectoryIterator;
19
use RecursiveIteratorIterator;
20
use SplFileInfo;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\NullOutput;
23
use Symfony\Component\Console\Output\OutputInterface;
24
use Symfony\Component\Console\Style\SymfonyStyle;
25
26
/**
27
 * Console command for debugging weaving issues due to circular dependencies.
28
 *
29
 * @codeCoverageIgnore
30
 */
31
class DebugWeavingCommand extends BaseAspectCommand
32
{
33
    /**
34
     * {@inheritDoc}
35
     */
36
    protected function configure(): void
37
    {
38
        parent::configure();
39
        $this
40
            ->setName('debug:weaving')
41
            ->setDescription('Checks consistency in weaving process')
42
            ->setHelp(
43
                <<<EOT
44
Allows to check consistency of weaving process, detects circular references and mutual dependencies between
45
subjects of weaving and aspects.
46
EOT
47
            )
48
        ;
49
    }
50
51
    /**
52
     * {@inheritDoc}
53
     */
54
    protected function execute(InputInterface $input, OutputInterface $output): int
55
    {
56
        $this->loadAspectKernel($input, $output);
57
58
        $io = new SymfonyStyle($input, $output);
59
60
        $io->title('Weaving debug information');
61
62
        $cachePathManager = $this->aspectKernel->getContainer()->get('aspect.cache.path.manager');
63
        $warmer           = new CacheWarmer($this->aspectKernel, new NullOutput());
64
        $warmer->warmUp();
65
66
        $proxies = $this->getProxies($cachePathManager);
67
68
        $cachePathManager->clearCacheState();
69
        $warmer->warmUp();
70
71
        $errors = 0;
72
73
        foreach ($this->getProxies($cachePathManager) as $path => $content) {
74
            if (!isset($proxies[$path])) {
75
                $io->error(sprintf('Proxy on path "%s" is generated on second "warmup" pass.', $path));
76
                $errors++;
77
                continue;
78
            }
79
80
            if (isset($proxies[$path]) && $proxies[$path] !== $content) {
81
                $io->error(sprintf('Proxy on path "%s" is weaved differnlty on second "warmup" pass.', $path));
82
                $errors++;
83
                continue;
84
            }
85
86
            $io->note(sprintf('Proxy  on path "%s" is consistently weaved.', $path));
87
        }
88
89
        if ($errors > 0) {
90
            $io->error(sprintf('Weaving is unstable, there are %s reported error(s).', $errors));
91
92
            return $errors;
93
        }
94
95
        $io->success('Weaving is stable, there are no errors reported.');
96
97
        return 0;
98
    }
99
100
    /**
101
     * Gets Go! AOP generated proxy classes (paths and their contents) from the cache.
102
     */
103
    private function getProxies(CachePathManager $cachePathManager): array
104
    {
105
        $path     = $cachePathManager->getCacheDir() . '/_proxies';
106
        $iterator = new RecursiveIteratorIterator(
107
            new RecursiveDirectoryIterator(
108
                $path,
109
                FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS
110
            ),
111
            RecursiveIteratorIterator::CHILD_FIRST
112
        );
113
114
        $proxies = [];
115
116
        /**
117
         * @var SplFileInfo $splFileInfo
118
         */
119
        foreach ($iterator as $splFileInfo) {
120
            if ($splFileInfo->isFile()) {
121
                $proxies[$splFileInfo->getPathname()] = file_get_contents($splFileInfo->getPathname());
122
            }
123
        }
124
125
        return $proxies;
126
    }
127
}
128