Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@0
|
4 * @file
|
Chris@0
|
5 * Utility functions related to Drupal.
|
Chris@0
|
6 */
|
Chris@0
|
7
|
Chris@0
|
8 use Drush\Log\LogLevel;
|
Chris@0
|
9
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Loads the Drupal autoloader and returns the instance.
|
Chris@0
|
12 */
|
Chris@0
|
13 function drush_drupal_load_autoloader($drupal_root) {
|
Chris@0
|
14 static $autoloader = FALSE;
|
Chris@0
|
15
|
Chris@0
|
16 if (!$autoloader) {
|
Chris@0
|
17 $autoloader = require $drupal_root .'/autoload.php';
|
Chris@0
|
18 if ($autoloader === TRUE) {
|
Chris@0
|
19 // The autoloader was already require(). Assume that Drush and Drupal share an autoloader per
|
Chris@0
|
20 // "Point autoload.php to the proper vendor directory" - https://www.drupal.org/node/2404989
|
Chris@0
|
21 $autoloader = drush_get_context('DRUSH_CLASSLOADER');
|
Chris@0
|
22 }
|
Chris@0
|
23 }
|
Chris@0
|
24 return $autoloader;
|
Chris@0
|
25 }
|
Chris@0
|
26
|
Chris@0
|
27 /**
|
Chris@0
|
28 * Detects the version number of the current Drupal installation,
|
Chris@0
|
29 * if any. Returns FALSE if there is no current Drupal installation,
|
Chris@0
|
30 * or it is somehow broken.
|
Chris@0
|
31 *
|
Chris@0
|
32 * @return
|
Chris@0
|
33 * A string containing the version number of the current
|
Chris@0
|
34 * Drupal installation, if any. Otherwise, return FALSE.
|
Chris@0
|
35 */
|
Chris@0
|
36 function drush_drupal_version($drupal_root = NULL) {
|
Chris@0
|
37 static $version = FALSE;
|
Chris@0
|
38
|
Chris@0
|
39 if (!$version) {
|
Chris@0
|
40 if (($drupal_root != NULL) || ($drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT'))) {
|
Chris@0
|
41 $bootstrap = drush_bootstrap_class_for_root($drupal_root);
|
Chris@0
|
42 if ($bootstrap) {
|
Chris@0
|
43 $version = $bootstrap->get_version($drupal_root);
|
Chris@0
|
44 }
|
Chris@0
|
45 }
|
Chris@0
|
46 }
|
Chris@0
|
47 return $version;
|
Chris@0
|
48 }
|
Chris@0
|
49
|
Chris@0
|
50 function drush_drupal_cache_clear_all() {
|
Chris@0
|
51 if (drush_drupal_major_version() >= 8) {
|
Chris@0
|
52 drush_invoke_process('@self', 'cache-rebuild');
|
Chris@0
|
53 }
|
Chris@0
|
54 else {
|
Chris@0
|
55 drush_invoke_process('@self', 'cache-clear', array('all'));
|
Chris@0
|
56 }
|
Chris@0
|
57 }
|
Chris@0
|
58
|
Chris@0
|
59 /**
|
Chris@0
|
60 * Returns the Drupal major version number (6, 7, 8 ...)
|
Chris@0
|
61 */
|
Chris@0
|
62 function drush_drupal_major_version($drupal_root = NULL) {
|
Chris@0
|
63 $major_version = FALSE;
|
Chris@0
|
64 if ($version = drush_drupal_version($drupal_root)) {
|
Chris@0
|
65 $version_parts = explode('.', $version);
|
Chris@0
|
66 if (is_numeric($version_parts[0])) {
|
Chris@0
|
67 $major_version = (integer)$version_parts[0];
|
Chris@0
|
68 }
|
Chris@0
|
69 }
|
Chris@0
|
70 return $major_version;
|
Chris@0
|
71 }
|
Chris@0
|
72
|
Chris@0
|
73 /**
|
Chris@0
|
74 * Log Drupal watchdog() calls.
|
Chris@0
|
75 *
|
Chris@0
|
76 * A sneaky implementation of hook_watchdog(), for D6/D7.
|
Chris@0
|
77 */
|
Chris@0
|
78 function system_watchdog($log_entry) {
|
Chris@0
|
79 // Transform non informative severity levels to 'error' for compatibility with _drush_print_log.
|
Chris@0
|
80 // Other severity levels are coincident with the ones we use in drush.
|
Chris@0
|
81 if (drush_drupal_major_version() >= 6 && $log_entry['severity'] <= 2) {
|
Chris@0
|
82 $severity = 'error';
|
Chris@0
|
83 }
|
Chris@0
|
84 else {
|
Chris@0
|
85 drush_include_engine('drupal', 'environment');
|
Chris@0
|
86 $levels = drush_watchdog_severity_levels();
|
Chris@0
|
87 $severity = $levels[$log_entry['severity']];
|
Chris@0
|
88 }
|
Chris@0
|
89 // Format the message.
|
Chris@0
|
90 if (is_array($log_entry['variables'])) {
|
Chris@0
|
91 $message = strtr($log_entry['message'], $log_entry['variables']);
|
Chris@0
|
92 }
|
Chris@0
|
93 else {
|
Chris@0
|
94 $message = $log_entry['message'];
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97 // decode_entities() only loaded after FULL bootstrap.
|
Chris@0
|
98 if (function_exists('decode_entities')) {
|
Chris@0
|
99 $message = decode_entities($message);
|
Chris@0
|
100 }
|
Chris@0
|
101 $message = strip_tags($message);
|
Chris@0
|
102
|
Chris@0
|
103 // Log or print or ignore. Just printing saves memory but thats rarely needed.
|
Chris@0
|
104 switch (drush_get_option('watchdog', 'log')) {
|
Chris@0
|
105 case 'log':
|
Chris@0
|
106 drush_log('WD '. $log_entry['type'] . ': ' . $message, $severity);
|
Chris@0
|
107 break;
|
Chris@0
|
108 case 'print':
|
Chris@0
|
109 // Disable in backend mode since it logs output and the goal is to conserve memory.
|
Chris@0
|
110 // @see _drush_bootstrap_drush().
|
Chris@0
|
111 if (ob_get_length() === FALSE) {
|
Chris@0
|
112 drush_print('WD '. $severity . ' ' . $log_entry['type'] . ': ' . $message);
|
Chris@0
|
113 }
|
Chris@0
|
114 break;
|
Chris@0
|
115 default:
|
Chris@0
|
116 // Do nothing.
|
Chris@0
|
117 }
|
Chris@0
|
118 }
|
Chris@0
|
119
|
Chris@0
|
120 /**
|
Chris@0
|
121 * Log the return value of Drupal hook_update_n functions.
|
Chris@0
|
122 *
|
Chris@0
|
123 * This is used during install and update to log the output
|
Chris@0
|
124 * of the update process to the logging system.
|
Chris@0
|
125 */
|
Chris@0
|
126 function _drush_log_update_sql($ret) {
|
Chris@0
|
127 if (count($ret)) {
|
Chris@0
|
128 foreach ($ret as $info) {
|
Chris@0
|
129 if (is_array($info)) {
|
Chris@0
|
130 if (!$info['success']) {
|
Chris@0
|
131 drush_set_error('DRUPAL_UPDATE_FAILED', $info['query']);
|
Chris@0
|
132 }
|
Chris@0
|
133 else {
|
Chris@0
|
134 drush_log($info['query'], ($info['success']) ? LogLevel::SUCCESS : LogLevel::ERROR);
|
Chris@0
|
135 }
|
Chris@0
|
136 }
|
Chris@0
|
137 }
|
Chris@0
|
138 }
|
Chris@0
|
139 }
|
Chris@0
|
140
|
Chris@0
|
141 function drush_find_profiles($drupal_root , $key = 'name') {
|
Chris@0
|
142 return drush_scan_directory($drupal_root . '/profiles', "/.*\.profile$/", array('.', '..', 'CVS', 'tests'), 0, 2, $key);
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 /**
|
Chris@0
|
146 * Parse Drupal info file format.
|
Chris@0
|
147 *
|
Chris@0
|
148 * Copied with modifications from includes/common.inc.
|
Chris@0
|
149 *
|
Chris@0
|
150 * @see drupal_parse_info_file
|
Chris@0
|
151 */
|
Chris@0
|
152 function drush_drupal_parse_info_file($filename) {
|
Chris@0
|
153 if (!file_exists($filename)) {
|
Chris@0
|
154 return array();
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 $data = file_get_contents($filename);
|
Chris@0
|
158 return _drush_drupal_parse_info_file($data);
|
Chris@0
|
159 }
|
Chris@0
|
160
|
Chris@0
|
161 /**
|
Chris@0
|
162 * Parse the info file.
|
Chris@0
|
163 */
|
Chris@0
|
164 function _drush_drupal_parse_info_file($data, $merge_item = NULL) {
|
Chris@0
|
165 if (!$data) {
|
Chris@0
|
166 return FALSE;
|
Chris@0
|
167 }
|
Chris@0
|
168
|
Chris@0
|
169 if (preg_match_all('
|
Chris@0
|
170 @^\s* # Start at the beginning of a line, ignoring leading whitespace
|
Chris@0
|
171 ((?:
|
Chris@0
|
172 [^=;\[\]]| # Key names cannot contain equal signs, semi-colons or square brackets,
|
Chris@0
|
173 \[[^\[\]]*\] # unless they are balanced and not nested
|
Chris@0
|
174 )+?)
|
Chris@0
|
175 \s*=\s* # Key/value pairs are separated by equal signs (ignoring white-space)
|
Chris@0
|
176 (?:
|
Chris@0
|
177 ("(?:[^"]|(?<=\\\\)")*")| # Double-quoted string, which may contain slash-escaped quotes/slashes
|
Chris@0
|
178 (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes
|
Chris@0
|
179 ([^\r\n]*?) # Non-quoted string
|
Chris@0
|
180 )\s*$ # Stop at the next end of a line, ignoring trailing whitespace
|
Chris@0
|
181 @msx', $data, $matches, PREG_SET_ORDER)) {
|
Chris@0
|
182 $info = array();
|
Chris@0
|
183 foreach ($matches as $match) {
|
Chris@0
|
184 // Fetch the key and value string.
|
Chris@0
|
185 $i = 0;
|
Chris@0
|
186 foreach (array('key', 'value1', 'value2', 'value3') as $var) {
|
Chris@0
|
187 $$var = isset($match[++$i]) ? $match[$i] : '';
|
Chris@0
|
188 }
|
Chris@0
|
189 $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3;
|
Chris@0
|
190
|
Chris@0
|
191 // Parse array syntax.
|
Chris@0
|
192 $keys = preg_split('/\]?\[/', rtrim($key, ']'));
|
Chris@0
|
193 $last = array_pop($keys);
|
Chris@0
|
194 $parent = &$info;
|
Chris@0
|
195
|
Chris@0
|
196 // Create nested arrays.
|
Chris@0
|
197 foreach ($keys as $key) {
|
Chris@0
|
198 if ($key == '') {
|
Chris@0
|
199 $key = count($parent);
|
Chris@0
|
200 }
|
Chris@0
|
201 if (isset($merge_item) && isset($parent[$key]) && !is_array($parent[$key])) {
|
Chris@0
|
202 $parent[$key] = array($merge_item => $parent[$key]);
|
Chris@0
|
203 }
|
Chris@0
|
204 if (!isset($parent[$key]) || !is_array($parent[$key])) {
|
Chris@0
|
205 $parent[$key] = array();
|
Chris@0
|
206 }
|
Chris@0
|
207 $parent = &$parent[$key];
|
Chris@0
|
208 }
|
Chris@0
|
209
|
Chris@0
|
210 // Handle PHP constants.
|
Chris@0
|
211 if (defined($value)) {
|
Chris@0
|
212 $value = constant($value);
|
Chris@0
|
213 }
|
Chris@0
|
214
|
Chris@0
|
215 // Insert actual value.
|
Chris@0
|
216 if ($last == '') {
|
Chris@0
|
217 $last = count($parent);
|
Chris@0
|
218 }
|
Chris@0
|
219 if (isset($merge_item) && isset($parent[$last]) && is_array($parent[$last])) {
|
Chris@0
|
220 $parent[$last][$merge_item] = $value;
|
Chris@0
|
221 }
|
Chris@0
|
222 else {
|
Chris@0
|
223 $parent[$last] = $value;
|
Chris@0
|
224 }
|
Chris@0
|
225 }
|
Chris@0
|
226 return $info;
|
Chris@0
|
227 }
|
Chris@0
|
228 return FALSE;
|
Chris@0
|
229 }
|
Chris@0
|
230
|
Chris@0
|
231 /**
|
Chris@0
|
232 * Build a cache id to store the install_profile for a given site.
|
Chris@0
|
233 */
|
Chris@0
|
234 function drush_cid_install_profile() {
|
Chris@0
|
235 return drush_get_cid('install_profile', array(), array(drush_get_context('DRUSH_SELECTED_DRUPAL_SITE_CONF_PATH')));
|
Chris@0
|
236 }
|
Chris@0
|
237
|
Chris@0
|
238 /*
|
Chris@0
|
239 * An array of options shared by sql-sanitize and sql-sync commands.
|
Chris@0
|
240 */
|
Chris@0
|
241 function drupal_sanitize_options() {
|
Chris@0
|
242 return array(
|
Chris@0
|
243 'sanitize-password' => array(
|
Chris@0
|
244 'description' => 'The password to assign to all accounts in the sanitization operation, or "no" to keep passwords unchanged.',
|
Chris@0
|
245 'example-value' => 'password',
|
Chris@0
|
246 'value' => 'required',
|
Chris@0
|
247 ),
|
Chris@0
|
248 'sanitize-email' => array(
|
Chris@0
|
249 'description' => 'The pattern for test email addresses in the sanitization operation, or "no" to keep email addresses unchanged. May contain replacement patterns %uid, %mail or %name.',
|
Chris@0
|
250 'example-value' => 'user+%uid@localhost',
|
Chris@0
|
251 'value' => 'required',
|
Chris@0
|
252 ),
|
Chris@0
|
253 );
|
Chris@0
|
254 }
|