Completed
Push — master ( 6bc272...387eb9 )
by Craig
07:54
created

BuildPackageCommand::execute()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 95
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 64
nc 16
nop 2
dl 0
loc 95
rs 8.2079
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
#!/usr/bin/env php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 17 and the first side effect is on line 1.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
<?php
3
4
use Symfony\Component\Console\Application;
5
use Symfony\Component\Console\Command\Command;
6
use Symfony\Component\Console\Input\InputArgument;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Input\InputOption;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Symfony\Component\Console\Helper\ProgressBar;
11
use Symfony\Component\Finder\Finder;
12
use Symfony\Component\Finder\SplFileInfo;
1 ignored issue
show
Bug introduced by
This use statement conflicts with another class in this namespace, SplFileInfo.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use Symfony\Component\Filesystem\Filesystem;
14
15
require 'src/vendor/autoload.php';
16
17
class GenerateVendorDocCommand extends Command
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
18
{
19
    protected function configure()
20
    {
21
        $this
22
            ->setName('build:generate_vendor_doc')
23
            ->setDescription('Generates a file containing all the vendors and the installed version.')
24
            ->addOption('write-to', null, InputOption::VALUE_REQUIRED, 'Where to dump the generated file.');
25
    }
26
27
    protected function execute(InputInterface $input, OutputInterface $output)
28
    {
29
        $output->writeln('Reading composer vendors.');
30
        $packages = json_decode(file_get_contents('composer.lock'), true);
31
        $packages = $packages['packages'];
32
33
        $output->writeln('Generating output');
34
35
        $typeOrder = [
36
            'zikula-module' => 'Zikula Modules',
37
            'zikula-theme' => 'Zikula Themes',
38
            'symfony-bundle' => 'Symfony Bundles',
39
            'component' => 'Web Components',
40
            'library' => 'Other PHP libraries',
41
            'composer-installer' => 'Composer Installers',
42
            'composer-plugin' => 'Composer Plugins'
43
        ];
44
        $types = array_keys($typeOrder);
45
        usort($packages, function ($a, $b) use ($types) {
46
            return array_search($a['type'], $types) - array_search($b['type'], $types);
47
        });
48
49
        $content = '';
50
        $currentType = '';
51
        $authors = [];
52
        foreach ($packages as $package) {
53
            if ($currentType != $package['type']) {
54
                if ($currentType != '') {
55
                    $content .= "\n";
56
                }
57
                $content .= $typeOrder[$package['type']] . "\n";
58
                $content .= str_repeat('-', strlen($typeOrder[$package['type']])) . "\n";
59
                $currentType = $package['type'];
60
            }
61
            $content .= "- **" . $package['name'] . "** `" . $package['version'] . "`";
62
            if (isset($package['license'])) {
63
                $content .= ", License: `" . implode(', ', $package['license']) . "`\n";
64
            } else {
65
                $content .= "\n";
66
            }
67
            if (isset($package['description'])) {
68
                $content .= "  *" . $package['description'] . "*\n";
69
            }
70
            if (isset($package['authors'])) {
71
                $authors = array_merge($authors, $package['authors']);
72
            }
73
        }
74
75
        $content .= "\n\n";
76
        $content .= "These are the main authors of all of the projects supporting Zikula\n";
77
        $content .= "-------------------------------------------------------------------\n";
78
79
        $tmp = [];
80
        foreach ($authors as $k => $author) {
81
            if (in_array($author['name'], $tmp)) {
82
                unset($authors[$k]);
83
                continue;
84
            }
85
            $tmp[] = $author['name'];
86
        }
87
        foreach ($authors as $author) {
88
            $content .= "- **" . $author['name'] . "**";
89
            if (isset($author['homepage'])) {
90
                $content .= " " . $author['homepage'];
91
            }
92
            if (isset($author['email'])) {
93
                $content .= " *" . $author['email'] . "*";
94
            }
95
            $content .= "\n";
96
        }
97
98
        $output->writeln('Dumping vendors to ' . $input->getOption('write-to'));
99
100
        file_put_contents($input->getOption('write-to'), $content);
101
    }
102
}
103
104
class PurgeVendorsCommand extends Command
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
105
{
106
    protected function configure()
107
    {
108
        $this
109
            ->setName('build:purge_vendors')
110
            ->setDescription('Purges tests from vendors')
111
            ->addUsage('my/package/path/vendor')
112
            ->addArgument('vendor-dir', InputArgument::REQUIRED, 'Vendors dir, e.g. src/vendor');
113
    }
114
115
    protected function execute(InputInterface $input, OutputInterface $output)
116
    {
117
        $dir = $input->getArgument('vendor-dir');
118
        $progress = new ProgressBar($output, 4);
119
        $progress->start();
120
121
        self::cleanVendors($dir, $progress);
122
    }
123
124
    public static function cleanVendors($dir, ProgressBar $progress)
125
    {
126
        $filesystem = new Filesystem();
127
128
        $finder = new Finder();
129
        $finder->in($dir)
130
            ->directories()
131
            ->path('.git')
132
            ->path('tests')
133
            ->path('Tests')
134
            ->ignoreDotFiles(false)
135
            ->ignoreVCS(false);
136
        $progress->advance();
137
138
        $paths = [];
139
        /** @var SplFileInfo $file */
140
        foreach ($finder as $file) {
141
            $paths[] = $file->getRealPath();
142
        }
143
144
        $paths = array_unique($paths);
145
        rsort($paths);
146
147
        $progress->advance();
148
        $filesystem->chmod($paths, 0777, 0000, true);
149
        $progress->advance();
150
        $filesystem->remove($paths);
151
        $progress->advance();
152
    }
153
}
154
155
class FixAutoloaderCommand extends Command
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
156
{
157
    protected function configure()
158
    {
159
        $this
160
            ->setName('build:fix_autoloader')
161
            ->setDescription('Fixes autoloader paths')
162
            ->addUsage('my/package/path/vendor')
163
            ->addArgument('vendor-dir', InputArgument::REQUIRED, 'Vendors dir, e.g. src/vendor');
164
    }
165
166
    protected function execute(InputInterface $input, OutputInterface $output)
167
    {
168
        $dir = $input->getArgument('vendor-dir');
169
        $progress = new ProgressBar($output, 3);
170
        $progress->start();
171
172
        self::fix($dir, $progress);
173
    }
174
175
    public static function fix($dir, ProgressBar $progress)
176
    {
177
        // fix paths in composer autoloader files removing src/ from paths
178
        $composerFiles = [
179
            'autoload_classmap.php',
180
            'autoload_namespaces.php',
181
            'autoload_real.php',
182
            'autoload_files.php',
183
            'autoload_psr4.php',
184
            'autoload_static.php'
185
        ];
186
        foreach ($composerFiles as $file) {
187
            $file = "$dir/composer/$file";
188
            $content = file_get_contents($file);
189
            $content = str_replace("baseDir . '/src/", "baseDir . '/", $content);
190
            $content = str_replace('dirname(dirname($vendorDir))', 'dirname($vendorDir)', $content);
191
            $content = str_replace("__DIR__ . '/../../..' . '/src", "__DIR__ . '/../..' . '", $content);
192
            file_put_contents($file, $content);
193
            $progress->advance();
194
        }
195
    }
196
}
197
198
/**
199
 * UNUSED COMMAND
200
 * Class BuildPackageCommand
201
 */
202
class BuildPackageCommand extends Command
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
203
{
204
    protected function configure()
205
    {
206
        $this
207
            ->setName('build:package')
208
            ->setDescription('Packages Zikula')
209
            ->addUsage('my-buildname path/to/my/build/dir path/to/my/source/dir')
210
            ->addArgument('name', InputArgument::REQUIRED, 'Build name')
211
            ->addArgument('source-dir', InputArgument::REQUIRED, 'Build dir')
212
            ->addArgument('build-dir', InputArgument::REQUIRED, 'Source dir');
213
    }
214
215
    protected function execute(InputInterface $input, OutputInterface $output)
216
    {
217
        $name = $input->getArgument('name');
218
        $sourceDir = $input->getArgument('source-dir');
219
        $buildDir = $input->getArgument('build-dir');
220
221
        $progress = new ProgressBar($output, 17);
222
        $progress->start();
223
224
        $filesystem = new Filesystem();
225
226
        $pwd = getcwd();
227
        if (is_dir($buildDir)) {
228
            system("rm -rf $buildDir");
229
        }
230
231
        // build env
232
        $filesystem->mkdir($buildDir, 0755);
233
        $progress->advance();
234
235
        $filesystem->mirror($sourceDir, "$buildDir/$name");
236
        $progress->advance();
237
238
        PurgeVendorsCommand::cleanVendors("$buildDir/$name/vendor", $progress);
239
        FixAutoloaderCommand::fix("$buildDir/$name/vendor", $progress);
240
241
        $writableArray = [
242
            "$buildDir/$name/var/cache",
243
            "$buildDir/$name/var/logs",
244
            "$buildDir/$name/web/uploads",
245
        ];
246
        $filesystem->chmod($writableArray, 0777);
247
        $progress->advance();
248
249
        chdir($buildDir);
250
        $finder = new Finder();
251
        $finder
252
            ->in($name)
253
            ->files()
254
            ->ignoreDotFiles(false);
255
256
        $allFiles = [];
257
        /** @var SplFileInfo $file */
258
        foreach ($finder as $file) {
259
            $allFiles[] = $file->getRelativePathname();
260
        }
261
        $progress->advance();
262
263
        // build zip
264
        $zip = new \ZipArchive();
265
        $fileName = "$name.zip";
266
        if ($zip->open($fileName, \ZipArchive::CREATE) !== true) {
267
            $output->writeln("<error>Error creating $fileName</error>");
268
        }
269
270
        foreach ($allFiles as $file) {
271
            $zip->addFile("$name/$file");
272
        }
273
        $progress->advance();
274
275
        $zip->close();
276
        $progress->advance();
277
278
        // build tar
279
        $fileName = "$name.tar";
280
        system("tar cp $name > $fileName");
281
        $progress->advance();
282
        system("gzip $fileName");
283
        $progress->advance();
284
285
        // checksums
286
        $zipMd5 = md5_file("$name.zip");
287
        $tarMd5 = md5_file("$name.tar.gz");
288
        $zipSha1 = sha1_file("$name.zip");
289
        $tarSha1 = sha1_file("$name.tar.gz");
290
291
        $checksum = <<<CHECKSUM
292
-----------------md5sums-----------------
293
$zipMd5  $name.zip
294
$tarMd5  $name.tar.gz
295
-----------------sha1sums-----------------
296
$zipSha1  $name.zip
297
$tarSha1  $name.tar.gz
298
CHECKSUM;
299
        file_put_contents("$name-checksum.txt", $checksum);
300
        $progress->advance();
301
302
        // cleanup
303
        system("rm -rf $buildDir $name");
304
        chdir($pwd);
305
        $progress->advance();
306
        $progress->finish();
307
308
        $output->writeln("<info>Artifacts built in $buildDir/ folder</info>");
309
    }
310
}
311
312
class LessCommand extends Command
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
313
{
314
    protected function configure()
315
    {
316
        $this
317
            ->setName('build:generate_less')
318
            ->setDescription('Generates Bootstrap Less file')
319
            ->addOption('write-to', null, InputOption::VALUE_REQUIRED, 'Where to dump the generated file.');
320
    }
321
322
    protected function execute(InputInterface $input, OutputInterface $output)
323
    {
324
        \Zikula\Composer\LessGenerator::generateCombinedBootstrapFontAwesomeCSS($input->getOption('write-to'));
325
    }
326
}
327
328
$application = new Application();
329
$application->add(new BuildPackageCommand());
330
$application->add(new PurgeVendorsCommand());
331
$application->add(new FixAutoloaderCommand());
332
$application->add(new GenerateVendorDocCommand());
333
$application->add(new LessCommand());
334
$application->run();
335