/extensions/ExternalData/ED_ParserFunctions.php
PHP | 382 lines | 251 code | 33 blank | 98 comment | 56 complexity | 56d218cb50c3253503fd253939edc80c MD5 | raw file
- <?php
- /**
- * Class for handling the parser functions for External Data
- */
-
- if ( !defined( 'MEDIAWIKI' ) ) {
- die( 'This file is a MediaWiki extension; it is not a valid entry point' );
- }
- class EDParserFunctions {
-
- /**
- * Render the #get_external_data parser function
- * @deprecated
- */
- static function doGetExternalData( &$parser ) {
- global $wgTitle, $edgCurPageName, $edgValues;
- // if we're handling multiple pages, reset $edgValues
- // when we move from one page to another
- $cur_page_name = $wgTitle->getText();
- if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
- $edgValues = array();
- $edgCurPageName = $cur_page_name;
- }
- $params = func_get_args();
- array_shift( $params ); // we already know the $parser ...
- $url = array_shift( $params );
- $url = str_replace( ' ', '%20', $url ); // do some minor URL-encoding
- // if the URL isn't allowed (based on a whitelist), exit
- if ( ! EDUtils::isURLAllowed( $url ) ) {
- return;
- }
- $format = strtolower( array_shift( $params ) ); // make case-insensitive
- $external_values = EDUtils::getDataFromURL( $url, $format );
- if ( count( $external_values ) == 0 ) {
- return;
- }
- // Get set of filters and set of mappings, determining each
- // one by whether there's a double or single equals sign,
- // respectively.
- $filters = array();
- $mappings = array();
- foreach ( $params as $param ) {
- if ( strpos( $param, '==' ) ) {
- list( $external_var, $value ) = explode( '==', $param );
- // set to all lowercase to avoid casing issues
- $external_var = strtolower( $external_var );
- $filters[$external_var] = $value;
- } elseif ( strpos( $param, '=' ) ) {
- list( $local_var, $external_var ) = explode( '=', $param );
- // set to all lowercase to avoid casing issues
- $external_var = strtolower( $external_var );
- $mappings[$local_var] = $external_var;
- } else {
- // if the parameter contains no equals signs,
- // do nothing
- }
- }
- self::setGlobalValuesArray( $external_values, $filters, $mappings );
- }
- /**
- * A helper function, since it's called by both doGetExternalData()
- * and doGetWebData() - the former is deprecated.
- */
- static public function setGlobalValuesArray( $external_values, $filters, $mappings ) {
- global $edgValues;
- foreach ( $filters as $filter_var => $filter_value ) {
- // Find the entry of $external_values that matches
- // the filter variable; if none exists, just ignore
- // the filter.
- if ( array_key_exists( $filter_var, $external_values ) ) {
- if ( is_array( $external_values[$filter_var] ) ) {
- $column_values = $external_values[$filter_var];
- foreach ( $column_values as $i => $single_value ) {
- // if a value doesn't match
- // the filter value, remove
- // the value from this row for
- // all columns
- if ( trim( $single_value ) != trim( $filter_value ) ) {
- foreach ( $external_values as $external_var => $external_value ) {
- unset( $external_values[$external_var][$i] );
- }
- }
- }
- } else {
- // if we have only one row of values,
- // and the filter doesn't match, just
- // keep the results array blank and
- // return
- if ( $external_values[$filter_var] != $filter_value ) {
- return;
- }
- }
- }
- }
- // for each external variable name specified in the function
- // call, get its value or values (if any exist), and attach it
- // or them to the local variable name
- foreach ( $mappings as $local_var => $external_var ) {
- if ( array_key_exists( $external_var, $external_values ) ) {
- if ( is_array( $external_values[$external_var] ) )
- // array_values() restores regular
- // 1, 2, 3 indexes to array, after unset()
- // in filtering may have removed some
- $edgValues[$local_var] = array_values( $external_values[$external_var] );
- else
- $edgValues[$local_var][] = $external_values[$external_var];
- }
- }
- }
- /**
- * Render the #get_web_data parser function
- */
- static function doGetWebData( &$parser ) {
- global $wgTitle, $edgCurPageName, $edgValues;
- // If we're handling multiple pages, reset $edgValues
- // when we move from one page to another.
- $cur_page_name = $wgTitle->getText();
- if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
- $edgValues = array();
- $edgCurPageName = $cur_page_name;
- }
- $params = func_get_args();
- array_shift( $params ); // we already know the $parser ...
- $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
- if ( array_key_exists( 'url', $args ) ) {
- $url = $args['url'];
- } else {
- return;
- }
- $url = str_replace( ' ', '%20', $url ); // do some minor URL-encoding
- // if the URL isn't allowed (based on a whitelist), exit
- if ( ! EDUtils::isURLAllowed( $url ) ) {
- return;
- }
- if ( array_key_exists( 'format', $args ) ) {
- $format = strtolower( $args['format'] );
- } else {
- $format = '';
- }
- $external_values = EDUtils::getDataFromURL( $url, $format );
- if ( count( $external_values ) == 0 ) {
- return;
- }
- if ( array_key_exists( 'data', $args ) ) {
- // parse the 'data' arg into mappings
- $mappings = EDUtils::paramToArray( $args['data'], false, true );
- } else {
- return;
- }
- if ( array_key_exists( 'filters', $args ) ) {
- // parse the 'filters' arg
- $filters = EDUtils::paramToArray( $args['filters'], true, false );
- } else {
- $filters = array();
- }
- self::setGlobalValuesArray( $external_values, $filters, $mappings );
- }
- /**
- * Render the #get_ldap_data parser function
- */
- static function doGetLDAPData( &$parser ) {
- global $wgTitle, $edgCurPageName, $edgValues;
- // if we're handling multiple pages, reset $edgValues
- // when we move from one page to another
- $cur_page_name = $wgTitle->getText();
- if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
- $edgValues = array();
- $edgCurPageName = $cur_page_name;
- }
- $params = func_get_args();
- array_shift( $params ); // we already know the $parser ...
- $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
- $mappings = EDUtils::paramToArray( $args['data'] ); // parse the data arg into mappings
- $external_values = EDUtils::getLDAPData( $args['filter'], $args['domain'], array_values( $mappings ) );
- // Build $edgValues
- foreach ( $mappings as $local_var => $external_var ) {
- $edgValues[$local_var][] = $external_values[0][$external_var][0];
- }
- return;
- }
- /**
- * Render the #get_db_data parser function
- */
- static function doGetDBData( &$parser ) {
- global $wgTitle, $edgCurPageName, $edgValues;
- // if we're handling multiple pages, reset $edgValues
- // when we move from one page to another
- $cur_page_name = $wgTitle->getText();
- if ( ! isset( $edgCurPageName ) || $edgCurPageName != $cur_page_name ) {
- $edgValues = array();
- $edgCurPageName = $cur_page_name;
- }
- $params = func_get_args();
- array_shift( $params ); // we already know the $parser ...
- $args = EDUtils::parseParams( $params ); // parse params into name-value pairs
- $data = ( array_key_exists( 'data', $args ) ) ? $args['data'] : null;
- $dbID = ( array_key_exists( 'db', $args ) ) ? $args['db'] : null;
- // For backwards-compatibility - 'db' parameter was added
- // in External Data version 1.3.
- if ( is_null( $dbID ) ) {
- $dbID = ( array_key_exists( 'server', $args ) ) ? $args['server'] : null;
- }
- $table = ( array_key_exists( 'from', $args ) ) ? $args['from'] : null;
- $conds = ( array_key_exists( 'where', $args ) ) ? $args['where'] : null;
- $limit = ( array_key_exists( 'limit', $args ) ) ? $args['limit'] : null;
- $orderBy = ( array_key_exists( 'order by', $args ) ) ? $args['order by'] : null;
- $options = array( 'LIMIT' => $limit, 'ORDER BY' => $orderBy );
- $mappings = EDUtils::paramToArray( $data ); // parse the data arg into mappings
- $external_values = EDUtils::getDBData( $dbID, $table, array_values( $mappings ), $conds, $options );
- // handle error cases
- if ( is_null( $external_values ) )
- return;
- // Build $edgValues
- foreach ( $mappings as $local_var => $external_var ) {
- if ( array_key_exists( $external_var, $external_values ) ) {
- foreach ( $external_values[$external_var] as $value ) {
- $edgValues[$local_var][] = $value;
- }
- }
- }
- return;
- }
- /**
- * Get the specified index of the array for the specified local
- * variable retrieved by #get_external_data
- */
- static function getIndexedValue( $var, $i ) {
- global $edgValues;
- if ( array_key_exists( $var, $edgValues ) && count( $edgValues[$var] > $i ) )
- return $edgValues[$var][$i];
- else
- return '';
- }
-
- /**
- * Render the #external_value parser function
- */
- static function doExternalValue( &$parser, $local_var = '' ) {
- global $edgValues;
- if ( ! array_key_exists( $local_var, $edgValues ) )
- return '';
- elseif ( is_array( $edgValues[$local_var] ) )
- return $edgValues[$local_var][0];
- else
- return $edgValues[$local_var];
- }
-
- /**
- * Render the #for_external_table parser function
- */
- static function doForExternalTable( &$parser, $expression = '' ) {
- global $edgValues;
- // get the variables used in this expression, get the number
- // of values for each, and loop through
- $matches = array();
- preg_match_all( '/{{{([^}]*)}}}/', $expression, $matches );
- $variables = $matches[1];
- $num_loops = 0;
- foreach ( $variables as $variable ) {
- // ignore the presence of '.urlencode' - it's a command,
- // not part of the actual variable name
- $variable = str_replace( '.urlencode', '', $variable );
- if ( array_key_exists( $variable, $edgValues ) ) {
- $num_loops = max( $num_loops, count( $edgValues[$variable] ) );
- }
- }
- $text = "";
- for ( $i = 0; $i < $num_loops; $i++ ) {
- $cur_expression = $expression;
- foreach ( $variables as $variable ) {
- // if variable name ends with a ".urlencode",
- // that's a command - URL-encode the value of
- // the actual variable
- $loc_of_urlencode = strrpos( $variable, '.urlencode' );
- if ( ( $loc_of_urlencode > 0 ) && ( $loc_of_urlencode == strlen( $variable ) - strlen( '.urlencode' ) ) ) {
- $real_var = str_replace( '.urlencode', '', $variable );
- $value = urlencode( self::getIndexedValue( $real_var , $i ) );
- } else {
- $value = self::getIndexedValue( $variable , $i );
- }
- $cur_expression = str_replace( '{{{' . $variable . '}}}', $value, $cur_expression );
- }
- $text .= $cur_expression;
- }
- return $text;
- }
-
- /**
- * Render the #store_external_table parser function
- */
- static function doStoreExternalTable( &$parser ) {
- if ( ! class_exists( 'SIOHandler' ) ) {
- return 'Semantic Internal Objects is not installed';
- }
- global $edgValues;
- $params = func_get_args();
- array_shift( $params ); // we already know the $parser...
- // get the variables used in this expression, get the number
- // of values for each, and loop through
- $expression = implode( '|', $params );
- $matches = array();
- preg_match_all( '/{{{([^}]*)}}}/', $expression, $matches );
- $variables = $matches[1];
- $num_loops = 0;
- foreach ( $variables as $variable ) {
- // ignore the presence of '.urlencode' - it's a command,
- // not part of the actual variable name
- $variable = str_replace( '.urlencode', '', $variable );
- if ( array_key_exists( $variable, $edgValues ) ) {
- $num_loops = max( $num_loops, count( $edgValues[$variable] ) );
- }
- }
- $text = "";
- for ( $i = 0; $i < $num_loops; $i++ ) {
- // re-get $params
- $params = func_get_args();
- array_shift( $params );
- foreach ( $params as $j => $param ) {
- foreach ( $variables as $variable ) {
- // if variable name ends with a ".urlencode",
- // that's a command - URL-encode the value of
- // the actual variable
- if ( strrpos( $variable, '.urlencode' ) == strlen( $variable ) - strlen( '.urlencode' ) ) {
- $real_var = str_replace( '.urlencode', '', $variable );
- $value = urlencode( self::getIndexedValue( $real_var , $i ) );
- } else {
- $value = self::getIndexedValue( $variable , $i );
- }
- $params[$j] = str_replace( '{{{' . $variable . '}}}', $value, $params[$j] );
- }
- }
- // Add $parser to the beginning of the $params array,
- // and pass the whole thing in as arguments to
- // doSetInternal, to mimic a call to #set_internal.
- array_unshift( $params, $parser );
- // As of PHP 5.3.1, call_user_func_array() requires that
- // the function params be references. Workaround via
- // http://stackoverflow.com/questions/2045875/pass-by-reference-problem-with-php-5-3-1
- $refParams = array();
- foreach ( $params as $key => $value ) {
- $refParams[$key] = &$params[$key];
- }
- call_user_func_array( array( 'SIOHandler', 'doSetInternal' ), $refParams );
- }
- return null;
- }
- /**
- * Render the #clear_external_data parser function
- */
- static function doClearExternalData( &$parser ) {
- global $edgValues;
- $edgValues = array();
- }
- }