JSBuilder::generateJS()   F
last analyzed

Complexity

Conditions 14
Paths 600

Size

Total Lines 118
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 51
nc 600
nop 3
dl 0
loc 118
rs 2.6555
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
<?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: RocketCMS
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
		//set flag, if buffer is empty
130
		$empty_flag = empty($buffer);
131
132
		//add comment so md5 hash will change
133
		$buffer = "/* generated by jsbuilder on " . gmdate("D, d M Y H:i:s", time()) . ", empty flag: " . ($empty_flag ? "true" : "false") . " */" . $buffer;
134
135
		//create cache directory, if neccessary
136
		if (!file_exists(CACHE_PATH . "jsbuilder/")) {
137
			mkdir(CACHE_PATH . "jsbuilder/");
138
		}
139
140
		//cache buffer
141
		file_put_contents($this->getCachePath($style_name, $media, $position), $buffer);
142
143
		Cache::put("jsbuilder", "hash_" . $style_name . "_" . $media . "_" . strtolower($position), md5($buffer));
144
		Cache::put("jsbuilder", "meta_" . $style_name . "_" . $media . "_" . strtolower($position), array('empty_flag' => $empty_flag));
145
146
		$this->content = $buffer;
147
148
		if (ACTIVATE_BENCHMARK) {
149
			$end_time = microtime(true);
150
			$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...
151
152
			self::$benchmark[$style_name . "_" . $media] = $exec_time;
153
		}
154
155
		return $buffer;
156
	}
157
158
	public function getCachePath (string $style, string $media = "ALL", string $position = "header") : string {
159
		$position = strtolower($position);
160
161
		$md5_filename = md5("js_" . $style . "_" . $media . "_" . $position);
162
		$js_cache_path = CACHE_PATH . "jsbuilder/" . $md5_filename . ".js";
163
164
		return $js_cache_path;
165
	}
166
167
	public function existsCache (string $style, string $media = "ALL", string $position = "header") : bool {
168
		return file_exists($this->getCachePath($style, $media, $position));
169
	}
170
171
	public function getHash (string $style, string $media = "ALL", string $position = "header") : string {
172
		if (!$this->existsCache($style, $media, $position)) {
173
			//generate cached js file
174
			$this->generateJS($style, $media, $position);
175
		}
176
177
		if (!Cache::contains("jsbuilder", "hash_" . $style . "_" . $media . "_" . $position)) {
178
			throw new IllegalStateException("cached js file 'hash_" . $style . "_" . $media . "_" . $position . "' doesnt exists.");
179
		}
180
181
		return Cache::get("jsbuilder", "hash_" . $style . "_" . $media . "_" . $position);
182
	}
183
184
	public function isEmpty (string $style, string $media = "ALL", string $position = "header") : bool {
185
		if (!Cache::contains("jsbuilder", "meta_" . $style . "_" . $media . "_" . $position)) {
186
			throw new IllegalStateException("cached js file 'meta_" . $style . "_" . $media . "_" . $position . "' doesnt exists.");
187
		}
188
189
		$array = Cache::get("jsbuilder", "meta_" . $style . "_" . $media . "_" . $position);
190
191
		return $array['empty_flag'] == true;
192
	}
193
194
	public function load (string $style, string $media = "ALL", string $position = "header") {
195
		$cache_path = $this->getCachePath($style, $media, $position);
196
197
		if (!$this->existsCache($style, $media, $position)) {
198
			$this->generateJS($style, $media, $position);
199
		} else {
200
			$this->content = file_get_contents($cache_path);
201
		}
202
	}
203
204
	public function getBuffer () : string {
205
		return $this->content;
206
	}
207
208
	public static function listBenchmarks () {
209
		return self::$benchmark;
210
	}
211
212
}
213
214
?>
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...
215