Passed
Push — feature/code_improvement ( 50ca4e...05471b )
by Thierry
02:57
created

CodeGenerator::_getScript()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Generator.php - Jaxon code generator
5
 *
6
 * Generate HTML, CSS and Javascript code for Jaxon.
7
 *
8
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2016 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
14
15
namespace Jaxon\Plugin;
16
17
use Jaxon\Utils\Template\Engine as TemplateEngine;
18
use Jaxon\Utils\Http\URI;
19
20
class CodeGenerator
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class CodeGenerator
Loading history...
21
{
22
    use \Jaxon\Features\Config;
23
    use \Jaxon\Features\Minifier;
24
25
    /**
26
     * The response type.
27
     *
28
     * @var string
29
     */
30
    const RESPONSE_TYPE = 'JSON';
31
32
    /**
33
     * The plugin manager
34
     *
35
     * @var Manager
36
     */
37
    protected $xPluginManager;
38
39
    /**
40
     * The Jaxon template engine
41
     *
42
     * @var TemplateEngine
43
     */
44
    protected $xTemplate;
45
46
    /**
47
     * Generated CSS code
48
     *
49
     * @var string
50
     */
51
    protected $sCssCode = '';
52
53
    /**
54
     * Generated Javascript code
55
     *
56
     * @var string
57
     */
58
    protected $sJsCode = '';
59
60
    /**
61
     * Generated Javascript ready script
62
     *
63
     * @var string
64
     */
65
    protected $sJsScript = '';
66
67
    /**
68
     * Code already generated
69
     *
70
     * @var boolean
71
     */
72
    protected $sCodeGenerated = false;
73
74
    /**
75
     * Default library URL
76
     *
77
     * @var string
78
     */
79
    protected $sJsLibraryUrl = 'https://cdn.jsdelivr.net/gh/jaxon-php/[email protected]/dist';
80
81
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $xTemplate should have a doc-comment as per coding-style.
Loading history...
82
     * The constructor
83
     *
84
     * @param Manager    $xPluginManager
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter type; 4 found
Loading history...
85
     */
86
    public function __construct(Manager $xPluginManager, TemplateEngine $xTemplate)
87
    {
88
        $this->xPluginManager = $xPluginManager;
89
        $this->xTemplate = $xTemplate;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
90
    }
91
92
    /**
93
     * Get the base URI of the Jaxon library javascript files
94
     *
95
     * @return string
96
     */
97
    private function getJsLibUri()
98
    {
99
        return rtrim($this->getOption('js.lib.uri', $this->sJsLibraryUrl), '/') . '/';
100
    }
101
102
    /**
103
     * Get the extension of the Jaxon library javascript files
104
     *
105
     * The returned string is '.min.js' if the files are minified.
106
     *
107
     * @return string
108
     */
109
    private function getJsLibExt()
110
    {
111
        if(($this->getOption('js.app.minify')))
112
        {
113
            return '.min.js';
114
        }
115
        return '.js';
116
    }
117
118
    /**
119
     * Check if the javascript code generated by Jaxon can be exported to an external file
120
     *
121
     * @return boolean
122
     */
123
    public function canExportJavascript()
124
    {
125
        // Check config options
126
        // - The js.app.export option must be set to true
127
        // - The js.app.uri and js.app.dir options must be set to non null values
128
        if(!$this->getOption('js.app.export') ||
129
            !$this->getOption('js.app.uri') ||
130
            !$this->getOption('js.app.dir'))
131
        {
132
            return false;
133
        }
134
        // Check dir access
135
        // - The js.app.dir must be writable
136
        $sJsAppDir = $this->getOption('js.app.dir');
137
        if(!is_dir($sJsAppDir) || !is_writable($sJsAppDir))
138
        {
139
            return false;
140
        }
141
        return true;
142
    }
143
144
    /**
145
     * Generate a hash for all the javascript code generated by the library
146
     *
147
     * @return string
148
     */
149
    private function generateHash()
150
    {
151
        $sHash = jaxon()->getVersion();
152
        foreach($this->xPluginManager->getRequestPlugins() as $xPlugin)
153
        {
154
            $sHash .= $xPlugin->generateHash();
155
        }
156
        foreach($this->xPluginManager->getResponsePlugins() as $xPlugin)
157
        {
158
            $sHash .= $xPlugin->generateHash();
159
        }
160
        return md5($sHash);
161
    }
162
163
    /**
164
     * Get the HTML tags to include Jaxon javascript files into the page
165
     *
166
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
167
     */
168
    private function makePluginsCode()
169
    {
170
        if(!$this->sCodeGenerated)
171
        {
172
            $this->sCodeGenerated = true;
173
174
            foreach($this->xPluginManager->getPlugins() as $xPlugin)
175
            {
176
                if($xPlugin instanceof Response)
177
                {
178
                    if(($sCssCode = trim($xPlugin->getCss())))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
179
                    {
180
                        $this->sCssCode .= rtrim($sCssCode, " \n") . "\n";
181
                    }
182
                    if(($sJsCode = trim($xPlugin->getJs())))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
183
                    {
184
                        $this->sJsCode .= rtrim($sJsCode, " \n") . "\n";
185
                    }
186
                }
187
                if(($sJsScript = trim($xPlugin->getScript())))
0 ignored issues
show
Coding Style introduced by
Variable assignment found within a condition. Did you mean to do a comparison ?
Loading history...
188
                {
189
                    $this->sJsScript .= trim($sJsScript, " \n") . "\n";
190
                }
191
            }
192
193
            // foreach($this->xPluginManager->getPackages() as $sPackageClass)
194
            // {
195
            //     $xPackage = jaxon()->di()->get($sPackageClass);
196
            //     if(($sCssCode = trim($xPackage->css())))
197
            //     {
198
            //         $this->sCssCode .= rtrim($sCssCode, " \n") . "\n";
199
            //     }
200
            //     if(($sJsCode = trim($xPackage->js())))
201
            //     {
202
            //         $this->sJsCode .= rtrim($sJsCode, " \n") . "\n";
203
            //     }
204
            //     if(($sJsScript = trim($xPackage->ready())))
205
            //     {
206
            //         $this->sJsScript .= trim($sJsScript, " \n") . "\n";
207
            //     }
208
            // }
209
        }
210
    }
211
212
    /**
213
     * Get the HTML tags to include Jaxon javascript files into the page
214
     *
215
     * @return string
216
     */
217
    public function getJs()
218
    {
219
        $sJsLibUri = $this->getJsLibUri();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
220
        $sJsLibExt = $this->getJsLibExt();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
221
        $sJsCoreUrl = $sJsLibUri . 'jaxon.core' . $sJsLibExt;
1 ignored issue
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
222
        $sJsDebugUrl = $sJsLibUri . 'jaxon.debug' . $sJsLibExt;
223
        // $sJsVerboseUrl = $sJsLibUri . 'jaxon.verbose' . $sJsLibExt;
224
        $sJsLanguageUrl = $sJsLibUri . 'lang/jaxon.' . $this->getOption('core.language') . $sJsLibExt;
225
226
        // Add component files to the javascript file array;
227
        $aJsFiles = [$sJsCoreUrl];
228
        if($this->getOption('core.debug.on'))
229
        {
230
            $aJsFiles[] = $sJsDebugUrl;
231
            $aJsFiles[] = $sJsLanguageUrl;
232
            /*if($this->getOption('core.debug.verbose'))
0 ignored issues
show
Coding Style introduced by
Block comment text must start on a new line
Loading history...
233
            {
234
                $aJsFiles[] = $sJsVerboseUrl;
235
            }*/
236
        }
237
238
        // Set the template engine cache dir
239
        $this->makePluginsCode();
240
241
        return $this->xTemplate->render('jaxon::plugins/includes.js', [
242
            'sJsOptions' => $this->getOption('js.app.options', ''),
243
            'aUrls' => $aJsFiles,
244
        ]) . $this->sJsCode;
245
    }
246
247
    /**
248
     * Get the HTML tags to include Jaxon CSS code and files into the page
249
     *
250
     * @return string
251
     */
252
    public function getCss()
253
    {
254
        // Set the template engine cache dir
255
        $this->makePluginsCode();
256
257
        return $this->sCssCode;
258
    }
259
260
    /**
261
     * Get the correspondances between previous and current config options
262
     *
263
     * They are used to keep the deprecated config options working.
264
     * They will be removed when the deprecated options will lot be supported anymore.
265
     *
266
     * @return array
267
     */
268
    private function getOptionVars()
269
    {
270
        return [
271
            'sResponseType'             => self::RESPONSE_TYPE,
272
            'sVersion'                  => $this->getOption('core.version'),
273
            'sLanguage'                 => $this->getOption('core.language'),
274
            'bLanguage'                 => $this->hasOption('core.language') ? true : false,
275
            'sRequestURI'               => $this->getOption('core.request.uri'),
276
            'sDefaultMode'              => $this->getOption('core.request.mode'),
277
            'sDefaultMethod'            => $this->getOption('core.request.method'),
278
            'sCsrfMetaName'             => $this->getOption('core.request.csrf_meta'),
279
            'bDebug'                    => $this->getOption('core.debug.on'),
280
            'bVerboseDebug'             => $this->getOption('core.debug.verbose'),
281
            'sDebugOutputID'            => $this->getOption('core.debug.output_id'),
282
            'nResponseQueueSize'        => $this->getOption('js.lib.queue_size'),
283
            'sStatusMessages'           => $this->getOption('js.lib.show_status') ? 'true' : 'false',
284
            'sWaitCursor'               => $this->getOption('js.lib.show_cursor') ? 'true' : 'false',
285
            'sDefer'                    => $this->getOption('js.app.options', ''),
286
        ];
287
    }
288
289
    /**
290
     * Get the javascript code to be sent to the browser
291
     *
292
     * @return string
293
     */
294
    private function _getScript()
295
    {
296
        $aVars = $this->getOptionVars();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 19 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
297
        $sYesScript = 'jaxon.ajax.response.process(command.response)';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 14 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
298
        $sNoScript = 'jaxon.confirm.skip(command);jaxon.ajax.response.process(command.response)';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 15 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
299
        $sConfirmScript = jaxon()->dialog()->confirm('msg', $sYesScript, $sNoScript);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
300
        $aVars['sConfirmScript'] = $this->xTemplate->render('jaxon::plugins/confirm.js', [
301
            'sConfirmScript' => $sConfirmScript,
302
        ]);
303
304
        return $this->xTemplate->render('jaxon::plugins/config.js', $aVars) . "\n" . $this->sJsScript . '
305
jaxon.dom.ready(function() {
306
    jaxon.command.handler.register("cc", jaxon.confirm.commands);
307
});
308
';
309
    }
310
311
    /**
312
     * Get the javascript code to be sent to the browser
313
     *
314
     * Also call each of the request plugins giving them the opportunity
315
     * to output some javascript to the page being generated.
316
     * This is called only when the page is being loaded initially.
317
     * This is not called when processing a request.
318
     *
319
     * @param boolean        $bIncludeJs            Also get the JS files
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter name; 12 found
Loading history...
320
     * @param boolean        $bIncludeCss        Also get the CSS files
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 8 found
Loading history...
321
     *
322
     * @return string
323
     */
324
    public function getScript($bIncludeJs = false, $bIncludeCss = false)
325
    {
326
        if(!$this->getOption('core.request.uri'))
327
        {
328
            $this->setOption('core.request.uri', jaxon()->di()->get(URI::class)->detect());
329
        }
330
331
        // Set the template engine cache dir
332
        $this->makePluginsCode();
333
334
        $sScript = '';
335
        if(($bIncludeCss))
336
        {
337
            $sScript .= $this->getCss() . "\n";
338
        }
339
        if(($bIncludeJs))
340
        {
341
            $sScript .= $this->getJs() . "\n";
342
        }
343
344
        if($this->canExportJavascript())
345
        {
346
            $sJsAppURI = rtrim($this->getOption('js.app.uri'), '/') . '/';
1 ignored issue
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
347
            $sJsAppDir = rtrim($this->getOption('js.app.dir'), '/') . '/';
1 ignored issue
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
348
            $sFinalFile = $this->getOption('js.app.file');
349
            $sExtension = $this->getJsLibExt();
350
351
            // Check if the final file already exists
352
            if(($sFinalFile) && is_file($sJsAppDir . $sFinalFile . $sExtension))
353
            {
354
                $sOutFile = $sFinalFile . $sExtension;
355
            }
356
            else
357
            {
358
                // The plugins scripts are written into the javascript app dir
359
                $sHash = $this->generateHash();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
360
                $sOutFile = $sHash . '.js';
361
                $sMinFile = $sHash . '.min.js';
362
                if(!is_file($sJsAppDir . $sOutFile))
363
                {
364
                    file_put_contents($sJsAppDir . $sOutFile, $this->_getScript());
365
                }
366
                if(($this->getOption('js.app.minify')))
367
                {
368
                    if(is_file($sJsAppDir . $sMinFile))
369
                    {
370
                        $sOutFile = $sMinFile; // The file was already minified
371
                    }
372
                    elseif(($this->minify($sJsAppDir . $sOutFile, $sJsAppDir . $sMinFile)))
373
                    {
374
                        $sOutFile = $sMinFile;
375
                    }
376
                }
377
                // Copy the file to its final location
378
                if(($sFinalFile))
379
                {
380
                    if(copy($sJsAppDir . $sOutFile, $sJsAppDir . $sFinalFile . $sExtension))
381
                    {
382
                        $sOutFile = $sFinalFile . $sExtension;
383
                    }
384
                }
385
            }
386
387
            // The returned code loads the generated javascript file
388
            $sScript .= $this->xTemplate->render('jaxon::plugins/include.js', [
389
                'sJsOptions' => $this->getOption('js.app.options', ''),
390
                'sUrl' => $sJsAppURI . $sOutFile,
391
            ]);
392
        }
393
        else
394
        {
395
            // The plugins scripts are wrapped with javascript tags
396
            $sScript .= $this->xTemplate->render('jaxon::plugins/wrapper.js', [
397
                'sJsOptions' => $this->getOption('js.app.options', ''),
398
                'sScript' => $this->_getScript(),
399
            ]);
400
        }
401
402
        return $sScript;
403
    }
404
}
405