Test Failed
Push — master ( a344fe...cefe45 )
by Justin
35:15 queued 31:49
created

JSBuilder::listBenchmarks()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 2
rs 10
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * Copyright (c) 2018 Justin Kuenzel (jukusoft.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
20
/**
21
 * Project: JuKuCMS
22
 * License: Apache 2.0 license
23
 * User: Justin
24
 * Date: 23.03.2018
25
 * Time: 14:02
26
 */
27
28
class JSBuilder {
29
30
	protected $content = "";
31
32
	protected static $benchmark = array();
33
	
34
	public function __construct() {
35
		//
36
	}
37
38
	public function generateJS (string $style_name, string $media = "ALL", string $position = "header") {
39
		if (ACTIVATE_BENCHMARK) {
40
			$start_time = microtime(true);
41
		}
42
43
		//validate values
44
		$style_name = Validator_Filename::get($style_name);
45
		$media = strtoupper(Validator_Filename::get($media));
46
		$position = strtoupper(Validator_Filename::get($position));
47
48
		$suffix = "";
49
50
		if ($position !== "HEADER") {
51
			$suffix = "_" . strtolower($position);
52
		}
53
54
		$js_files = array();
55
56
		//get css files from style.json
57
		if (file_exists(STYLE_PATH . $style_name . "/style.json")) {
58
			$json = json_decode(file_get_contents(STYLE_PATH . $style_name . "/style.json"), true);
59
60
			if (isset($json['js' . $suffix]) && is_array($json['js' . $suffix])) {
61
				foreach ($json['js' . $suffix] as $js_file) {
62
					$full_path = STYLE_PATH . $style_name . "/" . $js_file;
63
					$js_files[] = $full_path;
64
				}
65
			}
66
		}
67
68
		//load js files from database
69
		$rows = Database::getInstance()->listRows("SELECT * FROM `{praefix}js_files` WHERE (`style` = :style OR `style` = 'ALL') AND (`media` = :media OR `media` = 'ALL') AND `position` = :position AND `activated` = '1'; ", array(
70
			'style' => $style_name,
71
			'media' => $media,
72
			'position' => $position
73
		));
74
75
		foreach ($rows as $row) {
76
			$js_files[] = $row['js_file'];
77
		}
78
79
		$buffer = "";
80
81
		foreach ($js_files as $js_file) {
82
			//first check, if file exists
83
			if (!file_exists($js_file)) {
84
				if (DEBUG_MODE) {
85
					echo "Coulnd't found javascript file (style: " . $style_name . "): " . $js_file;
86
87
					ob_end_flush();
88
					exit;
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...
89
				} else {
90
					continue;
91
				}
92
			}
93
94
			//add file content to buffer
95
			$buffer .= file_get_contents($js_file) . "\n";
96
		}
97
98
		//$code = preg_replace("/\s\s+/", " ", $code);
99
100
		//https://github.com/matthiasmullie/minify
101
102
		//https://github.com/tchwork/jsqueeze
103
104
		//https://ourcodeworld.com/articles/read/350/how-to-minify-javascript-and-css-using-php
105
106
		//compress js: https://github.com/tedious/JShrink
107
108
		//remove comments
109
		//$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
110
111
		// remove space after colons
112
		//$buffer = str_replace(': ', ':', $buffer);
113
114
		//remove whitespace
115
		//$buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
116
117
		//replace template variables
118
		$buffer = str_replace("{STYLE_PATH}", DomainUtils::getBaseURL() . "/styles/" . $style_name . "/", $buffer);
119
120
		//compress code
121
		$jz = new JSqueeze();
122
		$buffer = $jz->squeeze(
123
			$buffer,
124
			true,   // $singleLine
125
			false,   // $keepImportantComments
126
			false   // $specialVarRx
127
		);
128
129
		//add comment so md5 hash will change
130
		$buffer = "/* generated by jsbuilder on " . gmdate("D, d M Y H:i:s", time()) . " */" . $buffer;
131
132
		//create cache directory, if neccessary
133
		if (!file_exists(CACHE_PATH . "jsbuilder/")) {
134
			mkdir(CACHE_PATH . "jsbuilder/");
135
		}
136
137
		//cache buffer
138
		file_put_contents($this->getCachePath($style_name, $media, $position), $buffer);
139
140
		Cache::put("jsbuilder", "hash_" . $style_name . "_" . $media . "_" . strtolower($position), md5($buffer));
141
142
		$this->content = $buffer;
143
144
		if (ACTIVATE_BENCHMARK) {
145
			$end_time = microtime(true);
146
			$exec_time = $end_time - $start_time;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $start_time does not seem to be defined for all execution paths leading up to this point.
Loading history...
147
148
			self::$benchmark[$style_name . "_" . $media] = $exec_time;
149
		}
150
151
		return $buffer;
152
	}
153
154
	public function getCachePath (string $style, string $media = "ALL", string $position = "header") : string {
155
		$position = strtolower($position);
156
157
		$md5_filename = md5("js_" . $style . "_" . $media . "_" . $position);
158
		$js_cache_path = CACHE_PATH . "jsbuilder/" . $md5_filename . ".js";
159
160
		return $js_cache_path;
161
	}
162
163
	public function existsCache (string $style, string $media = "ALL", string $position = "header") : bool {
164
		return file_exists($this->getCachePath($style, $media, $position));
165
	}
166
167
	public function getHash (string $style, string $media = "ALL", string $position = "header") : string {
168
		if (!$this->existsCache($style, $media, $position)) {
169
			//generate cached js file
170
			$this->generateJS($style, $media, $position);
171
		}
172
173
		if (!Cache::contains("jsbuilder", "hash_" . $style . "_" . $media . "_" . $position)) {
174
			throw new IllegalStateException("cached js file 'hash_" . $style . "_" . $media . "_" . $position . "' doesnt exists.");
175
		}
176
177
		return Cache::get("jsbuilder", "hash_" . $style . "_" . $media . "_" . $position);
178
	}
179
180
	public function load (string $style, string $media = "ALL", string $position = "header") {
181
		$cache_path = $this->getCachePath($style, $media, $position);
182
183
		if (!$this->existsCache($style, $media, $position)) {
184
			$this->generateJS($style, $media, $position);
185
		} else {
186
			$this->content = file_get_contents($cache_path);
187
		}
188
	}
189
190
	public function getBuffer () : string {
191
		return $this->content;
192
	}
193
194
	public static function listBenchmarks () {
195
		return self::$benchmark;
196
	}
197
198
}
199
200
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
201