Editor::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
/**
4
 * @package Theme editor
5
 * @author Iurii Makukh <[email protected]>
6
 * @copyright Copyright (c) 2015, Iurii Makukh
7
 * @license https://www.gnu.org/licenses/gpl.html GNU/GPLv3
8
 */
9
10
namespace gplcart\modules\editor\models;
11
12
use Exception;
13
use gplcart\core\Hook;
14
use gplcart\core\Module;
15
16
/**
17
 * Manages basic behaviors and data related to Theme Editor module
18
 */
19
class Editor
20
{
21
22
    /**
23
     * Hook class instance
24
     * @var \gplcart\core\Hook $hook
25
     */
26
    protected $hook;
27
28
    /**
29
     * Module class instance
30
     * @var \gplcart\core\Module $module
31
     */
32
    protected $module;
33
34
    /**
35
     * @param Hook $hook
36
     * @param Module $module
37
     */
38
    public function __construct(Hook $hook, Module $module)
39
    {
40
        $this->hook = $hook;
41
        $this->module = $module;
42
    }
43
44
    /**
45
     * Returns an array of editable files
46
     * @param array $module
47
     * @return array
48
     */
49
    public function getList(array $module)
50
    {
51
        $list = array();
52
53
        foreach ($this->getScanFolders() as $folder) {
54
            $files = gplcart_file_scan_recursive("{$module['directory']}/$folder");
55
            sort($files);
56
            $list[$folder] = $files;
57
        }
58
59
        $this->hook->attach('module.editor.list', $list);
60
        return $list;
61
    }
62
63
    /**
64
     * Returns an array of folder names to scan
65
     * @return array
66
     */
67
    protected function getScanFolders()
68
    {
69
        return array('templates', 'css', 'js');
70
    }
71
72
    /**
73
     * Saves an edited file
74
     * @param array $data
75
     * @return boolean
76
     */
77
    public function save($data)
78
    {
79
        $result = null;
80
        $this->hook->attach('module.editor.save.before', $data, $result);
81
82
        if (isset($result)) {
83
            return $result;
84
        }
85
86
        if (!$this->backup($data)) {
87
            return false;
88
        }
89
90
        $result = $this->write($data['content'], $data['path']);
91
        $this->hook->attach('module.editor.save.after', $data, $result);
92
        return $result;
93
    }
94
95
    /**
96
     * Backup a module
97
     * @param array $data
98
     * @return bool
99
     */
100
    protected function backup(array $data)
101
    {
102
        $has_backup = true;
103
104
        try {
105
106
            /* @var $backup \gplcart\modules\backup\Main */
107
            $backup = $this->module->getInstance('backup');
108
109
            if (!$backup->exists($data['module']['id'])) {
110
                $has_backup = $backup->backup('module', $data['module']) === true;
111
            }
112
113
        } catch (Exception $ex) {
114
            trigger_error($ex->getMessage());
115
            $has_backup = false;
116
        }
117
118
        return $has_backup;
119
    }
120
121
    /**
122
     * Writes a content to a file
123
     * @param string $content
124
     * @param string $file
125
     * @return boolean
126
     */
127
    protected function write($content, $file)
128
    {
129
        if (file_exists($file)) { // Do not create a new file
130
            return file_put_contents($file, $content) !== false;
131
        }
132
133
        return false;
134
    }
135
136
    /**
137
     * Tries to validate syntax of a PHP file
138
     * @param string $file
139
     * @return mixed
140
     */
141
    public function validatePhpFile($file)
142
    {
143
        if (!$this->canValidatePhpCode()) {
144
            return null;
145
        }
146
147
        $output = shell_exec('php -l ' . escapeshellarg($file));
148
149
        $count = 0;
150
        $error = preg_replace('/Errors parsing.*$/', '', $output, -1, $count);
151
        return $count > 0 ? trim("$error") : true;
152
    }
153
154
    /**
155
     * Whether it's possible to validate a PHP code
156
     * @return bool
157
     */
158
    public function canValidatePhpCode()
159
    {
160
        return function_exists('shell_exec') && !in_array('shell_exec', explode(',', ini_get('disable_functions')));
161
    }
162
163
    /**
164
     * Tries to validate a PHP code
165
     * @param string $code
166
     * @return mixed
167
     */
168
    public function validatePhpCode($code)
169
    {
170
        $temp = tmpfile();
171
        fwrite($temp, $code);
172
        $meta_data = stream_get_meta_data($temp);
173
174
        $result = $this->validatePhpFile($meta_data['uri']);
175
        fclose($temp);
176
        return $result;
177
    }
178
179
}
180