@@ -7,50 +7,50 @@ |
||
7 | 7 | */ |
8 | 8 | trait CsvTrait |
9 | 9 | { |
10 | - protected static $csvEscapeChar; |
|
11 | - |
|
12 | - /** |
|
13 | - * Check whether support the escape_char argument to fgetcsv/fputcsv or not |
|
14 | - * |
|
15 | - * @return bool |
|
16 | - */ |
|
17 | - protected static function supportsCsvEscapeChar() |
|
18 | - { |
|
19 | - if (static::$csvEscapeChar === null) { |
|
20 | - static::$csvEscapeChar = version_compare(PHP_VERSION, '5.5.4') >= 0; |
|
21 | - } |
|
22 | - |
|
23 | - return static::$csvEscapeChar; |
|
24 | - } |
|
25 | - |
|
26 | - /** |
|
27 | - * @param resource $handle |
|
28 | - * @param array $options |
|
29 | - * |
|
30 | - * @return array |
|
31 | - */ |
|
32 | - protected static function fgetcsv($handle, $options) |
|
33 | - { |
|
34 | - if (static::supportsCsvEscapeChar()) { |
|
35 | - return fgetcsv($handle, 0, $options['delimiter'], $options['enclosure'], $options['escape_char']); |
|
36 | - } |
|
37 | - |
|
38 | - return fgetcsv($handle, 0, $options['delimiter'], $options['enclosure']); |
|
39 | - } |
|
40 | - |
|
41 | - /** |
|
42 | - * @param resource $handle |
|
43 | - * @param array $fields |
|
44 | - * @param array $options |
|
45 | - * |
|
46 | - * @return bool|int |
|
47 | - */ |
|
48 | - protected static function fputcsv($handle, $fields, $options) |
|
49 | - { |
|
50 | - if (static::supportsCsvEscapeChar()) { |
|
51 | - return fputcsv($handle, $fields, $options['delimiter'], $options['enclosure'], $options['escape_char']); |
|
52 | - } |
|
53 | - |
|
54 | - return fputcsv($handle, $fields, $options['delimiter'], $options['enclosure']); |
|
55 | - } |
|
10 | + protected static $csvEscapeChar; |
|
11 | + |
|
12 | + /** |
|
13 | + * Check whether support the escape_char argument to fgetcsv/fputcsv or not |
|
14 | + * |
|
15 | + * @return bool |
|
16 | + */ |
|
17 | + protected static function supportsCsvEscapeChar() |
|
18 | + { |
|
19 | + if (static::$csvEscapeChar === null) { |
|
20 | + static::$csvEscapeChar = version_compare(PHP_VERSION, '5.5.4') >= 0; |
|
21 | + } |
|
22 | + |
|
23 | + return static::$csvEscapeChar; |
|
24 | + } |
|
25 | + |
|
26 | + /** |
|
27 | + * @param resource $handle |
|
28 | + * @param array $options |
|
29 | + * |
|
30 | + * @return array |
|
31 | + */ |
|
32 | + protected static function fgetcsv($handle, $options) |
|
33 | + { |
|
34 | + if (static::supportsCsvEscapeChar()) { |
|
35 | + return fgetcsv($handle, 0, $options['delimiter'], $options['enclosure'], $options['escape_char']); |
|
36 | + } |
|
37 | + |
|
38 | + return fgetcsv($handle, 0, $options['delimiter'], $options['enclosure']); |
|
39 | + } |
|
40 | + |
|
41 | + /** |
|
42 | + * @param resource $handle |
|
43 | + * @param array $fields |
|
44 | + * @param array $options |
|
45 | + * |
|
46 | + * @return bool|int |
|
47 | + */ |
|
48 | + protected static function fputcsv($handle, $fields, $options) |
|
49 | + { |
|
50 | + if (static::supportsCsvEscapeChar()) { |
|
51 | + return fputcsv($handle, $fields, $options['delimiter'], $options['enclosure'], $options['escape_char']); |
|
52 | + } |
|
53 | + |
|
54 | + return fputcsv($handle, $fields, $options['delimiter'], $options['enclosure']); |
|
55 | + } |
|
56 | 56 | } |
@@ -4,48 +4,48 @@ |
||
4 | 4 | |
5 | 5 | class StringReader |
6 | 6 | { |
7 | - public $pos; |
|
8 | - public $str; |
|
9 | - public $strlen; |
|
10 | - |
|
11 | - /** |
|
12 | - * Constructor. |
|
13 | - * |
|
14 | - * @param string $str The string to read |
|
15 | - */ |
|
16 | - public function __construct($str) |
|
17 | - { |
|
18 | - $this->str = $str; |
|
19 | - $this->strlen = strlen($this->str); |
|
20 | - } |
|
21 | - |
|
22 | - /** |
|
23 | - * Read and returns a part of the string. |
|
24 | - * |
|
25 | - * @param int $bytes The number of bytes to read |
|
26 | - * |
|
27 | - * @return string |
|
28 | - */ |
|
29 | - public function read($bytes) |
|
30 | - { |
|
31 | - $data = substr($this->str, $this->pos, $bytes); |
|
32 | - |
|
33 | - $this->seekto($this->pos + $bytes); |
|
34 | - |
|
35 | - return $data; |
|
36 | - } |
|
37 | - |
|
38 | - /** |
|
39 | - * Move the cursor to a specific position. |
|
40 | - * |
|
41 | - * @param int $pos The amount of bytes to move |
|
42 | - * |
|
43 | - * @return int The new position |
|
44 | - */ |
|
45 | - public function seekto($pos) |
|
46 | - { |
|
47 | - $this->pos = ($this->strlen < $pos) ? $this->strlen : $pos; |
|
48 | - |
|
49 | - return $this->pos; |
|
50 | - } |
|
7 | + public $pos; |
|
8 | + public $str; |
|
9 | + public $strlen; |
|
10 | + |
|
11 | + /** |
|
12 | + * Constructor. |
|
13 | + * |
|
14 | + * @param string $str The string to read |
|
15 | + */ |
|
16 | + public function __construct($str) |
|
17 | + { |
|
18 | + $this->str = $str; |
|
19 | + $this->strlen = strlen($this->str); |
|
20 | + } |
|
21 | + |
|
22 | + /** |
|
23 | + * Read and returns a part of the string. |
|
24 | + * |
|
25 | + * @param int $bytes The number of bytes to read |
|
26 | + * |
|
27 | + * @return string |
|
28 | + */ |
|
29 | + public function read($bytes) |
|
30 | + { |
|
31 | + $data = substr($this->str, $this->pos, $bytes); |
|
32 | + |
|
33 | + $this->seekto($this->pos + $bytes); |
|
34 | + |
|
35 | + return $data; |
|
36 | + } |
|
37 | + |
|
38 | + /** |
|
39 | + * Move the cursor to a specific position. |
|
40 | + * |
|
41 | + * @param int $pos The amount of bytes to move |
|
42 | + * |
|
43 | + * @return int The new position |
|
44 | + */ |
|
45 | + public function seekto($pos) |
|
46 | + { |
|
47 | + $this->pos = ($this->strlen < $pos) ? $this->strlen : $pos; |
|
48 | + |
|
49 | + return $this->pos; |
|
50 | + } |
|
51 | 51 | } |
@@ -7,153 +7,153 @@ |
||
7 | 7 | */ |
8 | 8 | class ParsedFunction |
9 | 9 | { |
10 | - /** |
|
11 | - * The function name. |
|
12 | - * |
|
13 | - * @var string |
|
14 | - */ |
|
15 | - protected $name; |
|
10 | + /** |
|
11 | + * The function name. |
|
12 | + * |
|
13 | + * @var string |
|
14 | + */ |
|
15 | + protected $name; |
|
16 | 16 | |
17 | - /** |
|
18 | - * The line where the function starts. |
|
19 | - * |
|
20 | - * @var int |
|
21 | - */ |
|
22 | - protected $line; |
|
17 | + /** |
|
18 | + * The line where the function starts. |
|
19 | + * |
|
20 | + * @var int |
|
21 | + */ |
|
22 | + protected $line; |
|
23 | 23 | |
24 | - /** |
|
25 | - * The strings extracted from the function arguments. |
|
26 | - * |
|
27 | - * @var string[] |
|
28 | - */ |
|
29 | - protected $arguments; |
|
24 | + /** |
|
25 | + * The strings extracted from the function arguments. |
|
26 | + * |
|
27 | + * @var string[] |
|
28 | + */ |
|
29 | + protected $arguments; |
|
30 | 30 | |
31 | - /** |
|
32 | - * The current index of the function (-1 if no arguments). |
|
33 | - * |
|
34 | - * @var int|null |
|
35 | - */ |
|
36 | - protected $argumentIndex; |
|
31 | + /** |
|
32 | + * The current index of the function (-1 if no arguments). |
|
33 | + * |
|
34 | + * @var int|null |
|
35 | + */ |
|
36 | + protected $argumentIndex; |
|
37 | 37 | |
38 | - /** |
|
39 | - * Shall we stop adding string chunks to the current argument? |
|
40 | - * |
|
41 | - * @var bool |
|
42 | - */ |
|
43 | - protected $argumentStopped; |
|
38 | + /** |
|
39 | + * Shall we stop adding string chunks to the current argument? |
|
40 | + * |
|
41 | + * @var bool |
|
42 | + */ |
|
43 | + protected $argumentStopped; |
|
44 | 44 | |
45 | - /** |
|
46 | - * Extracted comments. |
|
47 | - * |
|
48 | - * @var ParsedComment[]|null |
|
49 | - */ |
|
50 | - protected $comments; |
|
45 | + /** |
|
46 | + * Extracted comments. |
|
47 | + * |
|
48 | + * @var ParsedComment[]|null |
|
49 | + */ |
|
50 | + protected $comments; |
|
51 | 51 | |
52 | - /** |
|
53 | - * Initializes the instance. |
|
54 | - * |
|
55 | - * @param string $name The function name. |
|
56 | - * @param int $line The line where the function starts. |
|
57 | - */ |
|
58 | - public function __construct($name, $line) |
|
59 | - { |
|
60 | - $this->name = $name; |
|
61 | - $this->line = $line; |
|
62 | - $this->arguments = []; |
|
63 | - $this->argumentIndex = -1; |
|
64 | - $this->argumentStopped = false; |
|
65 | - $this->comments = null; |
|
66 | - } |
|
52 | + /** |
|
53 | + * Initializes the instance. |
|
54 | + * |
|
55 | + * @param string $name The function name. |
|
56 | + * @param int $line The line where the function starts. |
|
57 | + */ |
|
58 | + public function __construct($name, $line) |
|
59 | + { |
|
60 | + $this->name = $name; |
|
61 | + $this->line = $line; |
|
62 | + $this->arguments = []; |
|
63 | + $this->argumentIndex = -1; |
|
64 | + $this->argumentStopped = false; |
|
65 | + $this->comments = null; |
|
66 | + } |
|
67 | 67 | |
68 | - /** |
|
69 | - * Stop extracting strings from the current argument (because we found something that's not a string). |
|
70 | - */ |
|
71 | - public function stopArgument() |
|
72 | - { |
|
73 | - if ($this->argumentIndex === -1) { |
|
74 | - $this->argumentIndex = 0; |
|
75 | - } |
|
76 | - $this->argumentStopped = true; |
|
77 | - } |
|
68 | + /** |
|
69 | + * Stop extracting strings from the current argument (because we found something that's not a string). |
|
70 | + */ |
|
71 | + public function stopArgument() |
|
72 | + { |
|
73 | + if ($this->argumentIndex === -1) { |
|
74 | + $this->argumentIndex = 0; |
|
75 | + } |
|
76 | + $this->argumentStopped = true; |
|
77 | + } |
|
78 | 78 | |
79 | - /** |
|
80 | - * Go to the next argument because we a comma was found. |
|
81 | - */ |
|
82 | - public function nextArgument() |
|
83 | - { |
|
84 | - if ($this->argumentIndex === -1) { |
|
85 | - // This should neve occur, but let's stay safe - During test/development an Exception should be thrown. |
|
86 | - $this->argumentIndex = 1; |
|
87 | - } else { |
|
88 | - ++$this->argumentIndex; |
|
89 | - } |
|
90 | - $this->argumentStopped = false; |
|
91 | - } |
|
79 | + /** |
|
80 | + * Go to the next argument because we a comma was found. |
|
81 | + */ |
|
82 | + public function nextArgument() |
|
83 | + { |
|
84 | + if ($this->argumentIndex === -1) { |
|
85 | + // This should neve occur, but let's stay safe - During test/development an Exception should be thrown. |
|
86 | + $this->argumentIndex = 1; |
|
87 | + } else { |
|
88 | + ++$this->argumentIndex; |
|
89 | + } |
|
90 | + $this->argumentStopped = false; |
|
91 | + } |
|
92 | 92 | |
93 | - /** |
|
94 | - * Add a string to the current argument. |
|
95 | - * |
|
96 | - * @param string|null $chunk |
|
97 | - */ |
|
98 | - public function addArgumentChunk($chunk) |
|
99 | - { |
|
100 | - if ($this->argumentStopped === false) { |
|
101 | - if ($this->argumentIndex === -1) { |
|
102 | - $this->argumentIndex = 0; |
|
103 | - } |
|
104 | - if (isset($this->arguments[$this->argumentIndex])) { |
|
105 | - $this->arguments[$this->argumentIndex] .= $chunk; |
|
106 | - } else { |
|
107 | - $this->arguments[$this->argumentIndex] = $chunk; |
|
108 | - } |
|
109 | - } |
|
110 | - } |
|
93 | + /** |
|
94 | + * Add a string to the current argument. |
|
95 | + * |
|
96 | + * @param string|null $chunk |
|
97 | + */ |
|
98 | + public function addArgumentChunk($chunk) |
|
99 | + { |
|
100 | + if ($this->argumentStopped === false) { |
|
101 | + if ($this->argumentIndex === -1) { |
|
102 | + $this->argumentIndex = 0; |
|
103 | + } |
|
104 | + if (isset($this->arguments[$this->argumentIndex])) { |
|
105 | + $this->arguments[$this->argumentIndex] .= $chunk; |
|
106 | + } else { |
|
107 | + $this->arguments[$this->argumentIndex] = $chunk; |
|
108 | + } |
|
109 | + } |
|
110 | + } |
|
111 | 111 | |
112 | - /** |
|
113 | - * Add a comment associated to this function. |
|
114 | - * |
|
115 | - * @param ParsedComment $comment |
|
116 | - */ |
|
117 | - public function addComment($comment) |
|
118 | - { |
|
119 | - if ($this->comments === null) { |
|
120 | - $this->comments = []; |
|
121 | - } |
|
122 | - $this->comments[] = $comment; |
|
123 | - } |
|
112 | + /** |
|
113 | + * Add a comment associated to this function. |
|
114 | + * |
|
115 | + * @param ParsedComment $comment |
|
116 | + */ |
|
117 | + public function addComment($comment) |
|
118 | + { |
|
119 | + if ($this->comments === null) { |
|
120 | + $this->comments = []; |
|
121 | + } |
|
122 | + $this->comments[] = $comment; |
|
123 | + } |
|
124 | 124 | |
125 | - /** |
|
126 | - * Return the line the function starts. |
|
127 | - * |
|
128 | - * @return int Line number. |
|
129 | - */ |
|
130 | - public function getLine() |
|
131 | - { |
|
132 | - return $this->line; |
|
133 | - } |
|
125 | + /** |
|
126 | + * Return the line the function starts. |
|
127 | + * |
|
128 | + * @return int Line number. |
|
129 | + */ |
|
130 | + public function getLine() |
|
131 | + { |
|
132 | + return $this->line; |
|
133 | + } |
|
134 | 134 | |
135 | - /** |
|
136 | - * A closing parenthesis was found: return the final data. |
|
137 | - * The array returned has the following values: |
|
138 | - * 0 => string The function name. |
|
139 | - * 1 => int The line where the function starts. |
|
140 | - * 2 => string[] the strings extracted from the function arguments. |
|
141 | - * 3 => string[] the comments associated to the function. |
|
142 | - * |
|
143 | - * @return array |
|
144 | - */ |
|
145 | - public function close() |
|
146 | - { |
|
147 | - $arguments = []; |
|
148 | - for ($i = 0; $i <= $this->argumentIndex; ++$i) { |
|
149 | - $arguments[$i] = isset($this->arguments[$i]) ? $this->arguments[$i] : null; |
|
150 | - } |
|
135 | + /** |
|
136 | + * A closing parenthesis was found: return the final data. |
|
137 | + * The array returned has the following values: |
|
138 | + * 0 => string The function name. |
|
139 | + * 1 => int The line where the function starts. |
|
140 | + * 2 => string[] the strings extracted from the function arguments. |
|
141 | + * 3 => string[] the comments associated to the function. |
|
142 | + * |
|
143 | + * @return array |
|
144 | + */ |
|
145 | + public function close() |
|
146 | + { |
|
147 | + $arguments = []; |
|
148 | + for ($i = 0; $i <= $this->argumentIndex; ++$i) { |
|
149 | + $arguments[$i] = isset($this->arguments[$i]) ? $this->arguments[$i] : null; |
|
150 | + } |
|
151 | 151 | |
152 | - return [ |
|
153 | - $this->name, |
|
154 | - $this->line, |
|
155 | - $arguments, |
|
156 | - $this->comments, |
|
157 | - ]; |
|
158 | - } |
|
152 | + return [ |
|
153 | + $this->name, |
|
154 | + $this->line, |
|
155 | + $arguments, |
|
156 | + $this->comments, |
|
157 | + ]; |
|
158 | + } |
|
159 | 159 | } |
@@ -6,189 +6,189 @@ |
||
6 | 6 | |
7 | 7 | class PhpFunctionsScanner extends FunctionsScanner |
8 | 8 | { |
9 | - /** |
|
10 | - * PHP tokens of the code to be parsed. |
|
11 | - * |
|
12 | - * @var array |
|
13 | - */ |
|
14 | - protected $tokens; |
|
15 | - |
|
16 | - /** |
|
17 | - * If not false, comments will be extracted. |
|
18 | - * |
|
19 | - * @var string|false|array |
|
20 | - */ |
|
21 | - protected $extractComments = false; |
|
22 | - |
|
23 | - /** |
|
24 | - * Enable extracting comments that start with a tag (if $tag is empty all the comments will be extracted). |
|
25 | - * |
|
26 | - * @param mixed $tag |
|
27 | - */ |
|
28 | - public function enableCommentsExtraction($tag = '') |
|
29 | - { |
|
30 | - $this->extractComments = $tag; |
|
31 | - } |
|
32 | - |
|
33 | - /** |
|
34 | - * Disable comments extraction. |
|
35 | - */ |
|
36 | - public function disableCommentsExtraction() |
|
37 | - { |
|
38 | - $this->extractComments = false; |
|
39 | - } |
|
40 | - |
|
41 | - /** |
|
42 | - * Constructor. |
|
43 | - * |
|
44 | - * @param string $code The php code to scan |
|
45 | - */ |
|
46 | - public function __construct($code) |
|
47 | - { |
|
48 | - $this->tokens = array_values( |
|
49 | - array_filter( |
|
50 | - token_get_all($code), |
|
51 | - function ($token) { |
|
52 | - return !is_array($token) || $token[0] !== T_WHITESPACE; |
|
53 | - } |
|
54 | - ) |
|
55 | - ); |
|
56 | - } |
|
57 | - |
|
58 | - /** |
|
59 | - * {@inheritdoc} |
|
60 | - */ |
|
61 | - public function getFunctions(array $constants = []) |
|
62 | - { |
|
63 | - $count = count($this->tokens); |
|
64 | - /* @var ParsedFunction[] $bufferFunctions */ |
|
65 | - $bufferFunctions = []; |
|
66 | - /* @var ParsedComment[] $bufferComments */ |
|
67 | - $bufferComments = []; |
|
68 | - /* @var array $functions */ |
|
69 | - $functions = []; |
|
70 | - |
|
71 | - for ($k = 0; $k < $count; ++$k) { |
|
72 | - $value = $this->tokens[$k]; |
|
73 | - |
|
74 | - if (is_string($value)) { |
|
75 | - if (isset($bufferFunctions[0])) { |
|
76 | - switch ($value) { |
|
77 | - case ',': |
|
78 | - $bufferFunctions[0]->nextArgument(); |
|
79 | - break; |
|
80 | - case ')': |
|
81 | - $functions[] = array_shift($bufferFunctions)->close(); |
|
82 | - break; |
|
83 | - case '.': |
|
84 | - break; |
|
85 | - default: |
|
86 | - $bufferFunctions[0]->stopArgument(); |
|
87 | - break; |
|
88 | - } |
|
89 | - } |
|
90 | - continue; |
|
91 | - } |
|
92 | - |
|
93 | - switch ($value[0]) { |
|
94 | - case T_CONSTANT_ENCAPSED_STRING: |
|
95 | - //add an argument to the current function |
|
96 | - if (isset($bufferFunctions[0])) { |
|
97 | - $bufferFunctions[0]->addArgumentChunk(PhpCode::convertString($value[1])); |
|
98 | - } |
|
99 | - break; |
|
100 | - |
|
101 | - case T_STRING: |
|
102 | - if (isset($bufferFunctions[0])) { |
|
103 | - if (isset($constants[$value[1]])) { |
|
104 | - $bufferFunctions[0]->addArgumentChunk($constants[$value[1]]); |
|
105 | - break; |
|
106 | - } |
|
107 | - |
|
108 | - if (strtolower($value[1]) === 'null') { |
|
109 | - $bufferFunctions[0]->addArgumentChunk(null); |
|
110 | - break; |
|
111 | - } |
|
112 | - |
|
113 | - $bufferFunctions[0]->stopArgument(); |
|
114 | - } |
|
115 | - |
|
116 | - //new function found |
|
117 | - for ($j = $k + 1; $j < $count; ++$j) { |
|
118 | - $nextToken = $this->tokens[$j]; |
|
119 | - |
|
120 | - if (is_array($nextToken) && $nextToken[0] === T_COMMENT) { |
|
121 | - continue; |
|
122 | - } |
|
123 | - |
|
124 | - if ($nextToken === '(') { |
|
125 | - $newFunction = new ParsedFunction($value[1], $value[2]); |
|
126 | - |
|
127 | - // add comment that was on the line before. |
|
128 | - if (isset($bufferComments[0])) { |
|
129 | - $comment = $bufferComments[0]; |
|
130 | - |
|
131 | - if ($comment->isRelatedWith($newFunction)) { |
|
132 | - $newFunction->addComment($comment); |
|
133 | - } |
|
134 | - } |
|
135 | - |
|
136 | - array_unshift($bufferFunctions, $newFunction); |
|
137 | - $k = $j; |
|
138 | - } |
|
139 | - break; |
|
140 | - } |
|
141 | - break; |
|
142 | - |
|
143 | - case T_COMMENT: |
|
144 | - $comment = $this->parsePhpComment($value[1], $value[2]); |
|
145 | - |
|
146 | - if ($comment) { |
|
147 | - array_unshift($bufferComments, $comment); |
|
148 | - |
|
149 | - // The comment is inside the function call. |
|
150 | - if (isset($bufferFunctions[0])) { |
|
151 | - $bufferFunctions[0]->addComment($comment); |
|
152 | - } |
|
153 | - } |
|
154 | - break; |
|
155 | - |
|
156 | - default: |
|
157 | - if (isset($bufferFunctions[0])) { |
|
158 | - $bufferFunctions[0]->stopArgument(); |
|
159 | - } |
|
160 | - break; |
|
161 | - } |
|
162 | - } |
|
163 | - |
|
164 | - return $functions; |
|
165 | - } |
|
166 | - |
|
167 | - /** |
|
168 | - * Extract the actual text from a PHP comment. |
|
169 | - * |
|
170 | - * If set, only returns comments that match the prefix(es). |
|
171 | - * |
|
172 | - * @param string $value The PHP comment. |
|
173 | - * @param int $line Line number. |
|
174 | - * |
|
175 | - * @return null|ParsedComment Comment or null if comment extraction is disabled or if there is a prefix mismatch. |
|
176 | - */ |
|
177 | - protected function parsePhpComment($value, $line) |
|
178 | - { |
|
179 | - if ($this->extractComments === false) { |
|
180 | - return null; |
|
181 | - } |
|
182 | - |
|
183 | - //this returns a comment or null |
|
184 | - $comment = ParsedComment::create($value, $line); |
|
185 | - |
|
186 | - $prefixes = array_filter((array) $this->extractComments); |
|
187 | - |
|
188 | - if ($comment && $comment->checkPrefixes($prefixes)) { |
|
189 | - return $comment; |
|
190 | - } |
|
191 | - |
|
192 | - return null; |
|
193 | - } |
|
9 | + /** |
|
10 | + * PHP tokens of the code to be parsed. |
|
11 | + * |
|
12 | + * @var array |
|
13 | + */ |
|
14 | + protected $tokens; |
|
15 | + |
|
16 | + /** |
|
17 | + * If not false, comments will be extracted. |
|
18 | + * |
|
19 | + * @var string|false|array |
|
20 | + */ |
|
21 | + protected $extractComments = false; |
|
22 | + |
|
23 | + /** |
|
24 | + * Enable extracting comments that start with a tag (if $tag is empty all the comments will be extracted). |
|
25 | + * |
|
26 | + * @param mixed $tag |
|
27 | + */ |
|
28 | + public function enableCommentsExtraction($tag = '') |
|
29 | + { |
|
30 | + $this->extractComments = $tag; |
|
31 | + } |
|
32 | + |
|
33 | + /** |
|
34 | + * Disable comments extraction. |
|
35 | + */ |
|
36 | + public function disableCommentsExtraction() |
|
37 | + { |
|
38 | + $this->extractComments = false; |
|
39 | + } |
|
40 | + |
|
41 | + /** |
|
42 | + * Constructor. |
|
43 | + * |
|
44 | + * @param string $code The php code to scan |
|
45 | + */ |
|
46 | + public function __construct($code) |
|
47 | + { |
|
48 | + $this->tokens = array_values( |
|
49 | + array_filter( |
|
50 | + token_get_all($code), |
|
51 | + function ($token) { |
|
52 | + return !is_array($token) || $token[0] !== T_WHITESPACE; |
|
53 | + } |
|
54 | + ) |
|
55 | + ); |
|
56 | + } |
|
57 | + |
|
58 | + /** |
|
59 | + * {@inheritdoc} |
|
60 | + */ |
|
61 | + public function getFunctions(array $constants = []) |
|
62 | + { |
|
63 | + $count = count($this->tokens); |
|
64 | + /* @var ParsedFunction[] $bufferFunctions */ |
|
65 | + $bufferFunctions = []; |
|
66 | + /* @var ParsedComment[] $bufferComments */ |
|
67 | + $bufferComments = []; |
|
68 | + /* @var array $functions */ |
|
69 | + $functions = []; |
|
70 | + |
|
71 | + for ($k = 0; $k < $count; ++$k) { |
|
72 | + $value = $this->tokens[$k]; |
|
73 | + |
|
74 | + if (is_string($value)) { |
|
75 | + if (isset($bufferFunctions[0])) { |
|
76 | + switch ($value) { |
|
77 | + case ',': |
|
78 | + $bufferFunctions[0]->nextArgument(); |
|
79 | + break; |
|
80 | + case ')': |
|
81 | + $functions[] = array_shift($bufferFunctions)->close(); |
|
82 | + break; |
|
83 | + case '.': |
|
84 | + break; |
|
85 | + default: |
|
86 | + $bufferFunctions[0]->stopArgument(); |
|
87 | + break; |
|
88 | + } |
|
89 | + } |
|
90 | + continue; |
|
91 | + } |
|
92 | + |
|
93 | + switch ($value[0]) { |
|
94 | + case T_CONSTANT_ENCAPSED_STRING: |
|
95 | + //add an argument to the current function |
|
96 | + if (isset($bufferFunctions[0])) { |
|
97 | + $bufferFunctions[0]->addArgumentChunk(PhpCode::convertString($value[1])); |
|
98 | + } |
|
99 | + break; |
|
100 | + |
|
101 | + case T_STRING: |
|
102 | + if (isset($bufferFunctions[0])) { |
|
103 | + if (isset($constants[$value[1]])) { |
|
104 | + $bufferFunctions[0]->addArgumentChunk($constants[$value[1]]); |
|
105 | + break; |
|
106 | + } |
|
107 | + |
|
108 | + if (strtolower($value[1]) === 'null') { |
|
109 | + $bufferFunctions[0]->addArgumentChunk(null); |
|
110 | + break; |
|
111 | + } |
|
112 | + |
|
113 | + $bufferFunctions[0]->stopArgument(); |
|
114 | + } |
|
115 | + |
|
116 | + //new function found |
|
117 | + for ($j = $k + 1; $j < $count; ++$j) { |
|
118 | + $nextToken = $this->tokens[$j]; |
|
119 | + |
|
120 | + if (is_array($nextToken) && $nextToken[0] === T_COMMENT) { |
|
121 | + continue; |
|
122 | + } |
|
123 | + |
|
124 | + if ($nextToken === '(') { |
|
125 | + $newFunction = new ParsedFunction($value[1], $value[2]); |
|
126 | + |
|
127 | + // add comment that was on the line before. |
|
128 | + if (isset($bufferComments[0])) { |
|
129 | + $comment = $bufferComments[0]; |
|
130 | + |
|
131 | + if ($comment->isRelatedWith($newFunction)) { |
|
132 | + $newFunction->addComment($comment); |
|
133 | + } |
|
134 | + } |
|
135 | + |
|
136 | + array_unshift($bufferFunctions, $newFunction); |
|
137 | + $k = $j; |
|
138 | + } |
|
139 | + break; |
|
140 | + } |
|
141 | + break; |
|
142 | + |
|
143 | + case T_COMMENT: |
|
144 | + $comment = $this->parsePhpComment($value[1], $value[2]); |
|
145 | + |
|
146 | + if ($comment) { |
|
147 | + array_unshift($bufferComments, $comment); |
|
148 | + |
|
149 | + // The comment is inside the function call. |
|
150 | + if (isset($bufferFunctions[0])) { |
|
151 | + $bufferFunctions[0]->addComment($comment); |
|
152 | + } |
|
153 | + } |
|
154 | + break; |
|
155 | + |
|
156 | + default: |
|
157 | + if (isset($bufferFunctions[0])) { |
|
158 | + $bufferFunctions[0]->stopArgument(); |
|
159 | + } |
|
160 | + break; |
|
161 | + } |
|
162 | + } |
|
163 | + |
|
164 | + return $functions; |
|
165 | + } |
|
166 | + |
|
167 | + /** |
|
168 | + * Extract the actual text from a PHP comment. |
|
169 | + * |
|
170 | + * If set, only returns comments that match the prefix(es). |
|
171 | + * |
|
172 | + * @param string $value The PHP comment. |
|
173 | + * @param int $line Line number. |
|
174 | + * |
|
175 | + * @return null|ParsedComment Comment or null if comment extraction is disabled or if there is a prefix mismatch. |
|
176 | + */ |
|
177 | + protected function parsePhpComment($value, $line) |
|
178 | + { |
|
179 | + if ($this->extractComments === false) { |
|
180 | + return null; |
|
181 | + } |
|
182 | + |
|
183 | + //this returns a comment or null |
|
184 | + $comment = ParsedComment::create($value, $line); |
|
185 | + |
|
186 | + $prefixes = array_filter((array) $this->extractComments); |
|
187 | + |
|
188 | + if ($comment && $comment->checkPrefixes($prefixes)) { |
|
189 | + return $comment; |
|
190 | + } |
|
191 | + |
|
192 | + return null; |
|
193 | + } |
|
194 | 194 | } |
@@ -9,59 +9,59 @@ |
||
9 | 9 | */ |
10 | 10 | trait HeadersExtractorTrait |
11 | 11 | { |
12 | - /** |
|
13 | - * Add the headers found to the translations instance. |
|
14 | - * |
|
15 | - * @param string $headers |
|
16 | - * @param Translations $translations |
|
17 | - * |
|
18 | - * @return array |
|
19 | - */ |
|
20 | - protected static function extractHeaders($headers, Translations $translations) |
|
21 | - { |
|
22 | - $headers = explode("\n", $headers); |
|
23 | - $currentHeader = null; |
|
12 | + /** |
|
13 | + * Add the headers found to the translations instance. |
|
14 | + * |
|
15 | + * @param string $headers |
|
16 | + * @param Translations $translations |
|
17 | + * |
|
18 | + * @return array |
|
19 | + */ |
|
20 | + protected static function extractHeaders($headers, Translations $translations) |
|
21 | + { |
|
22 | + $headers = explode("\n", $headers); |
|
23 | + $currentHeader = null; |
|
24 | 24 | |
25 | - foreach ($headers as $line) { |
|
26 | - $line = static::convertString($line); |
|
25 | + foreach ($headers as $line) { |
|
26 | + $line = static::convertString($line); |
|
27 | 27 | |
28 | - if ($line === '') { |
|
29 | - continue; |
|
30 | - } |
|
28 | + if ($line === '') { |
|
29 | + continue; |
|
30 | + } |
|
31 | 31 | |
32 | - if (static::isHeaderDefinition($line)) { |
|
33 | - $header = array_map('trim', explode(':', $line, 2)); |
|
34 | - $currentHeader = $header[0]; |
|
35 | - $translations->setHeader($currentHeader, $header[1]); |
|
36 | - } else { |
|
37 | - $entry = $translations->getHeader($currentHeader); |
|
38 | - $translations->setHeader($currentHeader, $entry.$line); |
|
39 | - } |
|
40 | - } |
|
41 | - } |
|
32 | + if (static::isHeaderDefinition($line)) { |
|
33 | + $header = array_map('trim', explode(':', $line, 2)); |
|
34 | + $currentHeader = $header[0]; |
|
35 | + $translations->setHeader($currentHeader, $header[1]); |
|
36 | + } else { |
|
37 | + $entry = $translations->getHeader($currentHeader); |
|
38 | + $translations->setHeader($currentHeader, $entry.$line); |
|
39 | + } |
|
40 | + } |
|
41 | + } |
|
42 | 42 | |
43 | - /** |
|
44 | - * Checks if it is a header definition line. Useful for distguishing between header definitions |
|
45 | - * and possible continuations of a header entry. |
|
46 | - * |
|
47 | - * @param string $line Line to parse |
|
48 | - * |
|
49 | - * @return bool |
|
50 | - */ |
|
51 | - protected static function isHeaderDefinition($line) |
|
52 | - { |
|
53 | - return (bool) preg_match('/^[\w-]+:/', $line); |
|
54 | - } |
|
43 | + /** |
|
44 | + * Checks if it is a header definition line. Useful for distguishing between header definitions |
|
45 | + * and possible continuations of a header entry. |
|
46 | + * |
|
47 | + * @param string $line Line to parse |
|
48 | + * |
|
49 | + * @return bool |
|
50 | + */ |
|
51 | + protected static function isHeaderDefinition($line) |
|
52 | + { |
|
53 | + return (bool) preg_match('/^[\w-]+:/', $line); |
|
54 | + } |
|
55 | 55 | |
56 | - /** |
|
57 | - * Normalize a string. |
|
58 | - * |
|
59 | - * @param string $value |
|
60 | - * |
|
61 | - * @return string |
|
62 | - */ |
|
63 | - public static function convertString($value) |
|
64 | - { |
|
65 | - return $value; |
|
66 | - } |
|
56 | + /** |
|
57 | + * Normalize a string. |
|
58 | + * |
|
59 | + * @param string $value |
|
60 | + * |
|
61 | + * @return string |
|
62 | + */ |
|
63 | + public static function convertString($value) |
|
64 | + { |
|
65 | + return $value; |
|
66 | + } |
|
67 | 67 | } |
@@ -7,134 +7,134 @@ |
||
7 | 7 | */ |
8 | 8 | class ParsedComment |
9 | 9 | { |
10 | - /** |
|
11 | - * The comment itself. |
|
12 | - * |
|
13 | - * @var string |
|
14 | - */ |
|
15 | - protected $comment; |
|
16 | - |
|
17 | - /** |
|
18 | - * The line where the comment starts. |
|
19 | - * |
|
20 | - * @var int |
|
21 | - */ |
|
22 | - protected $firstLine; |
|
23 | - |
|
24 | - /** |
|
25 | - * The line where the comment ends. |
|
26 | - * |
|
27 | - * @var int |
|
28 | - */ |
|
29 | - protected $lastLine; |
|
30 | - |
|
31 | - /** |
|
32 | - * Initializes the instance. |
|
33 | - * |
|
34 | - * @param string $comment The comment itself. |
|
35 | - * @param int $firstLine The line where the comment starts. |
|
36 | - * @param int $lastLine The line where the comment ends. |
|
37 | - */ |
|
38 | - public function __construct($comment, $firstLine, $lastLine) |
|
39 | - { |
|
40 | - $this->comment = $comment; |
|
41 | - $this->firstLine = $firstLine; |
|
42 | - $this->lastLine = $lastLine; |
|
43 | - } |
|
44 | - |
|
45 | - /** |
|
46 | - * Create new object from raw comment data. |
|
47 | - * |
|
48 | - * @param string $value The PHP comment string. |
|
49 | - * @param int $line The line where the comment starts. |
|
50 | - * |
|
51 | - * @return static The parsed comment. |
|
52 | - */ |
|
53 | - public static function create($value, $line) |
|
54 | - { |
|
55 | - $lastLine = $line + substr_count($value, "\n"); |
|
56 | - |
|
57 | - $lines = array_map(function ($line) { |
|
58 | - if ('' === trim($line)) { |
|
59 | - return null; |
|
60 | - } |
|
61 | - |
|
62 | - $line = ltrim($line, "#*/ \t"); |
|
63 | - $line = rtrim($line, "#*/ \t"); |
|
64 | - |
|
65 | - return trim($line); |
|
66 | - }, explode("\n", $value)); |
|
67 | - |
|
68 | - // Remove empty lines. |
|
69 | - $lines = array_filter($lines); |
|
70 | - $value = implode(' ', $lines); |
|
71 | - |
|
72 | - return new static($value, $line, $lastLine); |
|
73 | - } |
|
74 | - |
|
75 | - /** |
|
76 | - * Return the line where the comment starts. |
|
77 | - * |
|
78 | - * @return int Line number. |
|
79 | - */ |
|
80 | - public function getFirstLine() |
|
81 | - { |
|
82 | - return $this->firstLine; |
|
83 | - } |
|
84 | - |
|
85 | - /** |
|
86 | - * Return the line where the comment ends. |
|
87 | - * |
|
88 | - * @return int Line number. |
|
89 | - */ |
|
90 | - public function getLastLine() |
|
91 | - { |
|
92 | - return $this->lastLine; |
|
93 | - } |
|
94 | - |
|
95 | - /** |
|
96 | - * Return the actual comment string. |
|
97 | - * |
|
98 | - * @return string The comment. |
|
99 | - */ |
|
100 | - public function getComment() |
|
101 | - { |
|
102 | - return $this->comment; |
|
103 | - } |
|
104 | - |
|
105 | - /** |
|
106 | - * Whether this comment is related with a given function. |
|
107 | - * |
|
108 | - * @param ParsedFunction $function The function to check. |
|
109 | - * @return bool Whether the comment is related or not. |
|
110 | - */ |
|
111 | - public function isRelatedWith(ParsedFunction $function) |
|
112 | - { |
|
113 | - return $this->getLastLine() === $function->getLine() || $this->getLastLine() === $function->getLine() - 1; |
|
114 | - } |
|
115 | - |
|
116 | - /** |
|
117 | - * Whether the comment matches the required prefixes. |
|
118 | - * |
|
119 | - * @param array $prefixes An array of prefixes to check. |
|
120 | - * @return bool Whether the comment matches the prefixes or not. |
|
121 | - */ |
|
122 | - public function checkPrefixes(array $prefixes) |
|
123 | - { |
|
124 | - if ('' === $this->comment) { |
|
125 | - return false; |
|
126 | - } |
|
127 | - |
|
128 | - if (empty($prefixes)) { |
|
129 | - return true; |
|
130 | - } |
|
131 | - |
|
132 | - foreach ($prefixes as $prefix) { |
|
133 | - if (strpos($this->comment, $prefix) === 0) { |
|
134 | - return true; |
|
135 | - } |
|
136 | - } |
|
137 | - |
|
138 | - return false; |
|
139 | - } |
|
10 | + /** |
|
11 | + * The comment itself. |
|
12 | + * |
|
13 | + * @var string |
|
14 | + */ |
|
15 | + protected $comment; |
|
16 | + |
|
17 | + /** |
|
18 | + * The line where the comment starts. |
|
19 | + * |
|
20 | + * @var int |
|
21 | + */ |
|
22 | + protected $firstLine; |
|
23 | + |
|
24 | + /** |
|
25 | + * The line where the comment ends. |
|
26 | + * |
|
27 | + * @var int |
|
28 | + */ |
|
29 | + protected $lastLine; |
|
30 | + |
|
31 | + /** |
|
32 | + * Initializes the instance. |
|
33 | + * |
|
34 | + * @param string $comment The comment itself. |
|
35 | + * @param int $firstLine The line where the comment starts. |
|
36 | + * @param int $lastLine The line where the comment ends. |
|
37 | + */ |
|
38 | + public function __construct($comment, $firstLine, $lastLine) |
|
39 | + { |
|
40 | + $this->comment = $comment; |
|
41 | + $this->firstLine = $firstLine; |
|
42 | + $this->lastLine = $lastLine; |
|
43 | + } |
|
44 | + |
|
45 | + /** |
|
46 | + * Create new object from raw comment data. |
|
47 | + * |
|
48 | + * @param string $value The PHP comment string. |
|
49 | + * @param int $line The line where the comment starts. |
|
50 | + * |
|
51 | + * @return static The parsed comment. |
|
52 | + */ |
|
53 | + public static function create($value, $line) |
|
54 | + { |
|
55 | + $lastLine = $line + substr_count($value, "\n"); |
|
56 | + |
|
57 | + $lines = array_map(function ($line) { |
|
58 | + if ('' === trim($line)) { |
|
59 | + return null; |
|
60 | + } |
|
61 | + |
|
62 | + $line = ltrim($line, "#*/ \t"); |
|
63 | + $line = rtrim($line, "#*/ \t"); |
|
64 | + |
|
65 | + return trim($line); |
|
66 | + }, explode("\n", $value)); |
|
67 | + |
|
68 | + // Remove empty lines. |
|
69 | + $lines = array_filter($lines); |
|
70 | + $value = implode(' ', $lines); |
|
71 | + |
|
72 | + return new static($value, $line, $lastLine); |
|
73 | + } |
|
74 | + |
|
75 | + /** |
|
76 | + * Return the line where the comment starts. |
|
77 | + * |
|
78 | + * @return int Line number. |
|
79 | + */ |
|
80 | + public function getFirstLine() |
|
81 | + { |
|
82 | + return $this->firstLine; |
|
83 | + } |
|
84 | + |
|
85 | + /** |
|
86 | + * Return the line where the comment ends. |
|
87 | + * |
|
88 | + * @return int Line number. |
|
89 | + */ |
|
90 | + public function getLastLine() |
|
91 | + { |
|
92 | + return $this->lastLine; |
|
93 | + } |
|
94 | + |
|
95 | + /** |
|
96 | + * Return the actual comment string. |
|
97 | + * |
|
98 | + * @return string The comment. |
|
99 | + */ |
|
100 | + public function getComment() |
|
101 | + { |
|
102 | + return $this->comment; |
|
103 | + } |
|
104 | + |
|
105 | + /** |
|
106 | + * Whether this comment is related with a given function. |
|
107 | + * |
|
108 | + * @param ParsedFunction $function The function to check. |
|
109 | + * @return bool Whether the comment is related or not. |
|
110 | + */ |
|
111 | + public function isRelatedWith(ParsedFunction $function) |
|
112 | + { |
|
113 | + return $this->getLastLine() === $function->getLine() || $this->getLastLine() === $function->getLine() - 1; |
|
114 | + } |
|
115 | + |
|
116 | + /** |
|
117 | + * Whether the comment matches the required prefixes. |
|
118 | + * |
|
119 | + * @param array $prefixes An array of prefixes to check. |
|
120 | + * @return bool Whether the comment matches the prefixes or not. |
|
121 | + */ |
|
122 | + public function checkPrefixes(array $prefixes) |
|
123 | + { |
|
124 | + if ('' === $this->comment) { |
|
125 | + return false; |
|
126 | + } |
|
127 | + |
|
128 | + if (empty($prefixes)) { |
|
129 | + return true; |
|
130 | + } |
|
131 | + |
|
132 | + foreach ($prefixes as $prefix) { |
|
133 | + if (strpos($this->comment, $prefix) === 0) { |
|
134 | + return true; |
|
135 | + } |
|
136 | + } |
|
137 | + |
|
138 | + return false; |
|
139 | + } |
|
140 | 140 | } |
@@ -7,175 +7,175 @@ |
||
7 | 7 | |
8 | 8 | abstract class FunctionsScanner |
9 | 9 | { |
10 | - /** |
|
11 | - * Scan and returns the functions and the arguments. |
|
12 | - * |
|
13 | - * @param array $constants Constants used in the code to replace |
|
14 | - * |
|
15 | - * @return array |
|
16 | - */ |
|
17 | - abstract public function getFunctions(array $constants = []); |
|
18 | - |
|
19 | - /** |
|
20 | - * Search for specific functions and create translations. |
|
21 | - * |
|
22 | - * You can pass multiple translation with different domains and value found will be sorted respectively. |
|
23 | - * |
|
24 | - * @param Translations|Translations[] $translations Multiple domain translations instances where to save the values |
|
25 | - * @param array $options The extractor options |
|
26 | - * @throws Exception |
|
27 | - */ |
|
28 | - public function saveGettextFunctions($translations, array $options) |
|
29 | - { |
|
30 | - $translations = is_array($translations) ? $translations : [$translations]; |
|
31 | - |
|
32 | - /** @var Translations[] $translationByDomain [domain => translations, ..] */ |
|
33 | - $translationByDomain = array_reduce($translations, function ($carry, Translations $translations) { |
|
34 | - $carry[$translations->getDomain()] = $translations; |
|
35 | - return $carry; |
|
36 | - }, []); |
|
37 | - |
|
38 | - $functions = $options['functions']; |
|
39 | - $file = $options['file']; |
|
40 | - |
|
41 | - /** |
|
42 | - * List of source code comments already associated with a function. |
|
43 | - * |
|
44 | - * Prevents associating the same comment to multiple functions. |
|
45 | - * |
|
46 | - * @var ParsedComment[] $commentsCache |
|
47 | - */ |
|
48 | - $commentsCache = []; |
|
49 | - |
|
50 | - foreach ($this->getFunctions($options['constants']) as $function) { |
|
51 | - list($name, $line, $args) = $function; |
|
52 | - |
|
53 | - if (isset($options['lineOffset'])) { |
|
54 | - $line += $options['lineOffset']; |
|
55 | - } |
|
56 | - |
|
57 | - if (!isset($functions[$name])) { |
|
58 | - continue; |
|
59 | - } |
|
60 | - |
|
61 | - $deconstructed = $this->deconstructArgs($functions[$name], $args); |
|
62 | - |
|
63 | - if (!$deconstructed) { |
|
64 | - continue; |
|
65 | - } |
|
66 | - |
|
67 | - list($domain, $context, $original, $plural) = $deconstructed; |
|
68 | - |
|
69 | - if ((string)$original === '') { |
|
70 | - continue; |
|
71 | - } |
|
72 | - |
|
73 | - $isDefaultDomain = $domain === null; |
|
74 | - |
|
75 | - $domainTranslations = isset($translationByDomain[$domain]) ? $translationByDomain[$domain] : false; |
|
76 | - |
|
77 | - if (!empty($options['domainOnly']) && $isDefaultDomain) { |
|
78 | - // If we want to find translations for a specific domain, skip default domain messages |
|
79 | - continue; |
|
80 | - } |
|
81 | - |
|
82 | - if (!$domainTranslations) { |
|
83 | - continue; |
|
84 | - } |
|
85 | - |
|
86 | - $translation = $domainTranslations->insert($context, $original, $plural); |
|
87 | - $translation->addReference($file, $line); |
|
88 | - |
|
89 | - if (isset($function[3])) { |
|
90 | - /* @var ParsedComment $extractedComment */ |
|
91 | - foreach ($function[3] as $extractedComment) { |
|
92 | - if (in_array($extractedComment, $commentsCache, true)) { |
|
93 | - continue; |
|
94 | - } |
|
95 | - $translation->addExtractedComment($extractedComment->getComment()); |
|
96 | - $commentsCache[] = $extractedComment; |
|
97 | - } |
|
98 | - } |
|
99 | - } |
|
100 | - } |
|
101 | - |
|
102 | - /** |
|
103 | - * Deconstruct arguments to translation values |
|
104 | - * |
|
105 | - * @param $function |
|
106 | - * @param $args |
|
107 | - * @return array|null |
|
108 | - * @throws Exception |
|
109 | - */ |
|
110 | - protected function deconstructArgs($function, $args) |
|
111 | - { |
|
112 | - $domain = null; |
|
113 | - $context = null; |
|
114 | - $original = null; |
|
115 | - $plural = null; |
|
116 | - |
|
117 | - switch ($function) { |
|
118 | - case 'noop': |
|
119 | - case 'gettext': |
|
120 | - if (!isset($args[0])) { |
|
121 | - return null; |
|
122 | - } |
|
123 | - |
|
124 | - $original = $args[0]; |
|
125 | - break; |
|
126 | - case 'ngettext': |
|
127 | - if (!isset($args[1])) { |
|
128 | - return null; |
|
129 | - } |
|
130 | - |
|
131 | - list($original, $plural) = $args; |
|
132 | - break; |
|
133 | - case 'pgettext': |
|
134 | - if (!isset($args[1])) { |
|
135 | - return null; |
|
136 | - } |
|
137 | - |
|
138 | - list($context, $original) = $args; |
|
139 | - break; |
|
140 | - case 'dgettext': |
|
141 | - if (!isset($args[1])) { |
|
142 | - return null; |
|
143 | - } |
|
144 | - |
|
145 | - list($domain, $original) = $args; |
|
146 | - break; |
|
147 | - case 'dpgettext': |
|
148 | - if (!isset($args[2])) { |
|
149 | - return null; |
|
150 | - } |
|
151 | - |
|
152 | - list($domain, $context, $original) = $args; |
|
153 | - break; |
|
154 | - case 'npgettext': |
|
155 | - if (!isset($args[2])) { |
|
156 | - return null; |
|
157 | - } |
|
158 | - |
|
159 | - list($context, $original, $plural) = $args; |
|
160 | - break; |
|
161 | - case 'dnpgettext': |
|
162 | - if (!isset($args[3])) { |
|
163 | - return null; |
|
164 | - } |
|
165 | - |
|
166 | - list($domain, $context, $original, $plural) = $args; |
|
167 | - break; |
|
168 | - case 'dngettext': |
|
169 | - if (!isset($args[2])) { |
|
170 | - return null; |
|
171 | - } |
|
172 | - |
|
173 | - list($domain, $original, $plural) = $args; |
|
174 | - break; |
|
175 | - default: |
|
176 | - throw new Exception(sprintf('Not valid function %s', $function)); |
|
177 | - } |
|
178 | - |
|
179 | - return [$domain, $context, $original, $plural]; |
|
180 | - } |
|
10 | + /** |
|
11 | + * Scan and returns the functions and the arguments. |
|
12 | + * |
|
13 | + * @param array $constants Constants used in the code to replace |
|
14 | + * |
|
15 | + * @return array |
|
16 | + */ |
|
17 | + abstract public function getFunctions(array $constants = []); |
|
18 | + |
|
19 | + /** |
|
20 | + * Search for specific functions and create translations. |
|
21 | + * |
|
22 | + * You can pass multiple translation with different domains and value found will be sorted respectively. |
|
23 | + * |
|
24 | + * @param Translations|Translations[] $translations Multiple domain translations instances where to save the values |
|
25 | + * @param array $options The extractor options |
|
26 | + * @throws Exception |
|
27 | + */ |
|
28 | + public function saveGettextFunctions($translations, array $options) |
|
29 | + { |
|
30 | + $translations = is_array($translations) ? $translations : [$translations]; |
|
31 | + |
|
32 | + /** @var Translations[] $translationByDomain [domain => translations, ..] */ |
|
33 | + $translationByDomain = array_reduce($translations, function ($carry, Translations $translations) { |
|
34 | + $carry[$translations->getDomain()] = $translations; |
|
35 | + return $carry; |
|
36 | + }, []); |
|
37 | + |
|
38 | + $functions = $options['functions']; |
|
39 | + $file = $options['file']; |
|
40 | + |
|
41 | + /** |
|
42 | + * List of source code comments already associated with a function. |
|
43 | + * |
|
44 | + * Prevents associating the same comment to multiple functions. |
|
45 | + * |
|
46 | + * @var ParsedComment[] $commentsCache |
|
47 | + */ |
|
48 | + $commentsCache = []; |
|
49 | + |
|
50 | + foreach ($this->getFunctions($options['constants']) as $function) { |
|
51 | + list($name, $line, $args) = $function; |
|
52 | + |
|
53 | + if (isset($options['lineOffset'])) { |
|
54 | + $line += $options['lineOffset']; |
|
55 | + } |
|
56 | + |
|
57 | + if (!isset($functions[$name])) { |
|
58 | + continue; |
|
59 | + } |
|
60 | + |
|
61 | + $deconstructed = $this->deconstructArgs($functions[$name], $args); |
|
62 | + |
|
63 | + if (!$deconstructed) { |
|
64 | + continue; |
|
65 | + } |
|
66 | + |
|
67 | + list($domain, $context, $original, $plural) = $deconstructed; |
|
68 | + |
|
69 | + if ((string)$original === '') { |
|
70 | + continue; |
|
71 | + } |
|
72 | + |
|
73 | + $isDefaultDomain = $domain === null; |
|
74 | + |
|
75 | + $domainTranslations = isset($translationByDomain[$domain]) ? $translationByDomain[$domain] : false; |
|
76 | + |
|
77 | + if (!empty($options['domainOnly']) && $isDefaultDomain) { |
|
78 | + // If we want to find translations for a specific domain, skip default domain messages |
|
79 | + continue; |
|
80 | + } |
|
81 | + |
|
82 | + if (!$domainTranslations) { |
|
83 | + continue; |
|
84 | + } |
|
85 | + |
|
86 | + $translation = $domainTranslations->insert($context, $original, $plural); |
|
87 | + $translation->addReference($file, $line); |
|
88 | + |
|
89 | + if (isset($function[3])) { |
|
90 | + /* @var ParsedComment $extractedComment */ |
|
91 | + foreach ($function[3] as $extractedComment) { |
|
92 | + if (in_array($extractedComment, $commentsCache, true)) { |
|
93 | + continue; |
|
94 | + } |
|
95 | + $translation->addExtractedComment($extractedComment->getComment()); |
|
96 | + $commentsCache[] = $extractedComment; |
|
97 | + } |
|
98 | + } |
|
99 | + } |
|
100 | + } |
|
101 | + |
|
102 | + /** |
|
103 | + * Deconstruct arguments to translation values |
|
104 | + * |
|
105 | + * @param $function |
|
106 | + * @param $args |
|
107 | + * @return array|null |
|
108 | + * @throws Exception |
|
109 | + */ |
|
110 | + protected function deconstructArgs($function, $args) |
|
111 | + { |
|
112 | + $domain = null; |
|
113 | + $context = null; |
|
114 | + $original = null; |
|
115 | + $plural = null; |
|
116 | + |
|
117 | + switch ($function) { |
|
118 | + case 'noop': |
|
119 | + case 'gettext': |
|
120 | + if (!isset($args[0])) { |
|
121 | + return null; |
|
122 | + } |
|
123 | + |
|
124 | + $original = $args[0]; |
|
125 | + break; |
|
126 | + case 'ngettext': |
|
127 | + if (!isset($args[1])) { |
|
128 | + return null; |
|
129 | + } |
|
130 | + |
|
131 | + list($original, $plural) = $args; |
|
132 | + break; |
|
133 | + case 'pgettext': |
|
134 | + if (!isset($args[1])) { |
|
135 | + return null; |
|
136 | + } |
|
137 | + |
|
138 | + list($context, $original) = $args; |
|
139 | + break; |
|
140 | + case 'dgettext': |
|
141 | + if (!isset($args[1])) { |
|
142 | + return null; |
|
143 | + } |
|
144 | + |
|
145 | + list($domain, $original) = $args; |
|
146 | + break; |
|
147 | + case 'dpgettext': |
|
148 | + if (!isset($args[2])) { |
|
149 | + return null; |
|
150 | + } |
|
151 | + |
|
152 | + list($domain, $context, $original) = $args; |
|
153 | + break; |
|
154 | + case 'npgettext': |
|
155 | + if (!isset($args[2])) { |
|
156 | + return null; |
|
157 | + } |
|
158 | + |
|
159 | + list($context, $original, $plural) = $args; |
|
160 | + break; |
|
161 | + case 'dnpgettext': |
|
162 | + if (!isset($args[3])) { |
|
163 | + return null; |
|
164 | + } |
|
165 | + |
|
166 | + list($domain, $context, $original, $plural) = $args; |
|
167 | + break; |
|
168 | + case 'dngettext': |
|
169 | + if (!isset($args[2])) { |
|
170 | + return null; |
|
171 | + } |
|
172 | + |
|
173 | + list($domain, $original, $plural) = $args; |
|
174 | + break; |
|
175 | + default: |
|
176 | + throw new Exception(sprintf('Not valid function %s', $function)); |
|
177 | + } |
|
178 | + |
|
179 | + return [$domain, $context, $original, $plural]; |
|
180 | + } |
|
181 | 181 | } |
@@ -10,91 +10,91 @@ |
||
10 | 10 | */ |
11 | 11 | trait MultidimensionalArrayTrait |
12 | 12 | { |
13 | - use HeadersGeneratorTrait; |
|
14 | - use HeadersExtractorTrait; |
|
13 | + use HeadersGeneratorTrait; |
|
14 | + use HeadersExtractorTrait; |
|
15 | 15 | |
16 | - /** |
|
17 | - * Returns a multidimensional array. |
|
18 | - * |
|
19 | - * @param Translations $translations |
|
20 | - * @param bool $includeHeaders |
|
21 | - * @param bool $forceArray |
|
22 | - * |
|
23 | - * @return array |
|
24 | - */ |
|
25 | - protected static function toArray(Translations $translations, $includeHeaders, $forceArray = false) |
|
26 | - { |
|
27 | - $pluralForm = $translations->getPluralForms(); |
|
28 | - $pluralSize = is_array($pluralForm) ? ($pluralForm[0] - 1) : null; |
|
29 | - $messages = []; |
|
16 | + /** |
|
17 | + * Returns a multidimensional array. |
|
18 | + * |
|
19 | + * @param Translations $translations |
|
20 | + * @param bool $includeHeaders |
|
21 | + * @param bool $forceArray |
|
22 | + * |
|
23 | + * @return array |
|
24 | + */ |
|
25 | + protected static function toArray(Translations $translations, $includeHeaders, $forceArray = false) |
|
26 | + { |
|
27 | + $pluralForm = $translations->getPluralForms(); |
|
28 | + $pluralSize = is_array($pluralForm) ? ($pluralForm[0] - 1) : null; |
|
29 | + $messages = []; |
|
30 | 30 | |
31 | - if ($includeHeaders) { |
|
32 | - $messages[''] = [ |
|
33 | - '' => [static::generateHeaders($translations)], |
|
34 | - ]; |
|
35 | - } |
|
31 | + if ($includeHeaders) { |
|
32 | + $messages[''] = [ |
|
33 | + '' => [static::generateHeaders($translations)], |
|
34 | + ]; |
|
35 | + } |
|
36 | 36 | |
37 | - foreach ($translations as $translation) { |
|
38 | - if ($translation->isDisabled()) { |
|
39 | - continue; |
|
40 | - } |
|
37 | + foreach ($translations as $translation) { |
|
38 | + if ($translation->isDisabled()) { |
|
39 | + continue; |
|
40 | + } |
|
41 | 41 | |
42 | - $context = $translation->getContext(); |
|
43 | - $original = $translation->getOriginal(); |
|
42 | + $context = $translation->getContext(); |
|
43 | + $original = $translation->getOriginal(); |
|
44 | 44 | |
45 | - if (!isset($messages[$context])) { |
|
46 | - $messages[$context] = []; |
|
47 | - } |
|
45 | + if (!isset($messages[$context])) { |
|
46 | + $messages[$context] = []; |
|
47 | + } |
|
48 | 48 | |
49 | - if ($translation->hasPluralTranslations(true)) { |
|
50 | - $messages[$context][$original] = $translation->getPluralTranslations($pluralSize); |
|
51 | - array_unshift($messages[$context][$original], $translation->getTranslation()); |
|
52 | - } elseif ($forceArray) { |
|
53 | - $messages[$context][$original] = [$translation->getTranslation()]; |
|
54 | - } else { |
|
55 | - $messages[$context][$original] = $translation->getTranslation(); |
|
56 | - } |
|
57 | - } |
|
49 | + if ($translation->hasPluralTranslations(true)) { |
|
50 | + $messages[$context][$original] = $translation->getPluralTranslations($pluralSize); |
|
51 | + array_unshift($messages[$context][$original], $translation->getTranslation()); |
|
52 | + } elseif ($forceArray) { |
|
53 | + $messages[$context][$original] = [$translation->getTranslation()]; |
|
54 | + } else { |
|
55 | + $messages[$context][$original] = $translation->getTranslation(); |
|
56 | + } |
|
57 | + } |
|
58 | 58 | |
59 | - return [ |
|
60 | - 'domain' => $translations->getDomain(), |
|
61 | - 'plural-forms' => $translations->getHeader('Plural-Forms'), |
|
62 | - 'messages' => $messages, |
|
63 | - ]; |
|
64 | - } |
|
59 | + return [ |
|
60 | + 'domain' => $translations->getDomain(), |
|
61 | + 'plural-forms' => $translations->getHeader('Plural-Forms'), |
|
62 | + 'messages' => $messages, |
|
63 | + ]; |
|
64 | + } |
|
65 | 65 | |
66 | - /** |
|
67 | - * Extract the entries from a multidimensional array. |
|
68 | - * |
|
69 | - * @param array $messages |
|
70 | - * @param Translations $translations |
|
71 | - */ |
|
72 | - protected static function fromArray(array $messages, Translations $translations) |
|
73 | - { |
|
74 | - if (!empty($messages['domain'])) { |
|
75 | - $translations->setDomain($messages['domain']); |
|
76 | - } |
|
66 | + /** |
|
67 | + * Extract the entries from a multidimensional array. |
|
68 | + * |
|
69 | + * @param array $messages |
|
70 | + * @param Translations $translations |
|
71 | + */ |
|
72 | + protected static function fromArray(array $messages, Translations $translations) |
|
73 | + { |
|
74 | + if (!empty($messages['domain'])) { |
|
75 | + $translations->setDomain($messages['domain']); |
|
76 | + } |
|
77 | 77 | |
78 | - if (!empty($messages['plural-forms'])) { |
|
79 | - $translations->setHeader(Translations::HEADER_PLURAL, $messages['plural-forms']); |
|
80 | - } |
|
78 | + if (!empty($messages['plural-forms'])) { |
|
79 | + $translations->setHeader(Translations::HEADER_PLURAL, $messages['plural-forms']); |
|
80 | + } |
|
81 | 81 | |
82 | - foreach ($messages['messages'] as $context => $contextTranslations) { |
|
83 | - foreach ($contextTranslations as $original => $value) { |
|
84 | - if ($context === '' && $original === '') { |
|
85 | - static::extractHeaders(is_array($value) ? array_shift($value) : $value, $translations); |
|
86 | - continue; |
|
87 | - } |
|
82 | + foreach ($messages['messages'] as $context => $contextTranslations) { |
|
83 | + foreach ($contextTranslations as $original => $value) { |
|
84 | + if ($context === '' && $original === '') { |
|
85 | + static::extractHeaders(is_array($value) ? array_shift($value) : $value, $translations); |
|
86 | + continue; |
|
87 | + } |
|
88 | 88 | |
89 | - $translation = $translations->insert($context, $original); |
|
89 | + $translation = $translations->insert($context, $original); |
|
90 | 90 | |
91 | - if (is_array($value)) { |
|
92 | - $translation->setTranslation(array_shift($value)); |
|
93 | - $translation->setPluralTranslations($value); |
|
94 | - } else { |
|
95 | - $translation->setTranslation($value); |
|
96 | - } |
|
97 | - } |
|
98 | - } |
|
99 | - } |
|
91 | + if (is_array($value)) { |
|
92 | + $translation->setTranslation(array_shift($value)); |
|
93 | + $translation->setPluralTranslations($value); |
|
94 | + } else { |
|
95 | + $translation->setTranslation($value); |
|
96 | + } |
|
97 | + } |
|
98 | + } |
|
99 | + } |
|
100 | 100 | } |
@@ -7,215 +7,215 @@ |
||
7 | 7 | */ |
8 | 8 | final class Merge |
9 | 9 | { |
10 | - const ADD = 1; |
|
11 | - const REMOVE = 2; |
|
12 | - |
|
13 | - const HEADERS_ADD = 4; |
|
14 | - const HEADERS_REMOVE = 8; |
|
15 | - const HEADERS_OVERRIDE = 16; |
|
16 | - |
|
17 | - const LANGUAGE_OVERRIDE = 32; |
|
18 | - const DOMAIN_OVERRIDE = 64; |
|
19 | - const TRANSLATION_OVERRIDE = 128; |
|
20 | - |
|
21 | - const COMMENTS_OURS = 256; |
|
22 | - const COMMENTS_THEIRS = 512; |
|
23 | - |
|
24 | - const EXTRACTED_COMMENTS_OURS = 1024; |
|
25 | - const EXTRACTED_COMMENTS_THEIRS = 2048; |
|
26 | - |
|
27 | - const FLAGS_OURS = 4096; |
|
28 | - const FLAGS_THEIRS = 8192; |
|
29 | - |
|
30 | - const REFERENCES_OURS = 16384; |
|
31 | - const REFERENCES_THEIRS = 32768; |
|
32 | - |
|
33 | - const DEFAULTS = 5; //1 + 4 |
|
34 | - |
|
35 | - /** |
|
36 | - * Merge the flags of two translations. |
|
37 | - * |
|
38 | - * @param Translation $from |
|
39 | - * @param Translation $to |
|
40 | - * @param int $options |
|
41 | - */ |
|
42 | - public static function mergeFlags(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
43 | - { |
|
44 | - if ($options & self::FLAGS_THEIRS) { |
|
45 | - $to->deleteFlags(); |
|
46 | - } |
|
47 | - |
|
48 | - if (!($options & self::FLAGS_OURS)) { |
|
49 | - foreach ($from->getFlags() as $flag) { |
|
50 | - $to->addFlag($flag); |
|
51 | - } |
|
52 | - } |
|
53 | - } |
|
54 | - |
|
55 | - /** |
|
56 | - * Merge the extracted comments of two translations. |
|
57 | - * |
|
58 | - * @param Translation $from |
|
59 | - * @param Translation $to |
|
60 | - * @param int $options |
|
61 | - */ |
|
62 | - public static function mergeExtractedComments(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
63 | - { |
|
64 | - if ($options & self::EXTRACTED_COMMENTS_THEIRS) { |
|
65 | - $to->deleteExtractedComments(); |
|
66 | - } |
|
67 | - |
|
68 | - if (!($options & self::EXTRACTED_COMMENTS_OURS)) { |
|
69 | - foreach ($from->getExtractedComments() as $comment) { |
|
70 | - $to->addExtractedComment($comment); |
|
71 | - } |
|
72 | - } |
|
73 | - } |
|
74 | - |
|
75 | - /** |
|
76 | - * Merge the comments of two translations. |
|
77 | - * |
|
78 | - * @param Translation $from |
|
79 | - * @param Translation $to |
|
80 | - * @param int $options |
|
81 | - */ |
|
82 | - public static function mergeComments(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
83 | - { |
|
84 | - if ($options & self::COMMENTS_THEIRS) { |
|
85 | - $to->deleteComments(); |
|
86 | - } |
|
87 | - |
|
88 | - if (!($options & self::COMMENTS_OURS)) { |
|
89 | - foreach ($from->getComments() as $comment) { |
|
90 | - $to->addComment($comment); |
|
91 | - } |
|
92 | - } |
|
93 | - } |
|
94 | - |
|
95 | - /** |
|
96 | - * Merge the references of two translations. |
|
97 | - * |
|
98 | - * @param Translation $from |
|
99 | - * @param Translation $to |
|
100 | - * @param int $options |
|
101 | - */ |
|
102 | - public static function mergeReferences(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
103 | - { |
|
104 | - if ($options & self::REFERENCES_THEIRS) { |
|
105 | - $to->deleteReferences(); |
|
106 | - } |
|
107 | - |
|
108 | - if (!($options & self::REFERENCES_OURS)) { |
|
109 | - foreach ($from->getReferences() as $reference) { |
|
110 | - $to->addReference($reference[0], $reference[1]); |
|
111 | - } |
|
112 | - } |
|
113 | - } |
|
114 | - |
|
115 | - /** |
|
116 | - * Merge the translations of two translations. |
|
117 | - * |
|
118 | - * @param Translation $from |
|
119 | - * @param Translation $to |
|
120 | - * @param int $options |
|
121 | - */ |
|
122 | - public static function mergeTranslation(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
123 | - { |
|
124 | - $override = (boolean) ($options & self::TRANSLATION_OVERRIDE); |
|
125 | - |
|
126 | - if (!$to->hasTranslation() || ($from->hasTranslation() && $override)) { |
|
127 | - $to->setTranslation($from->getTranslation()); |
|
128 | - } |
|
129 | - |
|
130 | - if (!$to->hasPlural() || ($from->hasPlural() && $override)) { |
|
131 | - $to->setPlural($from->getPlural()); |
|
132 | - } |
|
133 | - |
|
134 | - if (!$to->hasPluralTranslations() || ($from->hasPluralTranslations() && $override)) { |
|
135 | - $to->setPluralTranslations($from->getPluralTranslations()); |
|
136 | - } |
|
137 | - } |
|
138 | - |
|
139 | - /** |
|
140 | - * Merge the translations of two translations. |
|
141 | - * |
|
142 | - * @param Translations $from |
|
143 | - * @param Translations $to |
|
144 | - * @param int $options |
|
145 | - */ |
|
146 | - public static function mergeTranslations(Translations $from, Translations $to, $options = self::DEFAULTS) |
|
147 | - { |
|
148 | - if ($options & self::REMOVE) { |
|
149 | - $filtered = []; |
|
150 | - |
|
151 | - foreach ($to as $entry) { |
|
152 | - if ($from->find($entry)) { |
|
153 | - $filtered[$entry->getId()] = $entry; |
|
154 | - } |
|
155 | - } |
|
156 | - |
|
157 | - $to->exchangeArray($filtered); |
|
158 | - } |
|
159 | - |
|
160 | - foreach ($from as $entry) { |
|
161 | - if (($existing = $to->find($entry))) { |
|
162 | - $existing->mergeWith($entry, $options); |
|
163 | - } elseif ($options & self::ADD) { |
|
164 | - $to[] = $entry->getClone(); |
|
165 | - } |
|
166 | - } |
|
167 | - } |
|
168 | - |
|
169 | - /** |
|
170 | - * Merge the headers of two translations. |
|
171 | - * |
|
172 | - * @param Translations $from |
|
173 | - * @param Translations $to |
|
174 | - * @param int $options |
|
175 | - */ |
|
176 | - public static function mergeHeaders(Translations $from, Translations $to, $options = self::DEFAULTS) |
|
177 | - { |
|
178 | - if ($options & self::HEADERS_REMOVE) { |
|
179 | - foreach (array_keys($to->getHeaders()) as $name) { |
|
180 | - if ($from->getHeader($name) === null) { |
|
181 | - $to->deleteHeader($name); |
|
182 | - } |
|
183 | - } |
|
184 | - } |
|
185 | - |
|
186 | - foreach ($from->getHeaders() as $name => $value) { |
|
187 | - $current = $to->getHeader($name); |
|
188 | - |
|
189 | - if (empty($current)) { |
|
190 | - if ($options & self::HEADERS_ADD) { |
|
191 | - $to->setHeader($name, $value); |
|
192 | - } |
|
193 | - continue; |
|
194 | - } |
|
195 | - |
|
196 | - if (empty($value)) { |
|
197 | - continue; |
|
198 | - } |
|
199 | - |
|
200 | - switch ($name) { |
|
201 | - case Translations::HEADER_LANGUAGE: |
|
202 | - case Translations::HEADER_PLURAL: |
|
203 | - if ($options & self::LANGUAGE_OVERRIDE) { |
|
204 | - $to->setHeader($name, $value); |
|
205 | - } |
|
206 | - break; |
|
207 | - |
|
208 | - case Translations::HEADER_DOMAIN: |
|
209 | - if ($options & self::DOMAIN_OVERRIDE) { |
|
210 | - $to->setHeader($name, $value); |
|
211 | - } |
|
212 | - break; |
|
213 | - |
|
214 | - default: |
|
215 | - if ($options & self::HEADERS_OVERRIDE) { |
|
216 | - $to->setHeader($name, $value); |
|
217 | - } |
|
218 | - } |
|
219 | - } |
|
220 | - } |
|
10 | + const ADD = 1; |
|
11 | + const REMOVE = 2; |
|
12 | + |
|
13 | + const HEADERS_ADD = 4; |
|
14 | + const HEADERS_REMOVE = 8; |
|
15 | + const HEADERS_OVERRIDE = 16; |
|
16 | + |
|
17 | + const LANGUAGE_OVERRIDE = 32; |
|
18 | + const DOMAIN_OVERRIDE = 64; |
|
19 | + const TRANSLATION_OVERRIDE = 128; |
|
20 | + |
|
21 | + const COMMENTS_OURS = 256; |
|
22 | + const COMMENTS_THEIRS = 512; |
|
23 | + |
|
24 | + const EXTRACTED_COMMENTS_OURS = 1024; |
|
25 | + const EXTRACTED_COMMENTS_THEIRS = 2048; |
|
26 | + |
|
27 | + const FLAGS_OURS = 4096; |
|
28 | + const FLAGS_THEIRS = 8192; |
|
29 | + |
|
30 | + const REFERENCES_OURS = 16384; |
|
31 | + const REFERENCES_THEIRS = 32768; |
|
32 | + |
|
33 | + const DEFAULTS = 5; //1 + 4 |
|
34 | + |
|
35 | + /** |
|
36 | + * Merge the flags of two translations. |
|
37 | + * |
|
38 | + * @param Translation $from |
|
39 | + * @param Translation $to |
|
40 | + * @param int $options |
|
41 | + */ |
|
42 | + public static function mergeFlags(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
43 | + { |
|
44 | + if ($options & self::FLAGS_THEIRS) { |
|
45 | + $to->deleteFlags(); |
|
46 | + } |
|
47 | + |
|
48 | + if (!($options & self::FLAGS_OURS)) { |
|
49 | + foreach ($from->getFlags() as $flag) { |
|
50 | + $to->addFlag($flag); |
|
51 | + } |
|
52 | + } |
|
53 | + } |
|
54 | + |
|
55 | + /** |
|
56 | + * Merge the extracted comments of two translations. |
|
57 | + * |
|
58 | + * @param Translation $from |
|
59 | + * @param Translation $to |
|
60 | + * @param int $options |
|
61 | + */ |
|
62 | + public static function mergeExtractedComments(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
63 | + { |
|
64 | + if ($options & self::EXTRACTED_COMMENTS_THEIRS) { |
|
65 | + $to->deleteExtractedComments(); |
|
66 | + } |
|
67 | + |
|
68 | + if (!($options & self::EXTRACTED_COMMENTS_OURS)) { |
|
69 | + foreach ($from->getExtractedComments() as $comment) { |
|
70 | + $to->addExtractedComment($comment); |
|
71 | + } |
|
72 | + } |
|
73 | + } |
|
74 | + |
|
75 | + /** |
|
76 | + * Merge the comments of two translations. |
|
77 | + * |
|
78 | + * @param Translation $from |
|
79 | + * @param Translation $to |
|
80 | + * @param int $options |
|
81 | + */ |
|
82 | + public static function mergeComments(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
83 | + { |
|
84 | + if ($options & self::COMMENTS_THEIRS) { |
|
85 | + $to->deleteComments(); |
|
86 | + } |
|
87 | + |
|
88 | + if (!($options & self::COMMENTS_OURS)) { |
|
89 | + foreach ($from->getComments() as $comment) { |
|
90 | + $to->addComment($comment); |
|
91 | + } |
|
92 | + } |
|
93 | + } |
|
94 | + |
|
95 | + /** |
|
96 | + * Merge the references of two translations. |
|
97 | + * |
|
98 | + * @param Translation $from |
|
99 | + * @param Translation $to |
|
100 | + * @param int $options |
|
101 | + */ |
|
102 | + public static function mergeReferences(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
103 | + { |
|
104 | + if ($options & self::REFERENCES_THEIRS) { |
|
105 | + $to->deleteReferences(); |
|
106 | + } |
|
107 | + |
|
108 | + if (!($options & self::REFERENCES_OURS)) { |
|
109 | + foreach ($from->getReferences() as $reference) { |
|
110 | + $to->addReference($reference[0], $reference[1]); |
|
111 | + } |
|
112 | + } |
|
113 | + } |
|
114 | + |
|
115 | + /** |
|
116 | + * Merge the translations of two translations. |
|
117 | + * |
|
118 | + * @param Translation $from |
|
119 | + * @param Translation $to |
|
120 | + * @param int $options |
|
121 | + */ |
|
122 | + public static function mergeTranslation(Translation $from, Translation $to, $options = self::DEFAULTS) |
|
123 | + { |
|
124 | + $override = (boolean) ($options & self::TRANSLATION_OVERRIDE); |
|
125 | + |
|
126 | + if (!$to->hasTranslation() || ($from->hasTranslation() && $override)) { |
|
127 | + $to->setTranslation($from->getTranslation()); |
|
128 | + } |
|
129 | + |
|
130 | + if (!$to->hasPlural() || ($from->hasPlural() && $override)) { |
|
131 | + $to->setPlural($from->getPlural()); |
|
132 | + } |
|
133 | + |
|
134 | + if (!$to->hasPluralTranslations() || ($from->hasPluralTranslations() && $override)) { |
|
135 | + $to->setPluralTranslations($from->getPluralTranslations()); |
|
136 | + } |
|
137 | + } |
|
138 | + |
|
139 | + /** |
|
140 | + * Merge the translations of two translations. |
|
141 | + * |
|
142 | + * @param Translations $from |
|
143 | + * @param Translations $to |
|
144 | + * @param int $options |
|
145 | + */ |
|
146 | + public static function mergeTranslations(Translations $from, Translations $to, $options = self::DEFAULTS) |
|
147 | + { |
|
148 | + if ($options & self::REMOVE) { |
|
149 | + $filtered = []; |
|
150 | + |
|
151 | + foreach ($to as $entry) { |
|
152 | + if ($from->find($entry)) { |
|
153 | + $filtered[$entry->getId()] = $entry; |
|
154 | + } |
|
155 | + } |
|
156 | + |
|
157 | + $to->exchangeArray($filtered); |
|
158 | + } |
|
159 | + |
|
160 | + foreach ($from as $entry) { |
|
161 | + if (($existing = $to->find($entry))) { |
|
162 | + $existing->mergeWith($entry, $options); |
|
163 | + } elseif ($options & self::ADD) { |
|
164 | + $to[] = $entry->getClone(); |
|
165 | + } |
|
166 | + } |
|
167 | + } |
|
168 | + |
|
169 | + /** |
|
170 | + * Merge the headers of two translations. |
|
171 | + * |
|
172 | + * @param Translations $from |
|
173 | + * @param Translations $to |
|
174 | + * @param int $options |
|
175 | + */ |
|
176 | + public static function mergeHeaders(Translations $from, Translations $to, $options = self::DEFAULTS) |
|
177 | + { |
|
178 | + if ($options & self::HEADERS_REMOVE) { |
|
179 | + foreach (array_keys($to->getHeaders()) as $name) { |
|
180 | + if ($from->getHeader($name) === null) { |
|
181 | + $to->deleteHeader($name); |
|
182 | + } |
|
183 | + } |
|
184 | + } |
|
185 | + |
|
186 | + foreach ($from->getHeaders() as $name => $value) { |
|
187 | + $current = $to->getHeader($name); |
|
188 | + |
|
189 | + if (empty($current)) { |
|
190 | + if ($options & self::HEADERS_ADD) { |
|
191 | + $to->setHeader($name, $value); |
|
192 | + } |
|
193 | + continue; |
|
194 | + } |
|
195 | + |
|
196 | + if (empty($value)) { |
|
197 | + continue; |
|
198 | + } |
|
199 | + |
|
200 | + switch ($name) { |
|
201 | + case Translations::HEADER_LANGUAGE: |
|
202 | + case Translations::HEADER_PLURAL: |
|
203 | + if ($options & self::LANGUAGE_OVERRIDE) { |
|
204 | + $to->setHeader($name, $value); |
|
205 | + } |
|
206 | + break; |
|
207 | + |
|
208 | + case Translations::HEADER_DOMAIN: |
|
209 | + if ($options & self::DOMAIN_OVERRIDE) { |
|
210 | + $to->setHeader($name, $value); |
|
211 | + } |
|
212 | + break; |
|
213 | + |
|
214 | + default: |
|
215 | + if ($options & self::HEADERS_OVERRIDE) { |
|
216 | + $to->setHeader($name, $value); |
|
217 | + } |
|
218 | + } |
|
219 | + } |
|
220 | + } |
|
221 | 221 | } |