Index: trunk/extensions/DataTransclusion/DataTransclusion.i18n.php |
— | — | @@ -21,16 +21,18 @@ |
22 | 22 | 'datatransclusion-test-nowiki' => 'some <nowiki>{{nowiki}}</nowiki> code.', // Do not translate. |
23 | 23 | |
24 | 24 | 'datatransclusion-missing-source' => 'No data source specified. |
25 | | -First argument is required.', |
| 25 | +Second or "source" argument is required.', #FUZZ! |
26 | 26 | 'datatransclusion-unknown-source' => 'Bad data source specified. |
27 | 27 | "$1" is not known.', |
| 28 | + 'datatransclusion-missing-key' => 'No key specified. |
| 29 | +$2 are valid keys in data source $1.', |
28 | 30 | 'datatransclusion-bad-argument-by' => 'Bad key field specified. |
29 | 31 | "$2" is not a key field in data source "$1". |
30 | 32 | {{PLURAL:$4|Valid key|Valid keys are}}: $3.', |
31 | 33 | 'datatransclusion-missing-argument-key' => 'No key value specified. |
32 | 34 | Second or "key" argument is required.', |
33 | 35 | 'datatransclusion-missing-argument-template' => 'No template specified. |
34 | | -Third or "template" argument is required.', |
| 36 | +First or "template" argument is required.', #FUZZ! |
35 | 37 | 'datatransclusion-record-not-found' => 'No record matching $2 = $3 was found in data source $1.', |
36 | 38 | 'datatransclusion-bad-template-name' => 'Bad template name: $1.', |
37 | 39 | 'datatransclusion-unknown-template' => '<nowiki>{{</nowiki>[[{{ns:template}}:$1|$1]]<nowiki>}}</nowiki> does not exist.', |
— | — | @@ -41,16 +43,14 @@ |
42 | 44 | */ |
43 | 45 | $messages['qqq'] = array( |
44 | 46 | 'datatransclusion-desc' => '{{desc}}', |
45 | | - 'datatransclusion-missing-source' => 'Issued if no data source was specified.', |
| 47 | + 'datatransclusion-missing-source' => 'Issued if no data "source" or second positional argument was specified.', |
46 | 48 | 'datatransclusion-unknown-source' => 'Issued if an unknown data source was specified. Parameters: |
47 | 49 | * $1 is the name of the data source.', |
48 | | - 'datatransclusion-bad-argument-by' => 'Issued if a bad value was specified for the "by" argument, that is, an unknown key field was selected. Parameters: |
| 50 | + 'datatransclusion-missing-key' => 'Issued if no argument matches an entry in the list of key field. Parameters: |
49 | 51 | * $1 is the name of the data source |
50 | | -* $2 is the value of the by argument |
51 | | -* $3 is a list of all valid keys for this data source |
52 | | -* $4 is the number of valid keys for this data source.', |
53 | | - 'datatransclusion-missing-argument-key' => 'Issued if no "key" or second positional argument was given provided. A key value is always required.', |
54 | | - 'datatransclusion-missing-argument-template' => 'Issued if no "template" or third positional argument was given provided. A target template is always required.', |
| 52 | +* $2 is a list of all valid keys for this data source |
| 53 | +* $3 is the number of valid keys for this data source.', |
| 54 | + 'datatransclusion-missing-argument-template' => 'Issued if no "template" or first positional argument was given provided. A target template is always required.', |
55 | 55 | 'datatransclusion-record-not-found' => 'issued if the record specified using the "by" and "key" arguments was nout found in the data source. Parameters: |
56 | 56 | * $1 is the name of the data source |
57 | 57 | * $2 is the key filed used |
— | — | @@ -71,10 +71,6 @@ |
72 | 72 | Першы парамэтар — абавязковы.', |
73 | 73 | 'datatransclusion-unknown-source' => 'Няслушная крыніца зьвестак. |
74 | 74 | $1 — невядомая.', |
75 | | - 'datatransclusion-bad-argument-by' => 'Пазначана няслушнае ключавое поле. |
76 | | -$2 не зьяўляецца ключавым полем ў крыніцы зьвестак $1, слушныя ключы: $3.', |
77 | | - 'datatransclusion-missing-argument-key' => 'Ключавое значэньне не пазначана. |
78 | | -Неабходны другі ці «ключавы» аргумэнт.', |
79 | 75 | 'datatransclusion-missing-argument-template' => 'Шаблён не пазначаны. |
80 | 76 | Неабходны трэці ці «шаблённы» аргумэнт.', |
81 | 77 | 'datatransclusion-record-not-found' => 'Ня знойдзеныя супадаючыя запісы $2 = $3 ў крыніцы зьвестак $1.', |
— | — | @@ -99,10 +95,6 @@ |
100 | 96 | Das erste Argument ist erforderlich.', |
101 | 97 | 'datatransclusion-unknown-source' => 'Es wurde eine mangelhafte Datenquelle angegeben. |
102 | 98 | $1 ist nicht bekannt.', |
103 | | - 'datatransclusion-bad-argument-by' => 'Es wurde ein mangelhaftes Schlüsselfeld angegeben. |
104 | | -$2 ist kein Schlüsselfeld in der Datenquelle $1. Gültige Schlüssel sind: $3.', |
105 | | - 'datatransclusion-missing-argument-key' => 'Es wurde kein Schlüssel-Wert angegeben. |
106 | | -Ein zweites oder ein Schlüssel-Argument ist erforderlich.', |
107 | 99 | 'datatransclusion-missing-argument-template' => 'Es wurde keine Vorlage angegeben. |
108 | 100 | Ein drittes oder ein Vorlagen-Argument ist erforderlich.', |
109 | 101 | 'datatransclusion-record-not-found' => 'Es wurde kein passender Datensatz $2 = $3 in der Datenquelle $1 gefunden.', |
— | — | @@ -119,9 +111,6 @@ |
120 | 112 | Prědny argument jo trěbny.', |
121 | 113 | 'datatransclusion-unknown-source' => 'Wopacne datowe žrědło pódane. |
122 | 114 | $1 jo njeznaty.', |
123 | | - 'datatransclusion-bad-argument-by' => '$2 njejo klucowe pólo w datowem žrědle $1, płaśiwe kluce su: $3.', |
124 | | - 'datatransclusion-missing-argument-key' => 'Žedna datowa gódnota pódana. |
125 | | -Drugi abo "klucowy" argument je trěbny.', |
126 | 115 | 'datatransclusion-missing-argument-template' => 'Žedna pśedłoga pódana. |
127 | 116 | Tśeśi abo "pśedłogowy" argument jo trěbny.', |
128 | 117 | 'datatransclusion-record-not-found' => 'W datowem žrědle $1 njejo se žedna sajźba namakała, kótaraž $2=$3 wótpowědujo.', |
— | — | @@ -138,11 +127,6 @@ |
139 | 128 | Primer argumento es obligatorio.', |
140 | 129 | 'datatransclusion-unknown-source' => 'Fuente de datos mal especificado. |
141 | 130 | $1 es desconocido.', |
142 | | - 'datatransclusion-bad-argument-by' => 'Campo clave mal especificado. |
143 | | -"$2" no es un campo clave en la fuente de datos "$1". |
144 | | -{{PLURAL:$4|Clave válida|Claves válidas son}}: $3.', |
145 | | - 'datatransclusion-missing-argument-key' => 'Ningún valor clave especificado. |
146 | | -Argumento segundo o "clave" es obligatorio.', |
147 | 131 | 'datatransclusion-missing-argument-template' => 'Ninguna plantilla especificada. |
148 | 132 | Argumento tercero o "plantilla" es obligatorio.', |
149 | 133 | 'datatransclusion-record-not-found' => 'Ningún registro coincidente $2 = $3 fue encontrado en la fuente de datos $1.', |
— | — | @@ -159,10 +143,6 @@ |
160 | 144 | Le premier argument est obligatoire.', |
161 | 145 | 'datatransclusion-unknown-source' => 'Mauvaise source de données spécifiée. |
162 | 146 | $1 est inconnu.', |
163 | | - 'datatransclusion-bad-argument-by' => 'Mauvaise clé de champ spécifiée. |
164 | | -$2 n’est pas une clé de champ dans la source de données $1 ; les clés valides sont : $3.', |
165 | | - 'datatransclusion-missing-argument-key' => 'Aucune valeur de clé spécifiée. |
166 | | -Le deuxième argument ou « clé » est obligatoire.', |
167 | 147 | 'datatransclusion-missing-argument-template' => 'Aucun modèle spécifié. |
168 | 148 | Le troisième argument ou « modèle » est obligatoire.', |
169 | 149 | 'datatransclusion-record-not-found' => 'Aucun enregistrement vérifiant $2 = $3 n’a été trouvé dans la source de données $1.', |
— | — | @@ -199,10 +179,6 @@ |
200 | 180 | Prěni argument je trěbny.', |
201 | 181 | 'datatransclusion-unknown-source' => 'Wopačne datowe žórło podate. |
202 | 182 | $1 je njeznaty.', |
203 | | - 'datatransclusion-bad-argument-by' => 'Wopačne klučowe polo podate. |
204 | | -$2 njeje klučowe polo w datowym žórle $1, płaćiwe kluče su: $3', |
205 | | - 'datatransclusion-missing-argument-key' => 'Žana klučowa hódnota podata. |
206 | | -Druhi abo "klučowy" argument je trěbny.', |
207 | 183 | 'datatransclusion-missing-argument-template' => 'Žana předłoha podata. |
208 | 184 | Třeći abo "předłohowy" argument je trěbny.', |
209 | 185 | 'datatransclusion-record-not-found' => 'W datowym žórle $1 njeje so žana datowa sadźba namakała, kotraž $2=$3 wotpowěduje.', |
— | — | @@ -219,10 +195,6 @@ |
220 | 196 | Le prime parametro es obligatori.', |
221 | 197 | 'datatransclusion-unknown-source' => 'Un fonte de datos invalide ha essite specificate. |
222 | 198 | $1 non es cognoscite.', |
223 | | - 'datatransclusion-bad-argument-by' => 'Un campo de clave invalide ha essite specificate. |
224 | | -$2 non es un campo de clave in le fonte de datos $1. Le claves valide es: $3.', |
225 | | - 'datatransclusion-missing-argument-key' => 'Nulle valor de clave specificate. |
226 | | -Un secunde parametro "key" es obligatori.', |
227 | 199 | 'datatransclusion-missing-argument-template' => 'Nulle patrono specificate. |
228 | 200 | Un tertie parametro "template" es obligatori.', |
229 | 201 | 'datatransclusion-record-not-found' => 'Nulle dato correspondente a $2 = $3 ha essite trovate in le fonte de datos $1.', |
— | — | @@ -245,8 +217,6 @@ |
246 | 218 | 'datatransclusion-desc' => 'Увоз и обликување на податотечни записи од надворешни податотечни извори', |
247 | 219 | 'datatransclusion-missing-source' => 'не е укажан податотечен извор (се бара првиот аргумент)', |
248 | 220 | 'datatransclusion-unknown-source' => 'укажан е лош податотечен извор ($1 е непознат)', |
249 | | - 'datatransclusion-bad-argument-by' => 'укажано е лошо поле за клуч ($2 не претставува поле за клуч во податочниот извор $1. Важечки клучеви се: $3)', |
250 | | - 'datatransclusion-missing-argument-key' => 'нема укажано вредност за клучот (се бара вториот аргумент или „клуч“)', |
251 | 221 | 'datatransclusion-missing-argument-template' => 'нема укажано шаблон (се бара третиот аргумент или „шаблон“)', |
252 | 222 | 'datatransclusion-record-not-found' => 'во податочниот извор $1 нема пронајдено запис што одговара на $2 = $3', |
253 | 223 | 'datatransclusion-bad-template-name' => 'лошо име на шаблон: $1', |
— | — | @@ -262,11 +232,6 @@ |
263 | 233 | Het eerste argument is verplicht.', |
264 | 234 | 'datatransclusion-unknown-source' => 'Er is een ongeldige gegevensbron aangegeven. |
265 | 235 | $1 is niet bekend.', |
266 | | - 'datatransclusion-bad-argument-by' => 'Ongeldig sleutelveld aangegeven. |
267 | | -$2 is geen sleutelveld in gegevensbron $1. |
268 | | -Geldige {{PLUARAL:$4|sleutel is|sleutels zijn}}: $3.', |
269 | | - 'datatransclusion-missing-argument-key' => 'Er is geen sleutelwaarde aangegeven. |
270 | | -Een tweede argument of "sleutel" is verplicht.', |
271 | 236 | 'datatransclusion-missing-argument-template' => 'Geen sjabloon aangegeven. |
272 | 237 | Een derde argument of "template" is verplicht.', |
273 | 238 | 'datatransclusion-record-not-found' => 'Er is geen overeenkomstig gegeven $2 = $3 gevonden in de gegevensbron $1.', |
— | — | @@ -283,10 +248,6 @@ |
284 | 249 | O primeiro argumento é obrigatório.', |
285 | 250 | 'datatransclusion-unknown-source' => 'A fonte de dados especificada é incorrecta. |
286 | 251 | $1 não é conhecido.', |
287 | | - 'datatransclusion-bad-argument-by' => 'Foi especificado um campo chave incorrecto. |
288 | | -$2 não é um campo chave na fonte de dados $1; as chaves válidas são: $3.', |
289 | | - 'datatransclusion-missing-argument-key' => 'Não foi especificado um campo chave. |
290 | | -O segundo argumento, ou argumento "chave", é obrigatório.', |
291 | 252 | 'datatransclusion-missing-argument-template' => 'Não foi especificada uma predefinição. |
292 | 253 | O terceiro argumento, ou argumento "predefinição", é obrigatório.', |
293 | 254 | 'datatransclusion-record-not-found' => 'Não foi encontrado nenhum registo $2 = $3 na fonte de dados $1.', |
— | — | @@ -303,10 +264,6 @@ |
304 | 265 | Первый аргумент является обязательным.', |
305 | 266 | 'datatransclusion-unknown-source' => 'Указан неправильный источник данных. |
306 | 267 | $1 — неизвестен.', |
307 | | - 'datatransclusion-bad-argument-by' => 'Указано неправильное ключевое поле. |
308 | | -$2 не является ключевым полем в источнике данных $1. Действительными ключами являются: $3.', |
309 | | - 'datatransclusion-missing-argument-key' => 'Не указано значение ключа. |
310 | | -Второй или «ключевой» аргумент является обязательным.', |
311 | 268 | 'datatransclusion-missing-argument-template' => 'Не указан шаблон. |
312 | 269 | Третий или «шаблонный» аргумент является обязательным.', |
313 | 270 | 'datatransclusion-record-not-found' => 'В источнике данных $1 не найдено записи, соответствующей $2 = $3', |
— | — | @@ -323,10 +280,6 @@ |
324 | 281 | Kailangan ang unang argumento.', |
325 | 282 | 'datatransclusion-unknown-source' => 'Natukoy ang masamang pinagmulan ng dato. |
326 | 283 | Hindi alam ang $1.', |
327 | | - 'datatransclusion-bad-argument-by' => 'Natukoy ang isang larangan ng masamang susi. |
328 | | -Ang $2 ay hindi isang susing larangan sa loob ng pinagmulan ng dato na $1, ang tanggap na mga susi ay: $3.', |
329 | | - 'datatransclusion-missing-argument-key' => 'Walang tinukoy na halaga ng susi. |
330 | | -Kailangan ang pangalawa o "susi" na argumento.', |
331 | 284 | 'datatransclusion-missing-argument-template' => 'Walang tinukoy na suleras. |
332 | 285 | Kailangan ang pangatlo o argumentong "suleras".', |
333 | 286 | 'datatransclusion-record-not-found' => 'Walang natagpuang rekord na tumutugma sa $2 = $3 na nasa loob ng pinagmulan ng dato na $1.', |
Index: trunk/extensions/DataTransclusion/DataTransclusionHandler.php |
— | — | @@ -14,6 +14,12 @@ |
15 | 15 | die( 1 ); |
16 | 16 | } |
17 | 17 | |
| 18 | +/** DataTransclusionHandler implements handlers for a parser tag and a parser function, |
| 19 | +* both called record, for fetching a data record from some external source. They are used |
| 20 | +* as follows: <record source="SourceName" key="value">SomeTemplate</record> where |
| 21 | +* "key" may be any field name defined of a key field for that data source. Similarly: |
| 22 | +* {{#record:SomeTemplate|SourceName|key=value}}. |
| 23 | +*/ |
18 | 24 | class DataTransclusionHandler { |
19 | 25 | static function buildAssociativeArguments ( $params ) { |
20 | 26 | // build associative arguments from flat parameter list |
— | — | @@ -48,11 +54,15 @@ |
49 | 55 | return ''; // no category specified, return nothing |
50 | 56 | } |
51 | 57 | |
| 58 | + //first parameter is the template name |
| 59 | + $template = array_shift( $params ); |
| 60 | + |
52 | 61 | // build associative arguments from flat parameter list |
53 | 62 | $argv = DataTransclusionHandler::buildAssociativeArguments( $params ); |
| 63 | + $argv[ 0 ] = $template; |
54 | 64 | |
55 | 65 | // FIXME: error messages contining special blocks like <nowiki> don't get re-substitutet correctly. |
56 | | - $text = DataTransclusionHandler::handleRecordTransclusion( null, $argv, $parser, false ); |
| 66 | + $text = DataTransclusionHandler::handleRecordTransclusion( $template, $argv, $parser, false ); |
57 | 67 | return array( $text, 'noparse' => false, 'isHTML' => false ); |
58 | 68 | } |
59 | 69 | |
— | — | @@ -76,15 +86,15 @@ |
77 | 87 | /** |
78 | 88 | * Entry point for the <record> tag parser hook. Delegates to handleRecordTransclusion. |
79 | 89 | */ |
80 | | - static function handleRecordTag( $key, $argv, $parser ) { |
81 | | - return DataTransclusionHandler::handleRecordTransclusion( $key, $argv, $parser, true ); |
| 90 | + static function handleRecordTag( $text, $argv, $parser ) { |
| 91 | + return DataTransclusionHandler::handleRecordTransclusion( $text, $argv, $parser, true ); |
82 | 92 | } |
83 | 93 | |
84 | 94 | /** |
85 | 95 | * Fetches a records and renders it, according to the given array of parameters. |
86 | 96 | * Common implementation for parser tag and parser function. |
87 | 97 | */ |
88 | | - static function handleRecordTransclusion( $key, $argv, $parser, $asHTML, $templateText = null ) { |
| 98 | + static function handleRecordTransclusion( $template, $argv, $parser, $asHTML, $templateText = null ) { |
89 | 99 | // find out which data source to use... |
90 | 100 | if ( empty( $argv['source'] ) ) { |
91 | 101 | if ( empty( $argv[1] ) ) { |
— | — | @@ -99,50 +109,54 @@ |
100 | 110 | |
101 | 111 | $source = DataTransclusionHandler::getDataSource( $sourceName ); |
102 | 112 | if ( empty( $source ) ) { |
103 | | - wfDebugLog( 'DataTransclusion', "unknown data-source: $sourceName\n" ); |
| 113 | + wfDebugLog( 'DataTransclusion', "unknown source: $sourceName\n" ); |
104 | 114 | return DataTransclusionHandler::errorMessage( 'datatransclusion-unknown-source', $asHTML, $sourceName ); |
105 | 115 | } |
106 | 116 | |
107 | | - // find out how to find the desired record |
108 | | - if ( empty( $argv['by'] ) ) { |
109 | | - $by = $source->getDefaultKey(); |
110 | | - } else { |
111 | | - $by = $argv['by']; |
| 117 | + // find out how to render the record |
| 118 | + if ( !empty( $argv['template'] ) ) { |
| 119 | + $template = $argv['template']; |
| 120 | + } else if ( $template === null || $template === false ) { |
| 121 | + if ( empty( $argv[0] ) ) { |
| 122 | + wfDebugLog( 'DataTransclusion', "missing 'template' argument\n" ); |
| 123 | + return DataTransclusionHandler::errorMessage( 'datatransclusion-missing-argument-template', $asHTML ); |
| 124 | + } else { |
| 125 | + $template = $argv[0]; |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + // find key |
| 130 | + $by = false; |
| 131 | + $key = false; |
| 132 | + $keyFields = $source->getKeyFields(); |
| 133 | + foreach ( $keyFields as $k ) { |
| 134 | + if ( isset( $argv[ $k ] ) ) { |
| 135 | + $by = $k; |
| 136 | + $key = $argv[ $k ]; |
| 137 | + break; //XXX: could keep running and complain about multiple keys |
| 138 | + } |
112 | 139 | } |
113 | 140 | |
114 | | - $keyFields = $source->getKeyFields(); |
115 | | - if ( ! in_array( $by, $keyFields ) ) { |
| 141 | + if ( !$by ) { |
116 | 142 | global $wgContLang; |
117 | | - wfDebugLog( 'DataTransclusion', "bad 'by' argument: $by (not a known key field)\n" ); |
118 | | - return DataTransclusionHandler::errorMessage( 'datatransclusion-bad-argument-by', $asHTML, $sourceName, $by, |
| 143 | + wfDebugLog( 'DataTransclusion', "no key specified\n" ); |
| 144 | + return DataTransclusionHandler::errorMessage( 'datatransclusion-missing-key', $asHTML, $sourceName, |
119 | 145 | $wgContLang->commaList( $keyFields ), count( $keyFields ) ); |
120 | 146 | } |
121 | 147 | |
122 | | - if ( !empty( $argv['key'] ) ) { |
123 | | - $key = $argv['key']; |
124 | | - } else if ( $key === null || $key === false ) { |
125 | | - if ( empty( $argv[2] ) ) { |
126 | | - wfDebugLog( 'DataTransclusion', "missing 'key' argument\n" ); |
127 | | - return DataTransclusionHandler::errorMessage( 'datatransclusion-missing-argument-key', $asHTML ); |
128 | | - } else { |
129 | | - $key = $argv[2]; |
| 148 | + // collect options |
| 149 | + $options = array(); |
| 150 | + $optionNames = $source->getOptionNames(); |
| 151 | + if ( $optionNames ) { |
| 152 | + foreach ( $optionNames as $n ) { |
| 153 | + if ( isset( $argv[ $n ] ) ) { |
| 154 | + $options[ $n ] = $argv[ $n ]; |
| 155 | + } |
130 | 156 | } |
131 | 157 | } |
132 | 158 | |
133 | | - // find out how to render the record |
134 | | - if ( empty( $argv['template'] ) ) { |
135 | | - if ( empty( $argv[3] ) ) { |
136 | | - wfDebugLog( 'DataTransclusion', "missing 'template' argument\n" ); |
137 | | - return DataTransclusionHandler::errorMessage( 'datatransclusion-missing-argument-template', $asHTML ); |
138 | | - } else { |
139 | | - $template = $argv[3]; |
140 | | - } |
141 | | - } else { |
142 | | - $template = $argv['template']; |
143 | | - } |
144 | | - |
145 | 159 | // load the record |
146 | | - $record = $source->fetchRecord( $by, $key ); |
| 160 | + $record = $source->fetchRecord( $by, $key, $options ); |
147 | 161 | if ( empty( $record ) ) { |
148 | 162 | wfDebugLog( 'DataTransclusion', "no record found matching $by=$key in $sourceName\n" ); |
149 | 163 | return DataTransclusionHandler::errorMessage( 'datatransclusion-record-not-found', $asHTML, $sourceName, $by, $key ); |
— | — | @@ -157,7 +171,7 @@ |
158 | 172 | |
159 | 173 | $handler = new DataTransclusionHandler( $parser, $source, $t, $templateText ); |
160 | 174 | |
161 | | - $record = $handler->normalizeRecord( $record ); |
| 175 | + $record = $handler->normalizeRecord( $record, $argv ); |
162 | 176 | $text = $handler->render( $record ); |
163 | 177 | |
164 | 178 | if ( $text === false ) { |
— | — | @@ -233,10 +247,32 @@ |
234 | 248 | return $text; |
235 | 249 | } |
236 | 250 | |
237 | | - function normalizeRecord( $record ) { |
| 251 | + function normalizeRecord( $record, $args ) { |
238 | 252 | $rec = array(); |
239 | 253 | |
240 | | - // keep record fields, add missing values |
| 254 | + // add source meta info, so we can render links back to the source, |
| 255 | + // provide license info, etc |
| 256 | + $info = $this->source->getSourceInfo(); |
| 257 | + foreach ( $info as $f => $v ) { |
| 258 | + if ( is_array( $v ) || is_object( $v ) || is_resource( $v ) ) { |
| 259 | + continue; |
| 260 | + } |
| 261 | + |
| 262 | + $rec[ $f ] = $this->sanitizeValue( $v ); |
| 263 | + } |
| 264 | + |
| 265 | + if ( $args ) { |
| 266 | + // add arguments |
| 267 | + foreach ( $args as $f => $v ) { |
| 268 | + if ( is_array( $v ) || is_object( $v ) || is_resource( $v ) ) { |
| 269 | + continue; |
| 270 | + } |
| 271 | + |
| 272 | + $rec[ $f ] = $this->sanitizeValue( $v ); |
| 273 | + } |
| 274 | + } |
| 275 | + |
| 276 | + // copy record fields, add missing values |
241 | 277 | $fields = $this->source->getFieldNames(); |
242 | 278 | foreach ( $fields as $f ) { |
243 | 279 | if ( isset( $record[ $f ] ) ) { |
— | — | @@ -248,17 +284,6 @@ |
249 | 285 | $rec[ $f ] = $this->sanitizeValue( $v ); |
250 | 286 | } |
251 | 287 | |
252 | | - // add source meta info, so we can render links back to the source, |
253 | | - // provide license info, etc |
254 | | - $info = $this->source->getSourceInfo(); |
255 | | - foreach ( $info as $f => $v ) { |
256 | | - if ( is_array( $v ) || is_object( $v ) || is_resource( $v ) ) { |
257 | | - continue; |
258 | | - } |
259 | | - |
260 | | - $rec[ "source.$f" ] = $this->sanitizeValue( $v ); |
261 | | - } |
262 | | - |
263 | 288 | return $rec; |
264 | 289 | } |
265 | 290 | |
— | — | @@ -315,7 +340,7 @@ |
316 | 341 | throw new MWException( "failed to instantiate \$wgDataTransclusionSources['$name'] as new $c." ); |
317 | 342 | } |
318 | 343 | |
319 | | - wfDebugLog( 'DataTransclusion', "created instance of $c as data-source \"$name\"\n" ); |
| 344 | + wfDebugLog( 'DataTransclusion', "created instance of $c as source \"$name\"\n" ); |
320 | 345 | $source = $obj; |
321 | 346 | |
322 | 347 | if ( isset( $spec[ 'cache' ] ) ) { // check if a cache should be used |
— | — | @@ -326,7 +351,7 @@ |
327 | 352 | |
328 | 353 | $source = new CachingDataTransclusionSource( $obj, $c, @$spec['cache-duration'] ); // apply caching wrapper |
329 | 354 | |
330 | | - wfDebugLog( 'DataTransclusion', "wrapped data-source \"$name\" in an instance of CachingDataTransclusionSource\n" ); |
| 355 | + wfDebugLog( 'DataTransclusion', "wrapped source \"$name\" in an instance of CachingDataTransclusionSource\n" ); |
331 | 356 | } |
332 | 357 | |
333 | 358 | $wgDataTransclusionSources[ $name ] = $source; // replace spec array by actual object, for later re-use |
Index: trunk/extensions/DataTransclusion/tests/DataTransclusionTest.php |
— | — | @@ -25,7 +25,7 @@ |
26 | 26 | |
27 | 27 | class DataTransclusionTest extends PHPUnit_Framework_TestCase { |
28 | 28 | protected static $templates = array( |
29 | | - 'Test' => "'''{{{id}}}'''|{{{name}}}|{{{info}}}|[{{{url}}} link]|[{{{evil}}} click me]", |
| 29 | + 'Test' => "{{{source-name}}}:'''{{{id}}}'''|{{{name}}}|{{{extra}}}|{{{info}}}|[{{{url}}} link]|[{{{evil}}} click me]", |
30 | 30 | ); |
31 | 31 | |
32 | 32 | static function getTemplate( $title, $parser ) { |
— | — | @@ -186,35 +186,31 @@ |
187 | 187 | $wgDataTransclusionSources[ 'FOO' ] = $spec; |
188 | 188 | |
189 | 189 | # failure mode: no source given |
190 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'foo' => 'bar' ), $wgParser, false ); |
| 190 | + $s = DataTransclusionHandler::handleRecordTransclusion( "Dummy", array( 'foo' => 'bar', 'id' => 3 ), $wgParser, false ); |
191 | 191 | $this->assertTrue( preg_match( '/class="error datatransclusion-missing-source"/', $s ) === 1 ); |
192 | 192 | |
193 | 193 | # failure mode: bad source given |
194 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => '*** nonsense ***', 'template' => 'Dummy' ), $wgParser, false ); |
| 194 | + $s = DataTransclusionHandler::handleRecordTransclusion( "Dummy", array( 'source' => '*** nonsense ***', 'id' => 3 ), $wgParser, false ); |
195 | 195 | $this->assertTrue( preg_match( '/class="error datatransclusion-unknown-source"/', $s ) === 1 ); |
196 | 196 | |
197 | 197 | # failure mode: bad source given (alternative) |
198 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 1 => '*** nonsense ***', 'template' => 'Dummy' ), $wgParser, false ); |
| 198 | + $s = DataTransclusionHandler::handleRecordTransclusion( "Dummy", array( 1 => '*** nonsense ***', 'id' => 3 ), $wgParser, false ); |
199 | 199 | $this->assertTrue( preg_match( '/class="error datatransclusion-unknown-source"/', $s ) === 1 ); |
200 | 200 | |
201 | | - # failure mode: illegal value for by= (must be a key field) |
202 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => 'FOO', 'by' => 'info', 'template' => 'Dummy' ), $wgParser, false ); |
203 | | - $this->assertTrue( preg_match( '/class="error datatransclusion-bad-argument-by"/', $s ) === 1 ); |
204 | | - |
205 | 201 | # failure mode: no key value specified |
206 | | - $s = DataTransclusionHandler::handleRecordTransclusion( null, array( 'source' => 'FOO', 'template' => 'Dummy' ), $wgParser, false ); |
207 | | - $this->assertTrue( preg_match( '/class="error datatransclusion-missing-argument-key"/', $s ) === 1 ); |
| 202 | + $s = DataTransclusionHandler::handleRecordTransclusion( "Dummy", array( 'source' => 'FOO' ), $wgParser, false ); |
| 203 | + $this->assertTrue( preg_match( '/class="error datatransclusion-missing-key"/', $s ) === 1 ); |
208 | 204 | |
209 | 205 | # failure mode: no template specified |
210 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => 'FOO' ), $wgParser, false ); |
| 206 | + $s = DataTransclusionHandler::handleRecordTransclusion( null, array( 'source' => 'FOO', 'id' => 3 ), $wgParser, false ); |
211 | 207 | $this->assertTrue( preg_match( '/class="error datatransclusion-missing-argument-template"/', $s ) === 1 ); |
212 | 208 | |
213 | 209 | # failure mode: illegal template specified |
214 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => 'FOO', 'template' => '#' ), $wgParser, false ); |
| 210 | + $s = DataTransclusionHandler::handleRecordTransclusion( "##", array( 'source' => 'FOO', 'id' => 3 ), $wgParser, false ); |
215 | 211 | $this->assertTrue( preg_match( '/class="error datatransclusion-bad-template-name"/', $s ) === 1 ); |
216 | 212 | |
217 | 213 | # failure mode: record can't be found for that key |
218 | | - $s = DataTransclusionHandler::handleRecordTransclusion( "xxxxxxxxxx", array( 'source' => 'FOO', 'template' => 'Dummy' ), $wgParser, false ); |
| 214 | + $s = DataTransclusionHandler::handleRecordTransclusion( "Dummy", array( 'source' => 'FOO', 'id' => 'xxxxxxxxxx' ), $wgParser, false ); |
219 | 215 | $this->assertTrue( preg_match( '/class="error datatransclusion-record-not-found"/', $s ) === 1 ); |
220 | 216 | |
221 | 217 | /* |
— | — | @@ -226,15 +222,15 @@ |
227 | 223 | |
228 | 224 | //////////////////////////////////////////////////////// |
229 | 225 | # success: render record |
230 | | - $res = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => 'FOO', 'template' => 'Test' ), $wgParser, false, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
| 226 | + $res = DataTransclusionHandler::handleRecordTransclusion( "Test", array( 'source' => 'FOO', 'id' => 3 ), $wgParser, false, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
231 | 227 | $this->assertEquals( $res, '\'\'\'3\'\'\'|foo|test&X' ); |
232 | 228 | |
233 | 229 | # success: render record (find by name) |
234 | | - $res = DataTransclusionHandler::handleRecordTransclusion( "foo", array( 'source' => 'FOO', 'template' => 'Test', 'by' => 'name' ), $wgParser, false, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
| 230 | + $res = DataTransclusionHandler::handleRecordTransclusion( "Test", array( 'source' => 'FOO', 'name' => 'foo'), $wgParser, false, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
235 | 231 | $this->assertEquals( $res, '\'\'\'3\'\'\'|foo|test&X' ); |
236 | 232 | |
237 | 233 | # success: render record (as HTML) |
238 | | - $res = DataTransclusionHandler::handleRecordTransclusion( "3", array( 'source' => 'FOO', 'template' => 'Test' ), $wgParser, true, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
| 234 | + $res = DataTransclusionHandler::handleRecordTransclusion( "Test", array( 'source' => 'FOO', 'id' => 3 ), $wgParser, true, "'''{{{id}}}'''|{{{name}}}|{{{info}}}" ); |
239 | 235 | $this->assertEquals( $res, '<b>3</b>|foo|test&X' ); // FIXME: & should have been escaped to & here, no? why not? |
240 | 236 | } |
241 | 237 | |
— | — | @@ -247,7 +243,7 @@ |
248 | 244 | 'data' => $data, |
249 | 245 | 'keyFields' => 'name,id', |
250 | 246 | 'fieldNames' => 'id,name,info,url,evil', |
251 | | - 'defaultKey' => 'id' |
| 247 | + 'defaultKey' => 'id', |
252 | 248 | ); |
253 | 249 | |
254 | 250 | $wgDataTransclusionSources[ 'FOO' ] = $spec; |
— | — | @@ -257,12 +253,11 @@ |
258 | 254 | $options = new ParserOptions(); |
259 | 255 | $options->setTemplateCallback( 'DataTransclusionTest::getTemplate' ); |
260 | 256 | |
261 | | - $text = 'xx {{#record:FOO|3|Test}} xx'; |
| 257 | + $text = 'xx {{#record:Test|FOO|id=3|extra=Hallo}} xx'; |
262 | 258 | $wgParser->parse( $text, $title, $options ); |
263 | 259 | |
264 | 260 | $html = $wgParser->getOutput()->getText(); |
265 | | - $this->assertEquals( $html, '<p>xx <b>3</b>|foo|<test>&[[X]]|<a href="http://test.org/" class="external text" rel="nofollow">link</a>|[javascript:alert("evil") click me] xx'."\n".'</p>' ); // XXX: should be more lenient wrt whitespace |
266 | | - |
| 261 | + $this->assertEquals( $html, '<p>xx FOO:<b>3</b>|foo|Hallo|<test>&[[X]]|<a href="http://test.org/" class="external text" rel="nofollow">link</a>|[javascript:alert("evil") click me] xx'."\n".'</p>' ); // XXX: should be more lenient wrt whitespace |
267 | 262 | $templates = $wgParser->getOutput()->getTemplates(); |
268 | 263 | $this->assertTrue( isset( $templates[ NS_TEMPLATE ]['Test'] ) ); |
269 | 264 | } |
— | — | @@ -286,11 +281,11 @@ |
287 | 282 | $options = new ParserOptions(); |
288 | 283 | $options->setTemplateCallback( 'DataTransclusionTest::getTemplate' ); |
289 | 284 | |
290 | | - $text = 'xx <record source=FOO template="Test">3</record> xx'; |
| 285 | + $text = 'xx <record source="FOO" id=3 extra="Hallo">Test</record> xx'; |
291 | 286 | $wgParser->parse( $text, $title, $options ); |
292 | 287 | |
293 | 288 | $html = $wgParser->getOutput()->getText(); |
294 | | - $this->assertEquals( $html, '<p>xx <b>3</b>|foo|<test>&[[X]]|<a href="http://test.org/" class="external text" rel="nofollow">link</a>|[javascript:alert("evil") click me] xx'."\n".'</p>' ); // XXX: should be more lenient wrt whitespace |
| 289 | + $this->assertEquals( $html, '<p>xx FOO:<b>3</b>|foo|Hallo|<test>&[[X]]|<a href="http://test.org/" class="external text" rel="nofollow">link</a>|[javascript:alert("evil") click me] xx'."\n".'</p>' ); // XXX: should be more lenient wrt whitespace |
295 | 290 | $templates = $wgParser->getOutput()->getTemplates(); |
296 | 291 | $this->assertTrue( isset( $templates[ NS_TEMPLATE ]['Test'] ) ); |
297 | 292 | } |
— | — | @@ -309,11 +304,13 @@ |
310 | 305 | |
311 | 306 | $handler = new DataTransclusionHandler( $wgParser, $source, null ); |
312 | 307 | |
313 | | - $rec = $handler->normalizeRecord( $rec ); |
| 308 | + $args = array( "name" => "cruft", "more" => "stuff" ); |
| 309 | + $rec = $handler->normalizeRecord( $rec, $args ); |
314 | 310 | |
315 | | - $this->assertEquals( $rec['source.name'], 'FOO' ); |
316 | | - $this->assertEquals( $rec['source.quux'], 'xyzzy' ); |
317 | | - $this->assertEquals( $rec['source.x'], 43 ); |
| 311 | + $this->assertEquals( $rec['source-name'], 'FOO' ); |
| 312 | + $this->assertEquals( $rec['quux'], 'xyzzy' ); |
| 313 | + $this->assertEquals( $rec['x'], 43 ); |
| 314 | + $this->assertEquals( $rec['more'], 'stuff' ); |
318 | 315 | $this->assertEquals( $rec['name'], 'foo' ); |
319 | 316 | $this->assertEquals( $rec['id'], '3' ); |
320 | 317 | $this->assertEquals( $rec['info'], '{{test}}=[[x]] 1&2 ' ); |
— | — | @@ -402,7 +399,8 @@ |
403 | 400 | $spec = array( |
404 | 401 | 'name' => 'FOO', |
405 | 402 | 'keyFields' => 'id,name', |
406 | | - 'url' => 'http://acme.com/', |
| 403 | + 'optionNames' => 'x,y', |
| 404 | + 'url' => 'http://acme.com/{name}', |
407 | 405 | 'dataFormat' => 'php', |
408 | 406 | 'dataPath' => 'response/content/@0', |
409 | 407 | 'valuePath' => 'value', |
— | — | @@ -412,8 +410,14 @@ |
413 | 411 | $source = new WebDataTransclusionSource( $spec ); |
414 | 412 | |
415 | 413 | $u = $source->getRecordURL( 'name', 'foo&bar' ); |
416 | | - $this->assertEquals( $u, 'http://acme.com/?name=foo%26bar' ); |
| 414 | + $this->assertEquals( $u, 'http://acme.com/foo%26bar' ); |
417 | 415 | |
| 416 | + $u = $source->getRecordURL( 'id', '23' ); |
| 417 | + $this->assertEquals( $u, 'http://acme.com/?id=23' ); |
| 418 | + |
| 419 | + $u = $source->getRecordURL( 'name', 'foo&bar', array( 'x' => '42', 'y' => 57 ) ); |
| 420 | + $this->assertEquals( $u, 'http://acme.com/foo%26bar?x=42&y=57' ); |
| 421 | + |
418 | 422 | $rec = array( |
419 | 423 | "name" => array( 'type' => 'string', 'value' => "foo" ), |
420 | 424 | "id" => array( 'type' => 'int', 'value' => 3 ), |
— | — | @@ -435,7 +439,7 @@ |
436 | 440 | $this->assertEquals( $rec['id'], 3 ); |
437 | 441 | |
438 | 442 | //////////////////////// |
439 | | - $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-{field}-{value}.pser'; |
| 443 | + $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-name-{name}.pser'; |
440 | 444 | $spec['dataFormat'] = 'php'; |
441 | 445 | $source = new WebDataTransclusionSource( $spec ); |
442 | 446 | |
— | — | @@ -443,7 +447,7 @@ |
444 | 448 | $this->assertEquals( $rec['id'], 3 ); |
445 | 449 | |
446 | 450 | //////////////////////// |
447 | | - $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-{field}-{value}.json'; |
| 451 | + $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-name-{name}.json'; |
448 | 452 | $spec['dataFormat'] = 'json'; |
449 | 453 | $source = new WebDataTransclusionSource( $spec ); |
450 | 454 | |
— | — | @@ -452,7 +456,7 @@ |
453 | 457 | |
454 | 458 | //////////////////////// |
455 | 459 | if ( function_exists( 'wddx_unserialize' ) ) { |
456 | | - $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-{field}-{value}.wddx'; |
| 460 | + $spec['url'] = 'file://' . dirname( realpath( __FILE__ ) ) . '/test-data-name-{name}.wddx'; |
457 | 461 | $spec['dataFormat'] = 'wddx'; |
458 | 462 | $source = new WebDataTransclusionSource( $spec ); |
459 | 463 | |
Index: trunk/extensions/DataTransclusion/WebDataTransclusionSource.php |
— | — | @@ -22,10 +22,10 @@ |
23 | 23 | * WebDataTransclusionSource accepts some additional options |
24 | 24 | * |
25 | 25 | * * $spec['url']: base URL for building urls for retrieving individual records. |
26 | | - * If the URL contains the placeholder {field} and/or {value}, these |
27 | | - * get replaced by the field name resp. the field value. |
28 | | - * Otherwise, the key/value pair is appended to the URL as a regular URL |
29 | | - * parameter (preceeded by ? or &, as appropriate). For more |
| 26 | + * If the URL contains placeholders of the form {xxx}, these get replaced |
| 27 | + * by the respective key or option values. |
| 28 | + * Otherwise, the key/value pair and options get appended to the URL as a |
| 29 | + * regular URL parameter (preceeded by ? or &, as appropriate). For more |
30 | 30 | * complex rules for building the url, override getRecordURL(). REQUIRED. |
31 | 31 | * * $spec['dataFormat']: Serialization format returned from the web service. |
32 | 32 | * Supported values are 'php' for PHP serialization format, 'json' |
— | — | @@ -80,8 +80,8 @@ |
81 | 81 | } |
82 | 82 | } |
83 | 83 | |
84 | | - public function fetchRecord( $field, $value ) { |
85 | | - $raw = $this->loadRecordData( $field, $value ); |
| 84 | + public function fetchRecord( $field, $value, $options = null ) { |
| 85 | + $raw = $this->loadRecordData( $field, $value, $options ); |
86 | 86 | if ( !$raw ) { |
87 | 87 | wfDebugLog( 'DataTransclusion', "failed to fetch data for $field=$value\n" ); |
88 | 88 | return false; |
— | — | @@ -109,29 +109,42 @@ |
110 | 110 | return $rec; |
111 | 111 | } |
112 | 112 | |
113 | | - public function getRecordURL( $field, $value ) { |
| 113 | + public function getRecordURL( $field, $value, $options = null ) { |
114 | 114 | $u = $this->url; |
115 | 115 | |
116 | | - if ( strpos( $u, '{field}' ) !== false || strpos( $u, '{value}' ) !== false ) { |
117 | | - $u = str_replace( '{field}', urlencode( $field ), $u ); |
118 | | - $u = str_replace( '{value}', urlencode( $value ), $u ); |
119 | | - } else { |
| 116 | + $args = array( $field => $value ); |
| 117 | + |
| 118 | + if ( $options ) { |
| 119 | + $args = array_merge( $options, $args ); |
| 120 | + } |
| 121 | + |
| 122 | + foreach ( $args as $k => $v ) { |
| 123 | + $u = str_replace( '{'.$k.'}', urlencode( $v ), $u, $n ); |
| 124 | + |
| 125 | + if ( $n ) { //was found and replaced |
| 126 | + unset( $args[ $k ] ); |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + $u = preg_replace( '/\{.*?\}/', '', $u ); //strip remaining placeholders |
| 131 | + |
| 132 | + foreach ( $args as $k => $v ) { |
120 | 133 | if ( strpos( $u, '?' ) === false ) { |
121 | 134 | $u .= '?'; |
122 | 135 | } else { |
123 | 136 | $u .= '&'; |
124 | 137 | } |
125 | 138 | |
126 | | - $u .= urlencode( $field ); |
| 139 | + $u .= urlencode( $k ); |
127 | 140 | $u .= '='; |
128 | | - $u .= urlencode( $value ); |
| 141 | + $u .= urlencode( $v ); |
129 | 142 | } |
130 | 143 | |
131 | 144 | return $u; |
132 | 145 | } |
133 | 146 | |
134 | | - public function loadRecordData( $field, $value ) { |
135 | | - $u = $this->getRecordURL( $field, $value ); |
| 147 | + public function loadRecordData( $field, $value, $options ) { |
| 148 | + $u = $this->getRecordURL( $field, $value, $options ); |
136 | 149 | return $this->loadRecordDataFromURL( $u ); |
137 | 150 | } |
138 | 151 | |
Index: trunk/extensions/DataTransclusion/DataTransclusionSource.php |
— | — | @@ -27,11 +27,11 @@ |
28 | 28 | * Set automatically by DataTransclusionHandler. REQUIRED. |
29 | 29 | * * $spec['keyFields']: list of fields that can be used as the key |
30 | 30 | * for fetching a record. REQUIRED. |
| 31 | + * * $spec['optionNames']: names of option that can be specified in addition |
| 32 | + * to a key, to refine the output. Optional. |
31 | 33 | * * $spec['fieldNames']: names of all fields present in each record. |
32 | 34 | * Fields not listed here will not be available on the wiki, |
33 | 35 | * even if they are returned by the data source. REQUIRED. |
34 | | - * * $spec['defaultKey']: default key to select records. If not specified, |
35 | | - * the first entry in $spec['keyFields'] is used. |
36 | 36 | * * $spec['cacheDuration']: the number of seconds a result from this source |
37 | 37 | * may be cached for. If not set, results are assumed to be cacheable |
38 | 38 | * indefinitely. This setting determines the expiry time of the parser |
— | — | @@ -41,12 +41,11 @@ |
42 | 42 | * the expiry time of ObjectCache entries for records from this source. |
43 | 43 | * * $spec['sourceInfo']: associative array of information about the data source |
44 | 44 | * that should be made available on the wiki. This information will be |
45 | | - * present in the record arrays, with they keys prefixed by "source.". |
| 45 | + * present in the record arrays as passed to the template. |
46 | 46 | * This is intended to allow information about source, license, etc to be |
47 | 47 | * shown on the wiki. Note that DataTransclusionSource implementations may |
48 | 48 | * provide extra information in the source info on their own: This base |
49 | | - * class forces $spec['sourceInfo']['name'] = $spec['name'] and |
50 | | - * $spec['sourceInfo']['defaultKey'] = $spec['defaultKey']. |
| 49 | + * class forces $spec['sourceInfo']['source-name'] = $spec['name']. |
51 | 50 | * |
52 | 51 | * Options used by DataTransclusionHandler but ignored by DataTransclusionSource: |
53 | 52 | * * $spec['class']: see documentation if $wgDataTransclusionSources in DataTransclusion. |
— | — | @@ -79,6 +78,7 @@ |
80 | 79 | wfDebugLog( 'DataTransclusion', "constructing " . get_class( $this ) . " \"{$this->name}\"\n" ); |
81 | 80 | |
82 | 81 | $this->keyFields = self::splitList( $spec[ 'keyFields' ] ); |
| 82 | + $this->optionNames = self::splitList( @$spec[ 'optionNames' ] ); |
83 | 83 | |
84 | 84 | if ( isset( $spec[ 'fieldNames' ] ) ) { |
85 | 85 | $this->fieldNames = self::splitList( $spec[ 'fieldNames' ] ); |
— | — | @@ -86,12 +86,6 @@ |
87 | 87 | $this->fieldNames = $this->keyFields; |
88 | 88 | } |
89 | 89 | |
90 | | - if ( !empty( $spec[ 'defaultKey' ] ) ) { |
91 | | - $this->defaultKey = $spec[ 'defaultKey' ]; |
92 | | - } else { |
93 | | - $this->defaultKey = $this->keyFields[ 0 ]; |
94 | | - } |
95 | | - |
96 | 90 | if ( !empty( $spec[ 'cacheDuration' ] ) ) { |
97 | 91 | $this->cacheDuration = (int)$spec[ 'cacheDuration' ]; |
98 | 92 | } else { |
— | — | @@ -106,18 +100,13 @@ |
107 | 101 | } |
108 | 102 | } |
109 | 103 | |
110 | | - $this->sourceInfo[ 'name' ] = $this->name; // force this one |
111 | | - $this->sourceInfo[ 'defaultKey' ] = $this->name; // force this one |
| 104 | + $this->sourceInfo[ 'source-name' ] = $this->name; // force this one |
112 | 105 | } |
113 | 106 | |
114 | 107 | public function getName() { |
115 | 108 | return $this->name; |
116 | 109 | } |
117 | 110 | |
118 | | - public function getDefaultKey() { |
119 | | - return $this->defaultKey; |
120 | | - } |
121 | | - |
122 | 111 | public function getSourceInfo() { |
123 | 112 | return $this->sourceInfo; |
124 | 113 | } |
— | — | @@ -126,6 +115,10 @@ |
127 | 116 | return $this->keyFields; |
128 | 117 | } |
129 | 118 | |
| 119 | + public function getOptionNames() { |
| 120 | + return $this->optionNames; |
| 121 | + } |
| 122 | + |
130 | 123 | public function getFieldNames() { |
131 | 124 | return $this->fieldNames; |
132 | 125 | } |
— | — | @@ -134,7 +127,7 @@ |
135 | 128 | return $this->cacheDuration; |
136 | 129 | } |
137 | 130 | |
138 | | - public function fetchRecord( $field, $value ) { |
| 131 | + public function fetchRecord( $field, $value, $options = null ) { |
139 | 132 | throw new MWException( "override fetchRecord()" ); |
140 | 133 | } |
141 | 134 | } |
— | — | @@ -162,10 +155,6 @@ |
163 | 156 | return $this->source->getName(); |
164 | 157 | } |
165 | 158 | |
166 | | - public function getDefaultTemplate() { |
167 | | - return $this->source->getDefaultTemplate(); |
168 | | - } |
169 | | - |
170 | 159 | public function getSourceInfo() { |
171 | 160 | return $this->source->getSourceInfo(); |
172 | 161 | } |
— | — | @@ -174,6 +163,10 @@ |
175 | 164 | return $this->source->getKeyFields(); |
176 | 165 | } |
177 | 166 | |
| 167 | + public function getOptionNames() { |
| 168 | + return $this->source->getOptionNames(); |
| 169 | + } |
| 170 | + |
178 | 171 | public function getFieldNames() { |
179 | 172 | return $this->source->getFieldNames(); |
180 | 173 | } |
— | — | @@ -182,16 +175,21 @@ |
183 | 176 | return $this->source->getCacheDuration(); |
184 | 177 | } |
185 | 178 | |
186 | | - public function fetchRecord( $field, $value ) { |
| 179 | + public function fetchRecord( $field, $value, $options = null ) { |
187 | 180 | global $wgDBname, $wgUser; |
188 | 181 | |
189 | | - $cacheKey = "$wgDBname:DataTransclusion(" . $this->getName() . ":$field=$value)"; |
| 182 | + $k = "$field=$value"; |
| 183 | + if ( $options ) { |
| 184 | + $k .= "&" . sha1( var_export( $options, false ) ); |
| 185 | + } |
| 186 | + |
| 187 | + $cacheKey = "$wgDBname:DataTransclusion(" . $this->getName() . ":$k)"; |
190 | 188 | |
191 | 189 | $rec = $this->cache->get( $cacheKey ); |
192 | 190 | |
193 | 191 | if ( !$rec ) { |
194 | 192 | wfDebugLog( 'DataTransclusion', "fetching fresh record for $field=$value\n" ); |
195 | | - $rec = $this->source->fetchRecord( $field, $value ); |
| 193 | + $rec = $this->source->fetchRecord( $field, $value, $options ); |
196 | 194 | |
197 | 195 | if ( $rec ) { // XXX: also cache negatives?? |
198 | 196 | $duration = $this->getCacheDuration(); |
— | — | @@ -249,7 +247,7 @@ |
250 | 248 | } |
251 | 249 | } |
252 | 250 | |
253 | | - public function fetchRecord( $field, $value ) { |
| 251 | + public function fetchRecord( $field, $value, $options = null ) { |
254 | 252 | return @$this->lookup[ $field ][ $value ]; |
255 | 253 | } |
256 | 254 | } |
Index: trunk/extensions/DataTransclusion/DBDataTransclusionSource.php |
— | — | @@ -35,7 +35,7 @@ |
36 | 36 | * * $spec['keyFields']: like for DataTransclusionSource, this is list of fields |
37 | 37 | * that can be used as the key for fetching a record. However, it's not required |
38 | 38 | * for DBDataTransclusionSource: if not provided, array_keys( $spec['keyTypes'] ) |
39 | | - * will be used. REQUIRED. |
| 39 | + * will be used. |
40 | 40 | * |
41 | 41 | * For more information on options supported by DataTransclusionSource, see the class-level |
42 | 42 | * documentation there. |
— | — | @@ -112,7 +112,7 @@ |
113 | 113 | return $sql; |
114 | 114 | } |
115 | 115 | |
116 | | - public function fetchRecord( $field, $value ) { |
| 116 | + public function fetchRecord( $field, $value, $options = null ) { |
117 | 117 | $db = wfGetDB( DB_SLAVE ); |
118 | 118 | |
119 | 119 | $sql = $this->getQuery( $field, $value, $db ); |