Issues (426)

src/Commands/GenerateBlocks.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace A17\Twill\Commands;
4
5
use A17\Twill\Services\Blocks\Block;
6
use A17\Twill\Services\Blocks\BlockCollection;
7
use Illuminate\Console\Command;
0 ignored issues
show
This use statement conflicts with another class in this namespace, A17\Twill\Commands\Command. Consider defining an alias.

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...
8
use Illuminate\Filesystem\Filesystem;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Str;
11
use Illuminate\View\Factory as ViewFactory;
12
13
class GenerateBlocks extends Command
14
{
15
    const NO_BLOCKS_DEFINED = "There are no blocks defined yet. Please refer to https://twill.io/docs/#block-editor-3 in order to create blocks.";
16
    const SCANNING_BLOCKS = "Starting to scan block views directory...";
17
18
    /**
19
     * The name and signature of the console command.
20
     *
21
     * @var string
22
     */
23
    protected $signature = 'twill:blocks';
24
25
    /**
26
     * The console command description.
27
     *
28
     * @var string
29
     */
30
    protected $description = "Generate blocks as single file Vue components from blade views";
31
32
    /**
33
     * @var Filesystem
34
     */
35
    protected $filesystem;
36
37
    /**
38
     * @var ViewFactory
39
     */
40
    protected $viewFactory;
41
42
    /**
43
     * @param Filesystem $filesystem
44 69
     * @param ViewFactory $viewFactory
45
     */
46 69
    public function __construct(Filesystem $filesystem, ViewFactory $viewFactory)
47
    {
48 69
        parent::__construct();
49 69
50 69
        $this->filesystem = $filesystem;
51
        $this->viewFactory = $viewFactory;
52
    }
53
54
    /**
55
     * Executes the console command.
56
     *
57
     * @return mixed
58
     */
59
    public function handle()
60
    {
61
        if (!$this->filesystem->exists($path = resource_path('views/admin/blocks'))) {
62
            $this->error(self::NO_BLOCKS_DEFINED);
63
64
            return;
65
        }
66
67
        $this->info(self::SCANNING_BLOCKS);
68
69
        $blocks = new BlockCollection();
70
        $blocks
71
            ->collect()
72
            ->where('compiled', true)
73
            ->whereIn('source', [Block::SOURCE_APP, Block::SOURCE_CUSTOM])
74
            ->map(function ($block) {
75
                $blockName = str_replace('a17-block-', '', $block->component);
76
                $basename = str_replace('.blade.php', '', $block->fileName);
77
78
                $vueBlockTemplate = $this->viewFactory->make('admin.blocks.' . $basename, ['renderForBlocks' => true])->render();
79
80
                $vueBlockContent = $this->viewFactory->make('twill::blocks.builder', [
81
                    'render' => $this->sanitize($vueBlockTemplate),
82
                ])->render();
83
84
                $vueBlockPath = $this->makeDirectory(resource_path(config('twill.block_editor.custom_vue_blocks_resource_path', 'assets/js/blocks'))) . '/Block' . Str::title($blockName) . '.vue';
85
86
                $write = !$this->filesystem->exists($vueBlockPath);
87
88
                if (!$write) {
89
                    $write = $this->confirm("[$vueBlockPath] exists, overwrite?", false);
90
                }
91
92
                if ($write) {
93
                    $this->filesystem->put($vueBlockPath, $vueBlockContent);
94
                    $this->info("Block " . Str::title($blockName) . " generated successfully");
95
                } else {
96
                    $this->info("Skipping block " .  Str::title($blockName) . ".");
97
                }
98
            });
99
100
        $this->info("All blocks have been generated!");
101
    }
102
103
    /**
104
     * Recursively make a directory.
105
     *
106
     * @param string $directory
107
     * @return string
108
     */
109
    public function makeDirectory($directory)
110
    {
111
        if (!$this->filesystem->exists($directory)) {
112
            $this->filesystem->makeDirectory($directory, 0755, true);
113
        }
114
        return $directory;
115
    }
116
117
    /**
118
     * Sanitizes the given HTML code by removing redundant spaces and comments.
119
     *
120
     * @param string $html
121
     * @return string
122
     */
123
    private function sanitize($html)
124
    {
125
        $search = array(
126
            '/\>[^\S ]+/s', // strip whitespaces after tags, except space
127
            '/[^\S ]+\</s', // strip whitespaces before tags, except space
128
            '/(\s)+/s', // shorten multiple whitespace sequences
129
            '/<!--(.|\s)*?-->/', // Remove HTML comments
130
        );
131
132
        $replace = array(
133
            '>',
134
            '<',
135
            '\\1',
136
            '',
137
        );
138
139
        return preg_replace($search, $replace, Block::removeSpecialBladeTags($html));
140
    }
141
}
142