PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/extensions/ExternalData/ED_ParserFunctions.php

https://github.com/ChuguluGames/mediawiki-svn
PHP | 382 lines | 251 code | 33 blank | 98 comment | 56 complexity | 56d218cb50c3253503fd253939edc80c MD5 | raw file
  1. <?php
  2. /**
  3. * Class for handling the parser functions for External Data
  4. */
  5. if ( !defined( 'MEDIAWIKI' ) ) {
  6. die( 'This file is a MediaWiki extension; it is not a valid entry point' );
  7. }
  8. class EDParserFunctions {
  9. /**
  10. * Render the #get_external_data parser function
  11. * @deprecated
  12. */
  13. static function doGetExternalData( &$parser ) {
  14. global $wgTitle, $edgCurPageName, $edgValues;
  15. // if we're handling multiple pages, reset $edgValues
  16. // when we move from one page to another
  17. $cur_page_name = $wgTitle->getText();
  18. if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
  19. $edgValues = array();
  20. $edgCurPageName = $cur_page_name;
  21. }
  22. $params = func_get_args();
  23. array_shift( $params ); // we already know the $parser ...
  24. $url = array_shift( $params );
  25. $url = str_replace( ' ', '%20', $url ); // do some minor URL-encoding
  26. // if the URL isn't allowed (based on a whitelist), exit
  27. if ( ! EDUtils::isURLAllowed( $url ) ) {
  28. return;
  29. }
  30. $format = strtolower( array_shift( $params ) ); // make case-insensitive
  31. $external_values = EDUtils::getDataFromURL( $url, $format );
  32. if ( count( $external_values ) == 0 ) {
  33. return;
  34. }
  35. // Get set of filters and set of mappings, determining each
  36. // one by whether there's a double or single equals sign,
  37. // respectively.
  38. $filters = array();
  39. $mappings = array();
  40. foreach ( $params as $param ) {
  41. if ( strpos( $param, '==' ) ) {
  42. list( $external_var, $value ) = explode( '==', $param );
  43. // set to all lowercase to avoid casing issues
  44. $external_var = strtolower( $external_var );
  45. $filters[$external_var] = $value;
  46. } elseif ( strpos( $param, '=' ) ) {
  47. list( $local_var, $external_var ) = explode( '=', $param );
  48. // set to all lowercase to avoid casing issues
  49. $external_var = strtolower( $external_var );
  50. $mappings[$local_var] = $external_var;
  51. } else {
  52. // if the parameter contains no equals signs,
  53. // do nothing
  54. }
  55. }
  56. self::setGlobalValuesArray( $external_values, $filters, $mappings );
  57. }
  58. /**
  59. * A helper function, since it's called by both doGetExternalData()
  60. * and doGetWebData() - the former is deprecated.
  61. */
  62. static public function setGlobalValuesArray( $external_values, $filters, $mappings ) {
  63. global $edgValues;
  64. foreach ( $filters as $filter_var => $filter_value ) {
  65. // Find the entry of $external_values that matches
  66. // the filter variable; if none exists, just ignore
  67. // the filter.
  68. if ( array_key_exists( $filter_var, $external_values ) ) {
  69. if ( is_array( $external_values[$filter_var] ) ) {
  70. $column_values = $external_values[$filter_var];
  71. foreach ( $column_values as $i => $single_value ) {
  72. // if a value doesn't match
  73. // the filter value, remove
  74. // the value from this row for
  75. // all columns
  76. if ( trim( $single_value ) != trim( $filter_value ) ) {
  77. foreach ( $external_values as $external_var => $external_value ) {
  78. unset( $external_values[$external_var][$i] );
  79. }
  80. }
  81. }
  82. } else {
  83. // if we have only one row of values,
  84. // and the filter doesn't match, just
  85. // keep the results array blank and
  86. // return
  87. if ( $external_values[$filter_var] != $filter_value ) {
  88. return;
  89. }
  90. }
  91. }
  92. }
  93. // for each external variable name specified in the function
  94. // call, get its value or values (if any exist), and attach it
  95. // or them to the local variable name
  96. foreach ( $mappings as $local_var => $external_var ) {
  97. if ( array_key_exists( $external_var, $external_values ) ) {
  98. if ( is_array( $external_values[$external_var] ) )
  99. // array_values() restores regular
  100. // 1, 2, 3 indexes to array, after unset()
  101. // in filtering may have removed some
  102. $edgValues[$local_var] = array_values( $external_values[$external_var] );
  103. else
  104. $edgValues[$local_var][] = $external_values[$external_var];
  105. }
  106. }
  107. }
  108. /**
  109. * Render the #get_web_data parser function
  110. */
  111. static function doGetWebData( &$parser ) {
  112. global $wgTitle, $edgCurPageName, $edgValues;
  113. // If we're handling multiple pages, reset $edgValues
  114. // when we move from one page to another.
  115. $cur_page_name = $wgTitle->getText();
  116. if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
  117. $edgValues = array();
  118. $edgCurPageName = $cur_page_name;
  119. }
  120. $params = func_get_args();
  121. array_shift( $params ); // we already know the $parser ...
  122. $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
  123. if ( array_key_exists( 'url', $args ) ) {
  124. $url = $args['url'];
  125. } else {
  126. return;
  127. }
  128. $url = str_replace( ' ', '%20', $url ); // do some minor URL-encoding
  129. // if the URL isn't allowed (based on a whitelist), exit
  130. if ( ! EDUtils::isURLAllowed( $url ) ) {
  131. return;
  132. }
  133. if ( array_key_exists( 'format', $args ) ) {
  134. $format = strtolower( $args['format'] );
  135. } else {
  136. $format = '';
  137. }
  138. $external_values = EDUtils::getDataFromURL( $url, $format );
  139. if ( count( $external_values ) == 0 ) {
  140. return;
  141. }
  142. if ( array_key_exists( 'data', $args ) ) {
  143. // parse the 'data' arg into mappings
  144. $mappings = EDUtils::paramToArray( $args['data'], false, true );
  145. } else {
  146. return;
  147. }
  148. if ( array_key_exists( 'filters', $args ) ) {
  149. // parse the 'filters' arg
  150. $filters = EDUtils::paramToArray( $args['filters'], true, false );
  151. } else {
  152. $filters = array();
  153. }
  154. self::setGlobalValuesArray( $external_values, $filters, $mappings );
  155. }
  156. /**
  157. * Render the #get_ldap_data parser function
  158. */
  159. static function doGetLDAPData( &$parser ) {
  160. global $wgTitle, $edgCurPageName, $edgValues;
  161. // if we're handling multiple pages, reset $edgValues
  162. // when we move from one page to another
  163. $cur_page_name = $wgTitle->getText();
  164. if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
  165. $edgValues = array();
  166. $edgCurPageName = $cur_page_name;
  167. }
  168. $params = func_get_args();
  169. array_shift( $params ); // we already know the $parser ...
  170. $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
  171. $mappings = EDUtils::paramToArray( $args['data'] ); // parse the data arg into mappings
  172. $external_values = EDUtils::getLDAPData( $args['filter'], $args['domain'], array_values( $mappings ) );
  173. // Build $edgValues
  174. foreach ( $mappings as $local_var => $external_var ) {
  175. $edgValues[$local_var][] = $external_values[0][$external_var][0];
  176. }
  177. return;
  178. }
  179. /**
  180. * Render the #get_db_data parser function
  181. */
  182. static function doGetDBData( &$parser ) {
  183. global $wgTitle, $edgCurPageName, $edgValues;
  184. // if we're handling multiple pages, reset $edgValues
  185. // when we move from one page to another
  186. $cur_page_name = $wgTitle->getText();
  187. if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
  188. $edgValues = array();
  189. $edgCurPageName = $cur_page_name;
  190. }
  191. $params = func_get_args();
  192. array_shift( $params ); // we already know the $parser ...
  193. $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
  194. $data = ( array_key_exists( 'data', $args ) ) ? $args['data'] : null;
  195. $dbID = ( array_key_exists( 'db', $args ) ) ? $args['db'] : null;
  196. // For backwards-compatibility - 'db' parameter was added
  197. // in External Data version 1.3.
  198. if ( is_null( $dbID ) ) {
  199. $dbID = ( array_key_exists( 'server', $args ) ) ? $args['server'] : null;
  200. }
  201. $table = ( array_key_exists( 'from', $args ) ) ? $args['from'] : null;
  202. $conds = ( array_key_exists( 'where', $args ) ) ? $args['where'] : null;
  203. $limit = ( array_key_exists( 'limit', $args ) ) ? $args['limit'] : null;
  204. $orderBy = ( array_key_exists( 'order by', $args ) ) ? $args['order by'] : null;
  205. $options = array( 'LIMIT' => $limit, 'ORDER BY' => $orderBy );
  206. $mappings = EDUtils::paramToArray( $data ); // parse the data arg into mappings
  207. $external_values = EDUtils::getDBData( $dbID, $table, array_values( $mappings ), $conds, $options );
  208. // handle error cases
  209. if ( is_null( $external_values ) )
  210. return;
  211. // Build $edgValues
  212. foreach ( $mappings as $local_var => $external_var ) {
  213. if ( array_key_exists( $external_var, $external_values ) ) {
  214. foreach ( $external_values[$external_var] as $value ) {
  215. $edgValues[$local_var][] = $value;
  216. }
  217. }
  218. }
  219. return;
  220. }
  221. /**
  222. * Get the specified index of the array for the specified local
  223. * variable retrieved by #get_external_data
  224. */
  225. static function getIndexedValue( $var, $i ) {
  226. global $edgValues;
  227. if ( array_key_exists( $var, $edgValues ) && count( $edgValues[$var] > $i ) )
  228. return $edgValues[$var][$i];
  229. else
  230. return '';
  231. }
  232. /**
  233. * Render the #external_value parser function
  234. */
  235. static function doExternalValue( &$parser, $local_var = '' ) {
  236. global $edgValues;
  237. if ( ! array_key_exists( $local_var, $edgValues ) )
  238. return '';
  239. elseif ( is_array( $edgValues[$local_var] ) )
  240. return $edgValues[$local_var][0];
  241. else
  242. return $edgValues[$local_var];
  243. }
  244. /**
  245. * Render the #for_external_table parser function
  246. */
  247. static function doForExternalTable( &$parser, $expression = '' ) {
  248. global $edgValues;
  249. // get the variables used in this expression, get the number
  250. // of values for each, and loop through
  251. $matches = array();
  252. preg_match_all( '/{{{([^}]*)}}}/', $expression, $matches );
  253. $variables = $matches[1];
  254. $num_loops = 0;
  255. foreach ( $variables as $variable ) {
  256. // ignore the presence of '.urlencode' - it's a command,
  257. // not part of the actual variable name
  258. $variable = str_replace( '.urlencode', '', $variable );
  259. if ( array_key_exists( $variable, $edgValues ) ) {
  260. $num_loops = max( $num_loops, count( $edgValues[$variable] ) );
  261. }
  262. }
  263. $text = "";
  264. for ( $i = 0; $i < $num_loops; $i++ ) {
  265. $cur_expression = $expression;
  266. foreach ( $variables as $variable ) {
  267. // if variable name ends with a ".urlencode",
  268. // that's a command - URL-encode the value of
  269. // the actual variable
  270. $loc_of_urlencode = strrpos( $variable, '.urlencode' );
  271. if ( ( $loc_of_urlencode > 0 ) && ( $loc_of_urlencode == strlen( $variable ) - strlen( '.urlencode' ) ) ) {
  272. $real_var = str_replace( '.urlencode', '', $variable );
  273. $value = urlencode( self::getIndexedValue( $real_var , $i ) );
  274. } else {
  275. $value = self::getIndexedValue( $variable , $i );
  276. }
  277. $cur_expression = str_replace( '{{{' . $variable . '}}}', $value, $cur_expression );
  278. }
  279. $text .= $cur_expression;
  280. }
  281. return $text;
  282. }
  283. /**
  284. * Render the #store_external_table parser function
  285. */
  286. static function doStoreExternalTable( &$parser ) {
  287. if ( ! class_exists( 'SIOHandler' ) ) {
  288. return 'Semantic Internal Objects is not installed';
  289. }
  290. global $edgValues;
  291. $params = func_get_args();
  292. array_shift( $params ); // we already know the $parser...
  293. // get the variables used in this expression, get the number
  294. // of values for each, and loop through
  295. $expression = implode( '|', $params );
  296. $matches = array();
  297. preg_match_all( '/{{{([^}]*)}}}/', $expression, $matches );
  298. $variables = $matches[1];
  299. $num_loops = 0;
  300. foreach ( $variables as $variable ) {
  301. // ignore the presence of '.urlencode' - it's a command,
  302. // not part of the actual variable name
  303. $variable = str_replace( '.urlencode', '', $variable );
  304. if ( array_key_exists( $variable, $edgValues ) ) {
  305. $num_loops = max( $num_loops, count( $edgValues[$variable] ) );
  306. }
  307. }
  308. $text = "";
  309. for ( $i = 0; $i < $num_loops; $i++ ) {
  310. // re-get $params
  311. $params = func_get_args();
  312. array_shift( $params );
  313. foreach ( $params as $j => $param ) {
  314. foreach ( $variables as $variable ) {
  315. // if variable name ends with a ".urlencode",
  316. // that's a command - URL-encode the value of
  317. // the actual variable
  318. if ( strrpos( $variable, '.urlencode' ) == strlen( $variable ) - strlen( '.urlencode' ) ) {
  319. $real_var = str_replace( '.urlencode', '', $variable );
  320. $value = urlencode( self::getIndexedValue( $real_var , $i ) );
  321. } else {
  322. $value = self::getIndexedValue( $variable , $i );
  323. }
  324. $params[$j] = str_replace( '{{{' . $variable . '}}}', $value, $params[$j] );
  325. }
  326. }
  327. // Add $parser to the beginning of the $params array,
  328. // and pass the whole thing in as arguments to
  329. // doSetInternal, to mimic a call to #set_internal.
  330. array_unshift( $params, $parser );
  331. // As of PHP 5.3.1, call_user_func_array() requires that
  332. // the function params be references. Workaround via
  333. // http://stackoverflow.com/questions/2045875/pass-by-reference-problem-with-php-5-3-1
  334. $refParams = array();
  335. foreach ( $params as $key => $value ) {
  336. $refParams[$key] = &$params[$key];
  337. }
  338. call_user_func_array( array( 'SIOHandler', 'doSetInternal' ), $refParams );
  339. }
  340. return null;
  341. }
  342. /**
  343. * Render the #clear_external_data parser function
  344. */
  345. static function doClearExternalData( &$parser ) {
  346. global $edgValues;
  347. $edgValues = array();
  348. }
  349. }