Completed
Push — master ( a76db0...9d44a5 )
by WEBEWEB
05:01
created

UnzipAssetsCommand::displayHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
/**
4
 * This file is part of the core-bundle package.
5
 *
6
 * (c) 2018 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\Component\Console\Command\Command;
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\Console\Style\SymfonyStyle;
19
use WBW\Bundle\CoreBundle\Helper\AssetsHelper;
20
use WBW\Bundle\CoreBundle\Provider\AssetsProviderInterface;
21
22
/**
23
 * Unzip assets command.
24
 *
25
 * @author webeweb <https://github.com/webeweb/>
26
 * @package WBW\Bundle\CoreBundle\Command
27
 */
28
class UnzipAssetsCommand extends Command {
29
30
    /**
31
     * Command help.
32
     *
33
     * @var string
34
     */
35
    const COMMAND_HELP = <<< 'EOT'
36
The <info>%command.name%</info> command unzips bundle assets into a given
37
directory (e.g. the <comment>public</comment> directory).
38
39
    <info>php %command.full_name% public</info>
40
41
EOT;
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    protected function configure() {
47
        $this
48
            ->setName("wbw:core:unzip-assets")
49
            ->setDescription("Unzip assets under a public directory")
50
            ->setHelp(self::COMMAND_HELP);
51
    }
52
53
    /**
54
     * Display the footer.
55
     *
56
     * @param StyleInterface $io The I/O.
57
     * @param int $exitCode The exit code.
58
     * @param int $count The count.
59
     * @return void
60
     */
61
    protected function displayFooter(StyleInterface $io, $exitCode, $count) {
62
        if (0 < $exitCode) {
63
            $io->error("Some errors occurred while unzipping assets");
64
            return;
65
        }
66
        if (0 === $count) {
67
            $io->success("No assets were provided by any bundle");
68
        }
69
        $io->success("All assets were succefully unzipped");
70
    }
71
72
    /**
73
     * Displays the header.
74
     *
75
     * @param StyleInterface $io The I/O.
76
     * @return void
77
     */
78
    protected function displayHeader(StyleInterface $io) {
79
        $io->newLine();
80
        $io->text("Trying to unzip assets");
81
        $io->newLine();
82
    }
83
84
    /**
85
     * Displays the result.
86
     *
87
     * @param StyleInterface $io The I/O.
88
     * @param array $results The results.
89
     * @return int Returns the exit code.
90
     */
91
    protected function displayResult(StyleInterface $io, array $results) {
92
93
        // Initialize.
94
        $success = sprintf("<fg=green;options=bold>%s</>", "\\" === DIRECTORY_SEPARATOR ? "OK" : "\xE2\x9C\x94");
95
        $warning = sprintf("<fg=yellow;options=bold>%s</>", "\\" === DIRECTORY_SEPARATOR ? "KO" : "!");
96
97
        $rows = [];
98
99
        $exitCode = 0;
100
101
        // Handle each result.
102
        foreach ($results as $bundle => $assets) {
103
            foreach ($assets as $asset => $result) {
104
105
                $rows[] = [
106
                    true === $result ? $success : $warning,
107
                    $bundle,
108
                    basename($asset),
109
                ];
110
111
                $exitCode += true === $result ? 0 : 1;
112
            }
113
        }
114
115
        // Display a table.
116
        $io->table(["", "Bundle", "Asset"], $rows);
117
118
        // Return the exit code.
119
        return $exitCode;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    protected function execute(InputInterface $input, OutputInterface $output) {
126
127
        // Create an I/O.
128
        $io = $this->newStyle($input, $output);
129
        $this->displayHeader($io);
130
131
        // Initialize the results.
132
        $results = [];
133
134
        // Get the bundles.
135
        $bundles = $this->getApplication()->getKernel()->getBundles();
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...
136
137
        // Handle each bundle.
138
        foreach ($bundles as $current) {
139
140
            // Check the bundle.
141
            if (false === ($current instanceOf AssetsProviderInterface)) {
142
                continue;
143
            }
144
145
            // Get the bundle path.
146
            $bundlePath = $current->getPath();
147
148
            // Initialize the directories.
149
            $assetsDirectory = $bundlePath . $current->getAssetsDirectory();
150
            $publicDirectory = $bundlePath . "/Resources/public";
151
152
            // Unzip the assets.
153
            $results[$current->getName()] = AssetsHelper::unzipAssets($assetsDirectory, $publicDirectory);
154
        }
155
156
        // Display the result.
157
        $exitCode = $this->displayResult($io, $results);
158
159
        // Display the footer.
160
        $this->displayFooter($io, $exitCode, count($results));
161
162
        // Return the exit code.
163
        return $exitCode;
164
    }
165
166
    /**
167
     * Create a style.
168
     *
169
     * @param InputInterface $input The input.
170
     * @param OutputInterface $output The ouptut.
171
     * @return StyleInterface Returns the style.
172
     */
173
    protected function newStyle(InputInterface $input, OutputInterface $output) {
174
        return new SymfonyStyle($input, $output);
175
    }
176
177
}
178