LeptonServer::terminate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 3
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
// Set the directory to monitor
4
5
namespace Lepton;
6
7
use ScssPhp\ScssPhp\{Compiler, OutputStyle};
8
9
class LeptonServer
10
{
11
    private array $fileHashes = array();
12
    private array $dependancyTree = array();
13
    private bool $compile_sass = false;
14
    private $webServerProcess;
15
16
    public function __construct(public readonly string $sass_directory, public readonly string $css_directory, private readonly string $application)
17
    {
18
19
        echo "Running...".PHP_EOL;
20
21
        if(is_dir($this->sass_directory)) {
22
            // Clean output folder
23
            array_map('unlink', array_filter((array) glob($this->css_directory."*")));
24
25
            $this->compile_sass = true;
26
            echo "\e[32mCompiling assets...\e[39m".PHP_EOL;
27
28
            $this->updateMainFiles();
29
30
            // Compile the files
31
            foreach($this->fileHashes as $file => $hash) {
32
33
                $file = realpath($file);
34
                $fileDependancies = $this->compileFile($file);
35
                $this->fileHashes[$file] = filemtime($file);
36
                $this->dependancyTree[$file] = $fileDependancies;
37
                foreach($fileDependancies as $dep) {
38
                    $this->fileHashes[realpath($dep)] = filemtime($dep);
39
                }
40
            }
41
42
43
            echo "Dependancies tree built.".PHP_EOL.PHP_EOL;
44
45
            // Compute md5 hash for files
46
            foreach($this->dependancyTree as $file => $where) {
47
                $fileHashes[$file] = filemtime($file);
48
            }
49
50
        } else {
51
            echo "\e[32mNo _sass directory found\e[39m".PHP_EOL;
52
        }
53
    }
54
55
56
    public function run()
57
    {
58
59
60
        declare(ticks=1); // Enable tick processing for signal handling
61
62
        pcntl_signal(SIGINT, array($this, "terminate"));
63
64
        echo "\e[32mWatching in ".$this->sass_directory."\e[39m".PHP_EOL.PHP_EOL;
65
66
        echo "\e[33mStarting PHP WebServer (ONLY FOR DEVELOPMENT) at http://127.0.0.1:5555\e[39m".PHP_EOL.PHP_EOL;
67
68
        //Start the PHP built-in web server
69
        $command = sprintf('php -S localhost:5555 -t %s %s/webserver.php', $this->application, $this->application);
70
        $this->webServerProcess = proc_open($command, [STDIN, STDOUT, STDERR], $pipes);
71
        while(true) {
72
            if($this->compile_sass) {
73
                $this->cleanDeletedFiles();
74
                $this->updateMainFiles();
75
                foreach($this->fileHashes as $file => $hash) {
76
                    $file = realpath($file);
77
                    if(file_exists($file)) {
78
                        $newHash = filemtime($file);
79
                        if($newHash != $hash) {
80
                            echo "\e[93mFile $file modified!\e[39m".PHP_EOL;
81
                            $this->fileHashes[$file] = $newHash;
82
83
                            // if it's a main file
84
                            if(key_exists($file, $this->dependancyTree)) {
85
                                $this->dependancyTree[$file] = $this->compileFile($file);
86
                            } else { // if it's an included file
87
                                foreach($this->dependancyTree as $main => $dependancies) {
88
                                    if(in_array($file, $dependancies)) {
89
                                        $this->dependancyTree[$main] = $this->compileFile($main);
90
                                    }
91
                                }
92
                            }
93
94
                        }
95
                    } else {
96
                        unset($this->fileHashes[$file]);
97
                    }
98
                }
99
            }
100
            sleep(1);
101
        }
102
103
    }
104
105
    public function terminate()
106
    {
107
        echo "\n\n\e[31mTERMINATING...\e[39m\n";
108
        proc_terminate($this->webServerProcess);
109
        exit(130);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
110
    }
111
112
113
    public function cleanDeletedFiles()
114
    {
115
116
        foreach($this->fileHashes as $file => $hash) {
117
            if(!file_exists($file)) {
118
                unset($fileHashes[$file]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fileHashes seems to be never defined.
Loading history...
119
                foreach($this->dependancyTree as $main => $dependancies) {
120
                    if($main == $file) {
121
                        unset($this->dependancyTree[$main]);
122
                    }
123
                    if(in_array($file, $dependancies)) {
124
                        $key = array_search($file, $dependancies);
125
                        unset($this->dependancyTree[$main][$key]);
126
                    }
127
                }
128
            }
129
        }
130
    }
131
132
133
    public function compileScss($inputFile)
134
    {
135
136
        $compiler = new Compiler();
137
        $compiler->setImportPaths($this->sass_directory);
138
        $compiler->setOutputStyle(OutputStyle::COMPRESSED);
139
140
        if (is_file($inputFile)) {
141
            // Set the path to the output CSS file
142
            $outputFile = preg_replace('/(.*)\.(sass|scss)$/', '$1.css', basename($inputFile));
143
            $outputFile =  $this->css_directory.$outputFile;
144
            // Compile the SCSS code into CSS
145
            try {
146
                $result = $compiler->compileString(file_get_contents($inputFile));
147
148
                $outputdir = dirname($outputFile);
149
150
                // Create the directories recursively
151
                if (!is_dir($outputdir)) {
152
                    mkdir($outputdir, 0755, true);
153
                }
154
                file_put_contents($outputFile, $result->getCss());
155
                return $result->getIncludedFiles();
156
            } catch (\Exception $e) {
157
                print_r($e);
158
                syslog(LOG_ERR, 'scssphp: Unable to compile content');
159
            }
160
161
        } else {
162
            echo "Invalid file".PHP_EOL;
163
        }
164
    }
165
166
    public function compileFile($file)
167
    {
168
        $fileNameArray = explode("/", $file);
169
        $fileName = end($fileNameArray);
170
        echo "\e[39m\t==> Compiling $fileName... \e[39m";
171
        $included = $this->compileScss($file);
172
        echo "\e[32mDone!\e[39m".PHP_EOL;
173
        return $included;
174
    }
175
176
    public function updateMainFiles()
177
    {
178
        $files = glob($this->sass_directory . '/*');  // Get all files in the directory
179
180
181
        foreach ($files as $file) {
182
            $file = realpath($file);
183
            $pattern = '/^\/.+\/[^_]*[.](scss|sass)/';     // Specify the regex pattern for file names
184
            if(preg_match($pattern, $file)) {
185
                if(! array_key_exists($file, $this->fileHashes)) {
186
                    $this->fileHashes[$file] = 0;
187
                }
188
            }
189
        }
190
191
    }
192
193
}
194