Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace DrupalCodeGenerator;
|
Chris@0
|
4
|
Chris@0
|
5 use Symfony\Component\Console\Question\Question;
|
Chris@0
|
6
|
Chris@0
|
7 /**
|
Chris@0
|
8 * Helper methods for code generators.
|
Chris@0
|
9 */
|
Chris@0
|
10 class Utils {
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * Creates default plugin ID.
|
Chris@0
|
14 */
|
Chris@0
|
15 public static function defaultPluginId(array $vars) {
|
Chris@0
|
16 return $vars['machine_name'] . '_' . self::human2machine($vars['plugin_label']);
|
Chris@0
|
17 }
|
Chris@0
|
18
|
Chris@0
|
19 /**
|
Chris@0
|
20 * Transforms a machine name to human name.
|
Chris@0
|
21 */
|
Chris@0
|
22 public static function machine2human($machine_name) {
|
Chris@0
|
23 return ucfirst(trim(str_replace('_', ' ', $machine_name)));
|
Chris@0
|
24 }
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Transforms a human name to machine name.
|
Chris@0
|
28 */
|
Chris@0
|
29 public static function human2machine($human_name) {
|
Chris@0
|
30 return trim(preg_replace(
|
Chris@0
|
31 ['/^[0-9]+/', '/[^a-z0-9_]+/'],
|
Chris@0
|
32 '_',
|
Chris@0
|
33 strtolower($human_name)
|
Chris@0
|
34 ), '_');
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 /**
|
Chris@4
|
38 * Transforms a camelized sting to machine name.
|
Chris@4
|
39 */
|
Chris@4
|
40 public static function camel2machine($input) {
|
Chris@4
|
41 return self::human2machine(preg_replace('/[A-Z]/', ' \0', $input));
|
Chris@4
|
42 }
|
Chris@4
|
43
|
Chris@4
|
44 /**
|
Chris@0
|
45 * Camelize a string.
|
Chris@0
|
46 */
|
Chris@0
|
47 public static function camelize($string, $upper_camel = TRUE) {
|
Chris@0
|
48 $output = preg_replace('/([^A-Z])([A-Z])/', '$1 $2', $string);
|
Chris@0
|
49 $output = strtolower($output);
|
Chris@0
|
50 $output = preg_replace('/[^a-z0-9]/', ' ', $output);
|
Chris@0
|
51 $output = trim($output);
|
Chris@0
|
52 $output = ucwords($output);
|
Chris@0
|
53 $output = str_replace(' ', '', $output);
|
Chris@0
|
54 return $upper_camel ? $output : lcfirst($output);
|
Chris@0
|
55 }
|
Chris@0
|
56
|
Chris@0
|
57 /**
|
Chris@0
|
58 * Machine name validator.
|
Chris@0
|
59 */
|
Chris@0
|
60 public static function validateMachineName($value) {
|
Chris@0
|
61 if (!preg_match('/^[a-z][a-z0-9_]*[a-z0-9]$/', $value)) {
|
Chris@0
|
62 throw new \UnexpectedValueException('The value is not correct machine name.');
|
Chris@0
|
63 }
|
Chris@0
|
64 return $value;
|
Chris@0
|
65 }
|
Chris@0
|
66
|
Chris@0
|
67 /**
|
Chris@0
|
68 * Class name validator.
|
Chris@0
|
69 *
|
Chris@0
|
70 * @see http://php.net/manual/en/language.oop5.basic.php
|
Chris@0
|
71 */
|
Chris@0
|
72 public static function validateClassName($value) {
|
Chris@0
|
73 if (!preg_match('/^[A-Z][a-zA-Z0-9]+$/', $value)) {
|
Chris@0
|
74 throw new \UnexpectedValueException('The value is not correct class name.');
|
Chris@0
|
75 }
|
Chris@0
|
76 return $value;
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 /**
|
Chris@4
|
80 * Service name validator.
|
Chris@4
|
81 */
|
Chris@4
|
82 public static function validateServiceName($value) {
|
Chris@4
|
83 if ($value !== '' && !preg_match('/^[a-z][a-z0-9_\.]*[a-z0-9]$/', $value)) {
|
Chris@4
|
84 throw new \UnexpectedValueException('The value is not correct service name.');
|
Chris@4
|
85 }
|
Chris@4
|
86 return $value;
|
Chris@4
|
87 }
|
Chris@4
|
88
|
Chris@4
|
89 /**
|
Chris@0
|
90 * Required value validator.
|
Chris@0
|
91 */
|
Chris@0
|
92 public static function validateRequired($value) {
|
Chris@0
|
93 // FALSE is not considered as empty value because question helper use
|
Chris@0
|
94 // it as negative answer on confirmation questions.
|
Chris@0
|
95 if ($value === NULL || $value === '') {
|
Chris@0
|
96 throw new \UnexpectedValueException('The value is required.');
|
Chris@0
|
97 }
|
Chris@0
|
98 return $value;
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 /**
|
Chris@0
|
102 * Returns normalized file path.
|
Chris@0
|
103 *
|
Chris@0
|
104 * @codeCoverageIgnore
|
Chris@0
|
105 * @deprecated
|
Chris@0
|
106 */
|
Chris@0
|
107 public static function normalizePath($path) {
|
Chris@0
|
108 $parts = [];
|
Chris@0
|
109 $path = str_replace('\\', '/', $path);
|
Chris@0
|
110 $path = preg_replace('/\/+/', '/', $path);
|
Chris@0
|
111 $segments = explode('/', $path);
|
Chris@0
|
112 foreach ($segments as $segment) {
|
Chris@0
|
113 if ($segment != '.') {
|
Chris@0
|
114 $test = array_pop($parts);
|
Chris@0
|
115 if (is_null($test)) {
|
Chris@0
|
116 $parts[] = $segment;
|
Chris@0
|
117 }
|
Chris@0
|
118 elseif ($segment == '..') {
|
Chris@0
|
119 if ($test == '..') {
|
Chris@0
|
120 $parts[] = $test;
|
Chris@0
|
121 }
|
Chris@0
|
122 if ($test == '..' || $test == '') {
|
Chris@0
|
123 $parts[] = $segment;
|
Chris@0
|
124 }
|
Chris@0
|
125 }
|
Chris@0
|
126 else {
|
Chris@0
|
127 $parts[] = $test;
|
Chris@0
|
128 $parts[] = $segment;
|
Chris@0
|
129 }
|
Chris@0
|
130 }
|
Chris@0
|
131 }
|
Chris@0
|
132 return implode('/', $parts);
|
Chris@0
|
133 }
|
Chris@0
|
134
|
Chris@0
|
135 /**
|
Chris@0
|
136 * Returns default questions for module generators.
|
Chris@0
|
137 *
|
Chris@0
|
138 * @return \Symfony\Component\Console\Question\Question[]
|
Chris@0
|
139 * Array of default questions.
|
Chris@0
|
140 */
|
Chris@0
|
141 public static function defaultQuestions() {
|
Chris@0
|
142 $questions['name'] = new Question('Module name');
|
Chris@0
|
143 $questions['name']->setValidator([Utils::class, 'validateRequired']);
|
Chris@0
|
144 $questions['machine_name'] = new Question('Module machine name');
|
Chris@0
|
145 $questions['machine_name']->setValidator([Utils::class, 'validateMachineName']);
|
Chris@0
|
146 return $questions;
|
Chris@0
|
147 }
|
Chris@0
|
148
|
Chris@0
|
149 /**
|
Chris@0
|
150 * Returns default questions for plugin generators.
|
Chris@0
|
151 *
|
Chris@0
|
152 * @return \Symfony\Component\Console\Question\Question[]
|
Chris@0
|
153 * Array of default questions.
|
Chris@0
|
154 */
|
Chris@0
|
155 public static function defaultPluginQuestions() {
|
Chris@0
|
156 $questions = Utils::defaultQuestions();
|
Chris@0
|
157 $questions['plugin_label'] = new Question('Plugin label', 'Example');
|
Chris@0
|
158 $questions['plugin_label']->setValidator([Utils::class, 'validateRequired']);
|
Chris@0
|
159 $questions['plugin_id'] = new Question('Plugin ID', [Utils::class, 'defaultPluginId']);
|
Chris@0
|
160 $questions['plugin_id']->setValidator([Utils::class, 'validateMachineName']);
|
Chris@0
|
161 return $questions;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 /**
|
Chris@0
|
165 * Returns extension root.
|
Chris@0
|
166 *
|
Chris@0
|
167 * @return string|bool
|
Chris@0
|
168 * Extension root directory or false if it was not found.
|
Chris@0
|
169 */
|
Chris@0
|
170 public static function getExtensionRoot($directory) {
|
Chris@0
|
171 $extension_root = FALSE;
|
Chris@0
|
172 for ($i = 1; $i <= 5; $i++) {
|
Chris@0
|
173 $info_file = $directory . '/' . basename($directory) . '.info';
|
Chris@4
|
174 if ((file_exists($info_file) && basename($directory) !== 'drush') || file_exists($info_file . '.yml')) {
|
Chris@0
|
175 $extension_root = $directory;
|
Chris@0
|
176 break;
|
Chris@0
|
177 }
|
Chris@0
|
178 $directory = dirname($directory);
|
Chris@0
|
179 }
|
Chris@0
|
180 return $extension_root;
|
Chris@0
|
181 }
|
Chris@0
|
182
|
Chris@0
|
183 /**
|
Chris@0
|
184 * Removes a given number of lines from the beginning of the string.
|
Chris@0
|
185 */
|
Chris@0
|
186 public static function removeHeader($content, $header_size) {
|
Chris@0
|
187 return implode("\n", array_slice(explode("\n", $content), $header_size));
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 /**
|
Chris@0
|
191 * Return the user's home directory.
|
Chris@0
|
192 */
|
Chris@0
|
193 public static function getHomeDirectory() {
|
Chris@0
|
194 return isset($_SERVER['HOME']) ? $_SERVER['HOME'] : getenv('HOME');
|
Chris@0
|
195 }
|
Chris@0
|
196
|
Chris@0
|
197 /**
|
Chris@0
|
198 * Replaces all tokens in a given string with appropriate values.
|
Chris@0
|
199 *
|
Chris@0
|
200 * @param string $text
|
Chris@0
|
201 * A string potentially containing replaceable tokens.
|
Chris@0
|
202 * @param array $data
|
Chris@0
|
203 * An array where keys are token names and values are replacements.
|
Chris@0
|
204 *
|
Chris@0
|
205 * @return string
|
Chris@0
|
206 * Text with tokens replaced.
|
Chris@0
|
207 */
|
Chris@0
|
208 public static function tokenReplace($text, array $data) {
|
Chris@0
|
209 $tokens = [];
|
Chris@0
|
210 foreach ($data as $var_name => $var) {
|
Chris@0
|
211 if (is_string($var)) {
|
Chris@0
|
212 $tokens['{' . $var_name . '}'] = $var;
|
Chris@0
|
213 }
|
Chris@0
|
214 }
|
Chris@0
|
215 return str_replace(array_keys($tokens), array_values($tokens), $text);
|
Chris@0
|
216 }
|
Chris@0
|
217
|
Chris@4
|
218 /**
|
Chris@4
|
219 * Pluralizes a noun.
|
Chris@4
|
220 *
|
Chris@4
|
221 * @param string $string
|
Chris@4
|
222 * A noun to pluralize.
|
Chris@4
|
223 *
|
Chris@4
|
224 * @return string
|
Chris@4
|
225 * The pluralized noun.
|
Chris@4
|
226 */
|
Chris@4
|
227 public static function pluralize($string) {
|
Chris@4
|
228 switch (substr($string, -1)) {
|
Chris@4
|
229 case 'y':
|
Chris@4
|
230 return substr($string, 0, -1) . 'ies';
|
Chris@4
|
231
|
Chris@4
|
232 case 's':
|
Chris@4
|
233 return $string . 'es';
|
Chris@4
|
234
|
Chris@4
|
235 default:
|
Chris@4
|
236 return $string . 's';
|
Chris@4
|
237 }
|
Chris@4
|
238 }
|
Chris@4
|
239
|
Chris@4
|
240 /**
|
Chris@4
|
241 * Prepares choices.
|
Chris@4
|
242 *
|
Chris@4
|
243 * @param array $raw_choices
|
Chris@4
|
244 * The choices to be prepared.
|
Chris@4
|
245 *
|
Chris@4
|
246 * @return array
|
Chris@4
|
247 * The prepared choices.
|
Chris@4
|
248 */
|
Chris@4
|
249 public static function prepareChoices(array $raw_choices) {
|
Chris@4
|
250 // The $raw_choices can be an associative array.
|
Chris@4
|
251 $choices = array_values($raw_choices);
|
Chris@4
|
252 // Start choices list form '1'.
|
Chris@4
|
253 array_unshift($choices, NULL);
|
Chris@4
|
254 unset($choices[0]);
|
Chris@4
|
255 return $choices;
|
Chris@4
|
256 }
|
Chris@4
|
257
|
Chris@0
|
258 }
|