1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
|
<?php
loco_require_lib('compiled/gettext.php');
/** * String extraction from source code. */ class Loco_gettext_Extraction {
/** * @var Loco_package_Bundle */ private $bundle;
/** * @var LocoExtracted */ private $extracted;
/** * Extra strings to be pushed into domains * @var array */ private $extras = [];
/** * List of files skipped due to memory limit * @var Loco_fs_FileList|null */ private $skipped;
/** * Size in bytes of largest file encountered * @var int */ private $maxbytes = 0;
/** * Initialize extractor for a given bundle */ public function __construct( Loco_package_Bundle $bundle ){ loco_check_extension('ctype'); if( ! loco_check_extension('tokenizer') ){ throw new Loco_error_Exception('String extraction not available without required extension'); } $this->bundle = $bundle; $this->extracted = new LocoExtracted; $this->extracted->setDomain('default'); $default = $bundle->getDefaultProject(); if( $default instanceof Loco_package_Project ){ $domain = $default->getDomain()->getName(); // wildcard stands in for empty text domain, meaning unspecified or dynamic domains will be included. // note that strings intended to be in "default" domain must specify explicitly, or be included here too. if( '*' === $domain ){ $domain = ''; $this->extracted->setDomain(''); } // pull bundle's default metadata. these are translations that may not be encountered in files $extras = []; $header = $bundle->getHeaderInfo(); foreach( $bundle->getMetaTranslatable() as $prop => $notes ){ $text = $header->__get($prop); if( is_string($text) && '' !== $text ){ $extras[] = ['source'=>$text, 'notes'=>$notes ]; } } if( $extras ){ $this->extras[$domain] = $extras; } } }
/** * @return self */ public function addProject( Loco_package_Project $project ){ $base = $this->bundle->getDirectoryPath(); $domain = (string) $project->getDomain(); // skip files larger than configured maximum $opts = Loco_data_Settings::get(); $max = wp_convert_hr_to_bytes( $opts->max_php_size ); // *attempt* to raise memory limit to WP_MAX_MEMORY_LIMIT if( function_exists('wp_raise_memory_limit') ){ wp_raise_memory_limit('loco'); } /* @var Loco_fs_File $file */ foreach( $project->findSourceFiles() as $file ){ $type = $opts->ext2type( $file->extension() ); $fileref = $file->getRelativePath($base); try { $extr = loco_wp_extractor( $type, $file->fullExtension() ); if( 'php' === $type || 'twig' === $type) { // skip large files for PHP, because token_get_all is hungry if( 0 !== $max ){ $size = $file->size(); $this->maxbytes = max( $this->maxbytes, $size ); if( $size > $max ){ $list = $this->skipped or $list = ( $this->skipped = new Loco_fs_FileList() ); $list->add( $file ); continue; } } // extract headers from theme files (templates and patterns) if( $project->getBundle()->isTheme() ){ $extr->headerize( [ 'Template Name' => ['notes'=>'Name of the template'], ], $domain ); if( preg_match('!^patterns/!', $fileref) ){ $extr->headerize([ 'Title' => ['context'=>'Pattern title'], 'Description' => ['context'=>'Pattern description'], ], $domain ); } } } // normally missing domains are treated as "default", but we'll make an exception for theme.json. else if( 'json' === $type && $project->getBundle()->isTheme() ){ $extr->setDomain($domain); } $this->extracted->extractSource( $extr, $file->getContents(), $fileref ); } catch( Exception $e ){ Loco_error_AdminNotices::debug('Error extracting '.$fileref.': '.$e->getMessage() ); } } return $this; }
/** * Add metadata strings deferred from construction. Note this will alter domain counts * @return self */ public function includeMeta(){ foreach( $this->extras as $domain => $extras ){ foreach( $extras as $entry ){ $this->extracted->pushEntry($entry,$domain); } } $this->extras = []; return $this; }
/** * Add a custom source string constructed from `new Loco_gettext_String(msgid,[msgctxt])` * @param Loco_gettext_String $string * @param string $domain Optional text domain, if not current bundle's default * @return void */ public function addString( Loco_gettext_String $string, $domain = '' ){ if( ! $domain ) { $default = $this->bundle->getDefaultProject(); $domain = (string) ( $default ? $default->getDomain() : $this->extracted->getDomain() ); } $index = $this->extracted->pushEntry( $string->exportSingular(), $domain ); if( $string->hasPlural() ){ $this->extracted->pushPlural( $string->exportPlural(), $index ); } }
/** * Get number of unique strings across all domains extracted (excluding additional metadata) * @return array { default: x, myDomain: y } */ public function getDomainCounts(){ return $this->extracted->getDomainCounts(); }
/** * Pull extracted data into POT, filtering out any unwanted domains * @param string $domain * @return Loco_gettext_Data */ public function getTemplate( $domain ){ do_action('loco_extracted_template', $this, $domain ); $data = new Loco_gettext_Data( $this->extracted->filter($domain) ); return $data->templatize( $domain ); }
/** * Get total number of strings extracted from all domains, excluding additional metadata * @return int */ public function getTotal(){ return $this->extracted->count(); }
/** * Get list of files skipped, or null if none were skipped * @return Loco_fs_FileList|null */ public function getSkipped(){ return $this->skipped; }
/** * Get size in bytes of largest file encountered, even if skipped. * This is the value required of the max_php_size plugin setting to extract all files * @return int */ public function getMaxPhpSize(){ return $this->maxbytes; }
}
|