Completed
Push — master ( 4a311e...f33b08 )
by WEBEWEB
01:26
created

CopySkeletonCommand::getResourcesDirectory()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
/*
4
 * This file is part of the core-bundle package.
5
 *
6
 * (c) 2019 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Bundle\CoreBundle\Command;
13
14
use Symfony\Bundle\FrameworkBundle\Console\Application;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Console\Style\StyleInterface;
18
use Symfony\Component\HttpKernel\Kernel;
19
use Symfony\Component\HttpKernel\KernelInterface;
20
use WBW\Bundle\CoreBundle\Helper\KernelHelper;
21
use WBW\Bundle\CoreBundle\Helper\SkeletonHelper;
22
use WBW\Bundle\CoreBundle\Provider\SkeletonProviderInterface;
23
24
/**
25
 * Copy skeleton command.
26
 *
27
 * @author webeweb <https://github.com/webeweb/>
28
 * @package WBW\Bundle\CoreBundle\Command\Command
29
 */
30
class CopySkeletonCommand extends AbstractCommand {
31
32
    /**
33
     * Command help.
34
     *
35
     * @var string
36
     */
37
    const COMMAND_HELP = <<< EOT
38
The <info>%command.name%</info> command copy bundle skeleton into <comment>app/Resources</comment>.
39
40
    <info>php %command.full_name%</info>
41
42
EOT;
43
44
    /**
45
     * Service name.
46
     *
47
     * @var string
48
     */
49
    const SERVICE_NAME = "wbw.core.command.copy_skeleton";
50
51
    /**
52
     * {@inheritDoc}
53
     */
54
    protected function configure() {
55
        $this
56
            ->setName("wbw:core:copy-skeleton")
57
            ->setDescription("Copy skeleton under the app/Resources directory")
58
            ->setHelp(self::COMMAND_HELP);
59
    }
60
61
    /**
62
     * Display the footer.
63
     *
64
     * @param StyleInterface $io The I/O.
65
     * @param int $exitCode The exit code.
66
     * @param int $count The count.
67
     * @return void
68
     */
69
    protected function displayFooter(StyleInterface $io, $exitCode, $count) {
70
        if (0 < $exitCode) {
71
            $io->error("Some errors occurred while copying skeletons");
72
            return;
73
        }
74
        if (0 === $count) {
75
            $io->success("No skeleton were provided by any bundle");
76
            return;
77
        }
78
        $io->success("All skeletons were successfully copied");
79
    }
80
81
    /**
82
     * Displays the result.
83
     *
84
     * @param StyleInterface $io The I/O.
85
     * @param array $results The results.
86
     * @return int Returns the exit code.
87
     */
88
    protected function displayResult(StyleInterface $io, array $results) {
89
90
        $exitCode = 0;
91
92
        $rows = [];
93
94
        $success = $this->getCheckbox(true);
95
        $warning = $this->getCheckbox(false);
96
97
        foreach ($results as $bundle => $assets) {
98
            foreach ($assets as $asset => $result) {
99
100
                $rows[] = [
101
                    true === $result ? $success : $warning,
102
                    $bundle,
103
                    basename($asset),
104
                ];
105
106
                $exitCode += true === $result ? 0 : 1;
107
            }
108
        }
109
        $io->table(["", "Bundle", "Resource"], $rows);
110
111
        return $exitCode;
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117
    protected function execute(InputInterface $input, OutputInterface $output) {
118
119
        if (false === ($this->getApplication() instanceof Application)) {
120
            return -1;
121
        }
122
123
        $io = $this->newStyle($input, $output);
124
        $this->displayHeader($io, "Trying to copy skeletons");
125
126
        $results = [];
127
128
        $bundles = $this->getApplication()->getKernel()->getBundles();
129
130
        foreach ($bundles as $current) {
131
132
            if (false === ($current instanceof SkeletonProviderInterface)) {
133
                continue;
134
            }
135
136
            /** @var SkeletonProviderInterface $current */
137
            $bundlePath = $current->getPath();
0 ignored issues
show
Bug introduced by
The method getPath() does not seem to exist on object<WBW\Bundle\CoreBu...letonProviderInterface>.

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...
138
139
            $skeletonDirectory  = $bundlePath . $current->getSkeletonRelativeDirectory();
140
            $resourcesDirectory = $this->getResourcesDirectory();
141
142
            $results[$current->getName()] = SkeletonHelper::copySkeleton($skeletonDirectory, $resourcesDirectory);
0 ignored issues
show
Bug introduced by
The method getName() does not seem to exist on object<WBW\Bundle\CoreBu...letonProviderInterface>.

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...
143
        }
144
145
        $exitCode = $this->displayResult($io, $results);
146
        $this->displayFooter($io, $exitCode, count($results));
147
148
        return $exitCode;
149
    }
150
151
    /**
152
     * Get the resources directory.
153
     *
154
     * @return string Returns the resources directory.
155
     */
156
    protected function getResourcesDirectory() {
157
158
        /** @var KernelInterface $kernel */
159
        $kernel = $this->getApplication()->getKernel();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Console\Application as the method getKernel() does only exist in the following sub-classes of Symfony\Component\Console\Application: Symfony\Bundle\FrameworkBundle\Console\Application. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
160
161
        $rootDir = KernelHelper::getProjectDir($kernel);
162
163
        if (40000 <= Kernel::VERSION_ID) {
164
            return $rootDir . "/templates/bundles";
165
        }
166
167
        return $rootDir . "/app/Resources";
168
    }
169
}
170