From 8761fef62357f1296438cb7216ca893eace5e7f0 Mon Sep 17 00:00:00 2001 From: Sam Reed Date: Sun, 31 Jan 2010 21:21:46 +0000 Subject: [PATCH] Stylize.php on API --- includes/api/ApiDelete.php | 2 +- includes/api/ApiFormatYaml_spyc.php | 1149 +++++++++++++++++++++----- includes/api/ApiQueryBacklinks.php | 5 +- includes/api/ApiQueryDeletedrevs.php | 2 +- includes/api/ApiQueryWatchlist.php | 2 +- 5 files changed, 957 insertions(+), 203 deletions(-) diff --git a/includes/api/ApiDelete.php b/includes/api/ApiDelete.php index a539928155..5efdcfcbd6 100644 --- a/includes/api/ApiDelete.php +++ b/includes/api/ApiDelete.php @@ -80,7 +80,7 @@ class ApiDelete extends ApiBase { if ( count( $retval ) ) $this->dieUsageMsg( reset( $retval ) ); // We don't care about multiple errors, just report one of them - + if ( $params['watch'] || $wgUser->getOption( 'watchdeletion' ) ) $articleObj->doWatch(); else if ( $params['unwatch'] ) diff --git a/includes/api/ApiFormatYaml_spyc.php b/includes/api/ApiFormatYaml_spyc.php index 30f860dd4a..67c84857c3 100644 --- a/includes/api/ApiFormatYaml_spyc.php +++ b/includes/api/ApiFormatYaml_spyc.php @@ -1,182 +1,279 @@ - * @see http://spyc.sourceforge.net/ - * @copyright Copyright 2005-2006 Chris Wanstrath - * @license http://www.opensource.org/licenses/mit-license.php MIT License - */ + * Spyc -- A Simple PHP YAML Class + * @version 0.4.5 + * @author Vlad Andersen + * @author Chris Wanstrath + * @link http://code.google.com/p/spyc/ + * @copyright Copyright 2005-2006 Chris Wanstrath, 2006-2009 Vlad Andersen + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * @package Spyc + */ +/** + * The Simple PHP YAML Class. + * + * This class can be used to read a YAML file and convert its contents + * into a PHP array. It currently supports a very limited subsection of + * the YAML spec. + */ +class Spyc { + + // SETTINGS + + /** + * Setting this to true will force YAMLDump to enclose any string value in + * quotes. False by default. + * + * @var bool + */ + public $setting_dump_force_quotes = false; + + /** + * Setting this to true will forse YAMLLoad to use syck_load function when + * possible. False by default. + * @var bool + */ + public $setting_use_syck_is_possible = false; + + + + /**#@+ + * @access private + * @var mixed + */ + private $_dumpIndent; + private $_dumpWordWrap; + private $_containsGroupAnchor = false; + private $_containsGroupAlias = false; + private $path; + private $result; + private $LiteralPlaceHolder = '___YAML_Literal_Block___'; + private $SavedGroups = array(); + private $indent; + /** + * Path modifier that should be applied after adding current element. + * @var array + */ + private $delayedPath = array(); + + /**#@+ + * @access public + * @var mixed + */ + public $_nodeId; /** - * The Simple PHP YAML Class. - * - * This class can be used to read a YAML file and convert its contents - * into a PHP array. It currently supports a very limited subsection of - * the YAML spec. - * - * @ingroup API + * Load a valid YAML string to Spyc. + * @param string $input + * @return array */ -class Spyc { + public function load ( $input ) { + return $this->__loadString( $input ); + } - /** - * Dump YAML from PHP array statically - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as nothing.yml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @return string - * @param $array Array: PHP array - * @param $indent Integer: Pass in false to use the default, which is 2 - * @param $wordwrap Integer: Pass in 0 for no wordwrap, false for default (40) - */ - public static function YAMLDump( $array, $indent = false, $wordwrap = false ) { - $spyc = new Spyc; - return $spyc->dump( $array, $indent, $wordwrap ); - } + /** + * Load a valid YAML file to Spyc. + * @param string $file + * @return array + */ + public function loadFile ( $file ) { + return $this->__load( $file ); + } - /** - * Dump PHP array to YAML - * - * The dump method, when supplied with an array, will do its best - * to convert the array into friendly YAML. Pretty simple. Feel free to - * save the returned string as tasteful.yml and pass it around. - * - * Oh, and you can decide how big the indent is and what the wordwrap - * for folding is. Pretty cool -- just pass in 'false' for either if - * you want to use the default. - * - * Indent's default is 2 spaces, wordwrap's default is 40 characters. And - * you can turn off wordwrap by passing in 0. - * - * @public - * @return string - * @param $array Array: PHP array - * @param $indent Integer: Pass in false to use the default, which is 2 - * @param $wordwrap Integer: Pass in 0 for no wordwrap, false for default (40) - */ - function dump( $array, $indent = false, $wordwrap = false ) { - // Dumps to some very clean YAML. We'll have to add some more features - // and options soon. And better support for folding. - - // New features and options. - if ( $indent === false or !is_numeric( $indent ) ) { - $this->_dumpIndent = 2; - } else { - $this->_dumpIndent = $indent; - } + /** + * Load YAML into a PHP array statically + * + * The load method, when supplied with a YAML stream (string or file), + * will do its best to convert YAML in a file into a PHP array. Pretty + * simple. + * Usage: + * + * $array = Spyc::YAMLLoad('lucky.yaml'); + * print_r($array); + * + * @access public + * @return array + * @param string $input Path of YAML file or string containing YAML + */ + public static function YAMLLoad( $input ) { + $Spyc = new Spyc; + return $Spyc->__load( $input ); + } - if ( $wordwrap === false or !is_numeric( $wordwrap ) ) { - $this->_dumpWordWrap = 40; - } else { - $this->_dumpWordWrap = $wordwrap; - } + /** + * Load a string of YAML into a PHP array statically + * + * The load method, when supplied with a YAML string, will do its best + * to convert YAML in a string into a PHP array. Pretty simple. + * + * Note: use this function if you don't want files from the file system + * loaded and processed as YAML. This is of interest to people concerned + * about security whose input is from a string. + * + * Usage: + * + * $array = Spyc::YAMLLoadString("---\n0: hello world\n"); + * print_r($array); + * + * @access public + * @return array + * @param string $input String containing YAML + */ + public static function YAMLLoadString( $input ) { + $Spyc = new Spyc; + return $Spyc->__loadString( $input ); + } - // New YAML document - $string = "---\n"; + /** + * Dump YAML from PHP array statically + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as nothing.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + public static function YAMLDump( $array, $indent = false, $wordwrap = false ) { + $spyc = new Spyc; + return $spyc->dump( $array, $indent, $wordwrap ); + } - // Start at the base of the array and move through it. - foreach ( $array as $key => $value ) { - $string .= $this->_yamlize( $key, $value, 0 ); - } - return $string; - } - /**** Private Properties ****/ - - private $_haveRefs; - private $_allNodes; - private $_lastIndent; - private $_lastNode; - private $_inBlock; - private $_isInline; - private $_dumpIndent; - private $_dumpWordWrap; - - /**** Private Methods ****/ - - /** - * Attempts to convert a key / value array item to YAML - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _yamlize( $key, $value, $indent ) { - if ( is_array( $value ) ) { - // It has children. What to do? - // Make it the right kind of item - $string = $this->_dumpNode( $key, null, $indent ); - // Add the indent - $indent += $this->_dumpIndent; - // Yamlize the array - $string .= $this->_yamlizeArray( $value, $indent ); - } elseif ( !is_array( $value ) ) { - // It doesn't have children. Yip. - $string = $this->_dumpNode( $key, $value, $indent ); - } - return $string; - } + /** + * Dump PHP array to YAML + * + * The dump method, when supplied with an array, will do its best + * to convert the array into friendly YAML. Pretty simple. Feel free to + * save the returned string as tasteful.yaml and pass it around. + * + * Oh, and you can decide how big the indent is and what the wordwrap + * for folding is. Pretty cool -- just pass in 'false' for either if + * you want to use the default. + * + * Indent's default is 2 spaces, wordwrap's default is 40 characters. And + * you can turn off wordwrap by passing in 0. + * + * @access public + * @return string + * @param array $array PHP array + * @param int $indent Pass in false to use the default, which is 2 + * @param int $wordwrap Pass in 0 for no wordwrap, false for default (40) + */ + public function dump( $array, $indent = false, $wordwrap = false ) { + // Dumps to some very clean YAML. We'll have to add some more features + // and options soon. And better support for folding. - /** - * Attempts to convert an array to YAML - * @return string - * @param $array The array you want to convert - * @param $indent The indent of the current level - */ - private function _yamlizeArray( $array, $indent ) { - if ( is_array( $array ) ) { - $string = ''; - foreach ( $array as $key => $value ) { - $string .= $this->_yamlize( $key, $value, $indent ); - } - return $string; - } else { - return false; - } + // New features and options. + if ( $indent === false or !is_numeric( $indent ) ) { + $this->_dumpIndent = 2; + } else { + $this->_dumpIndent = $indent; } - /** - * Find out whether a string needs to be output as a literal rather than in plain style. - * Added by Roan Kattouw 13-03-2008 - * @param $value The string to check - * @return bool - */ - function _needLiteral( $value ) { - // Check whether the string contains # or : or begins with any of: - // [ - ? , [ ] { } ! * & | > ' " % @ ` ] - // or is a number or contains newlines - return (bool)( gettype( $value ) == "string" && - ( is_numeric( $value ) || - strpos( $value, "\n" ) || - preg_match( "/[#:]/", $value ) || - preg_match( "/^[-?,[\]{}!*&|>'\"%@`]/", $value ) ) ); - } + if ( $wordwrap === false or !is_numeric( $wordwrap ) ) { + $this->_dumpWordWrap = 40; + } else { + $this->_dumpWordWrap = $wordwrap; + } - /** - * Returns YAML from a key and a value - * @return string - * @param $key The name of the key - * @param $value The value of the item - * @param $indent The indent of the current node - */ - private function _dumpNode( $key, $value, $indent ) { - // do some folding here, for blocks - if ( $this->_needLiteral( $value ) ) { - $value = $this->_doLiteralBlock( $value, $indent ); - } else { - $value = $this->_doFolding( $value, $indent ); - } + // New YAML document + $string = "---\n"; + + // Start at the base of the array and move through it. + if ( $array ) { + $array = (array)$array; + $first_key = key( $array ); + + $previous_key = - 1; + foreach ( $array as $key => $value ) { + $string .= $this->_yamlize( $key, $value, 0, $previous_key, $first_key ); + $previous_key = $key; + } + } + return $string; + } + + /** + * Attempts to convert a key / value array item to YAML + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _yamlize( $key, $value, $indent, $previous_key = - 1, $first_key = 0 ) { + if ( is_array( $value ) ) { + if ( empty ( $value ) ) + return $this->_dumpNode( $key, array(), $indent, $previous_key, $first_key ); + // It has children. What to do? + // Make it the right kind of item + $string = $this->_dumpNode( $key, NULL, $indent, $previous_key, $first_key ); + // Add the indent + $indent += $this->_dumpIndent; + // Yamlize the array + $string .= $this->_yamlizeArray( $value, $indent ); + } elseif ( !is_array( $value ) ) { + // It doesn't have children. Yip. + $string = $this->_dumpNode( $key, $value, $indent, $previous_key, $first_key ); + } + return $string; + } - $spaces = str_repeat( ' ', $indent ); + /** + * Attempts to convert an array to YAML + * @access private + * @return string + * @param $array The array you want to convert + * @param $indent The indent of the current level + */ + private function _yamlizeArray( $array, $indent ) { + if ( is_array( $array ) ) { + $string = ''; + $previous_key = - 1; + $first_key = key( $array ); + foreach ( $array as $key => $value ) { + $string .= $this->_yamlize( $key, $value, $indent, $previous_key, $first_key ); + $previous_key = $key; + } + return $string; + } else { + return false; + } + } + + /** + * Returns YAML from a key and a value + * @access private + * @return string + * @param $key The name of the key + * @param $value The value of the item + * @param $indent The indent of the current node + */ + private function _dumpNode( $key, $value, $indent, $previous_key = - 1, $first_key = 0 ) { + // do some folding here, for blocks + if ( is_string ( $value ) && ( ( strpos( $value, "\n" ) !== false || strpos( $value, ": " ) !== false || strpos( $value, "- " ) !== false || + strpos( $value, "*" ) !== false || strpos( $value, "#" ) !== false || strpos( $value, "<" ) !== false || strpos( $value, ">" ) !== false || + strpos( $value, "[" ) !== false || strpos( $value, "]" ) !== false || strpos( $value, "{" ) !== false || strpos( $value, "}" ) !== false ) || substr ( $value, - 1, 1 ) == ':' ) ) { + $value = $this->_doLiteralBlock( $value, $indent ); + } else { + $value = $this->_doFolding( $value, $indent ); + if ( is_bool( $value ) ) { + $value = ( $value ) ? "true" : "false"; + } + } + + if ( $value === array() ) $value = '[ ]'; if ( is_int( $key ) ) { // It's a sequence @@ -185,7 +282,7 @@ class Spyc { else $string = $spaces . "-\n"; } else { - if ($key == '*') //bug 21922 - Quote asterix used as keys + if ( $key == '*' ) // bug 21922 - Quote asterix used as keys $key = "'*'"; // It's mapped @@ -197,40 +294,696 @@ class Spyc { return $string; } - /** - * Creates a literal block for dumping - * @return string - * @param $value - * @param $indent int The value of the indent - */ - private function _doLiteralBlock( $value, $indent ) { - $exploded = explode( "\n", $value ); - $newValue = '|-'; - $indent += $this->_dumpIndent; - $spaces = str_repeat( ' ', $indent ); - foreach ( $exploded as $line ) { - $newValue .= "\n" . $spaces . trim( $line ); - } - return $newValue; - } + if ( is_int( $key ) && $key - 1 == $previous_key && $first_key === 0 ) { + // It's a sequence + $string = $spaces . '- ' . $value . "\n"; + } else { + if ( $first_key === 0 ) throw new Exception( 'Keys are all screwy. The first one was zero, now it\'s "' . $key . '"' ); + // It's mapped + if ( strpos( $key, ":" ) !== false ) { $key = '"' . $key . '"'; } + $string = $spaces . $key . ': ' . $value . "\n"; + } + return $string; + } - /** - * Folds a string of text, if necessary - * @return string - * @param $value The string you wish to fold - */ - private function _doFolding( $value, $indent ) { - // Don't do anything if wordwrap is set to 0 - if ( $this->_dumpWordWrap === 0 ) { - return $value; - } + /** + * Creates a literal block for dumping + * @access private + * @return string + * @param $value + * @param $indent int The value of the indent + */ + private function _doLiteralBlock( $value, $indent ) { + if ( strpos( $value, "\n" ) === false && strpos( $value, "'" ) === false ) { + return sprintf ( "'%s'", $value ); + } + if ( strpos( $value, "\n" ) === false && strpos( $value, '"' ) === false ) { + return sprintf ( '"%s"', $value ); + } + $exploded = explode( "\n", $value ); + $newValue = '|'; + $indent += $this->_dumpIndent; + $spaces = str_repeat( ' ', $indent ); + foreach ( $exploded as $line ) { + $newValue .= "\n" . $spaces . trim( $line ); + } + return $newValue; + } - if ( strlen( $value ) > $this->_dumpWordWrap ) { - $indent += $this->_dumpIndent; - $indent = str_repeat( ' ', $indent ); - $wrapped = wordwrap( $value, $this->_dumpWordWrap, "\n$indent" ); - $value = ">-\n" . $indent . $wrapped; - } - return $value; - } + /** + * Folds a string of text, if necessary + * @access private + * @return string + * @param $value The string you wish to fold + */ + private function _doFolding( $value, $indent ) { + // Don't do anything if wordwrap is set to 0 + + if ( $this->_dumpWordWrap !== 0 && is_string ( $value ) && strlen( $value ) > $this->_dumpWordWrap ) { + $indent += $this->_dumpIndent; + $indent = str_repeat( ' ', $indent ); + $wrapped = wordwrap( $value, $this->_dumpWordWrap, "\n$indent" ); + $value = ">\n" . $indent . $wrapped; + } else { + if ( $this->setting_dump_force_quotes && is_string ( $value ) ) + $value = '"' . $value . '"'; + } + + + return $value; + } + +// LOADING FUNCTIONS + + private function __load( $input ) { + $Source = $this->loadFromSource( $input ); + return $this->loadWithSource( $Source ); + } + + private function __loadString( $input ) { + $Source = $this->loadFromString( $input ); + return $this->loadWithSource( $Source ); + } + + private function loadWithSource( $Source ) { + if ( empty ( $Source ) ) return array(); + if ( $this->setting_use_syck_is_possible && function_exists ( 'syck_load' ) ) { + $array = syck_load ( implode ( '', $Source ) ); + return is_array( $array ) ? $array : array(); + } + + $this->path = array(); + $this->result = array(); + + $cnt = count( $Source ); + for ( $i = 0; $i < $cnt; $i++ ) { + $line = $Source[$i]; + + $this->indent = strlen( $line ) - strlen( ltrim( $line ) ); + $tempPath = $this->getParentPathByIndent( $this->indent ); + $line = self::stripIndent( $line, $this->indent ); + if ( self::isComment( $line ) ) continue; + if ( self::isEmpty( $line ) ) continue; + $this->path = $tempPath; + + $literalBlockStyle = self::startsLiteralBlock( $line ); + if ( $literalBlockStyle ) { + $line = rtrim ( $line, $literalBlockStyle . " \n" ); + $literalBlock = ''; + $line .= $this->LiteralPlaceHolder; + + while ( ++$i < $cnt && $this->literalBlockContinues( $Source[$i], $this->indent ) ) { + $literalBlock = $this->addLiteralLine( $literalBlock, $Source[$i], $literalBlockStyle ); + } + $i--; + } + + while ( ++$i < $cnt && self::greedilyNeedNextLine( $line ) ) { + $line = rtrim ( $line, " \n\t\r" ) . ' ' . ltrim ( $Source[$i], " \t" ); + } + $i--; + + + + if ( strpos ( $line, '#' ) ) { + if ( strpos ( $line, '"' ) === false && strpos ( $line, "'" ) === false ) + $line = preg_replace( '/\s+#(.+)$/', '', $line ); + } + + $lineArray = $this->_parseLine( $line ); + + if ( $literalBlockStyle ) + $lineArray = $this->revertLiteralPlaceHolder ( $lineArray, $literalBlock ); + + $this->addArray( $lineArray, $this->indent ); + + foreach ( $this->delayedPath as $indent => $delayedPath ) + $this->path[$indent] = $delayedPath; + + $this->delayedPath = array(); + + } + return $this->result; + } + + private function loadFromSource ( $input ) { + if ( !empty( $input ) && strpos( $input, "\n" ) === false && file_exists( $input ) ) + return file( $input ); + + return $this->loadFromString( $input ); + } + + private function loadFromString ( $input ) { + $lines = explode( "\n", $input ); + foreach ( $lines as $k => $_ ) { + $lines[$k] = rtrim ( $_, "\r" ); + } + return $lines; + } + + /** + * Parses YAML code and returns an array for a node + * @access private + * @return array + * @param string $line A line from the YAML file + */ + private function _parseLine( $line ) { + if ( !$line ) return array(); + $line = trim( $line ); + + if ( !$line ) return array(); + $array = array(); + + $group = $this->nodeContainsGroup( $line ); + if ( $group ) { + $this->addGroup( $line, $group ); + $line = $this->stripGroup ( $line, $group ); + } + + if ( $this->startsMappedSequence( $line ) ) + return $this->returnMappedSequence( $line ); + + if ( $this->startsMappedValue( $line ) ) + return $this->returnMappedValue( $line ); + + if ( $this->isArrayElement( $line ) ) + return $this->returnArrayElement( $line ); + + if ( $this->isPlainArray( $line ) ) + return $this->returnPlainArray( $line ); + + + return $this->returnKeyValuePair( $line ); + + } + + /** + * Finds the type of the passed value, returns the value as the new type. + * @access private + * @param string $value + * @return mixed + */ + private function _toType( $value ) { + if ( $value === '' ) return null; + $first_character = $value[0]; + $last_character = substr( $value, - 1, 1 ); + + $is_quoted = false; + do { + if ( !$value ) break; + if ( $first_character != '"' && $first_character != "'" ) break; + if ( $last_character != '"' && $last_character != "'" ) break; + $is_quoted = true; + } while ( 0 ); + + if ( $is_quoted ) + return strtr( substr ( $value, 1, - 1 ), array ( '\\"' => '"', '\'\'' => '\'', '\\\'' => '\'' ) ); + + if ( strpos( $value, ' #' ) !== false ) + $value = preg_replace( '/\s+#(.+)$/', '', $value ); + + if ( $first_character == '[' && $last_character == ']' ) { + // Take out strings sequences and mappings + $innerValue = trim( substr ( $value, 1, - 1 ) ); + if ( $innerValue === '' ) return array(); + $explode = $this->_inlineEscape( $innerValue ); + // Propagate value array + $value = array(); + foreach ( $explode as $v ) { + $value[] = $this->_toType( $v ); + } + return $value; + } + + if ( strpos( $value, ': ' ) !== false && $first_character != '{' ) { + $array = explode( ': ', $value ); + $key = trim( $array[0] ); + array_shift( $array ); + $value = trim( implode( ': ', $array ) ); + $value = $this->_toType( $value ); + return array( $key => $value ); + } + + if ( $first_character == '{' && $last_character == '}' ) { + $innerValue = trim( substr ( $value, 1, - 1 ) ); + if ( $innerValue === '' ) return array(); + // Inline Mapping + // Take out strings sequences and mappings + $explode = $this->_inlineEscape( $innerValue ); + // Propagate value array + $array = array(); + foreach ( $explode as $v ) { + $SubArr = $this->_toType( $v ); + if ( empty( $SubArr ) ) continue; + if ( is_array ( $SubArr ) ) { + $array[key( $SubArr )] = $SubArr[key( $SubArr )]; continue; + } + $array[] = $SubArr; + } + return $array; + } + + if ( $value == 'null' || $value == 'NULL' || $value == 'Null' || $value == '' || $value == '~' ) { + return null; + } + + if ( intval( $first_character ) > 0 && preg_match ( '/^[1-9]+[0-9]*$/', $value ) ) { + $intvalue = (int)$value; + if ( $intvalue != PHP_INT_MAX ) + $value = $intvalue; + return $value; + } + + if ( in_array( $value, + array( 'true', 'on', '+', 'yes', 'y', 'True', 'TRUE', 'On', 'ON', 'YES', 'Yes', 'Y' ) ) ) { + return true; + } + + if ( in_array( strtolower( $value ), + array( 'false', 'off', '-', 'no', 'n' ) ) ) { + return false; + } + + if ( is_numeric( $value ) ) { + if ( $value === '0' ) return 0; + if ( trim ( $value, 0 ) === $value ) + $value = (float)$value; + return $value; + } + + return $value; + } + + /** + * Used in inlines to check for more inlines or quoted strings + * @access private + * @return array + */ + private function _inlineEscape( $inline ) { + // There's gotta be a cleaner way to do this... + // While pure sequences seem to be nesting just fine, + // pure mappings and mappings with sequences inside can't go very + // deep. This needs to be fixed. + + $seqs = array(); + $maps = array(); + $saved_strings = array(); + + // Check for strings + $regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/'; + if ( preg_match_all( $regex, $inline, $strings ) ) { + $saved_strings = $strings[0]; + $inline = preg_replace( $regex, 'YAMLString', $inline ); + } + unset( $regex ); + + $i = 0; + do { + + // Check for sequences + while ( preg_match( '/\[([^{}\[\]]+)\]/U', $inline, $matchseqs ) ) { + $seqs[] = $matchseqs[0]; + $inline = preg_replace( '/\[([^{}\[\]]+)\]/U', ( 'YAMLSeq' . ( count( $seqs ) - 1 ) . 's' ), $inline, 1 ); + } + + // Check for mappings + while ( preg_match( '/{([^\[\]{}]+)}/U', $inline, $matchmaps ) ) { + $maps[] = $matchmaps[0]; + $inline = preg_replace( '/{([^\[\]{}]+)}/U', ( 'YAMLMap' . ( count( $maps ) - 1 ) . 's' ), $inline, 1 ); + } + + if ( $i++ >= 10 ) break; + + } while ( strpos ( $inline, '[' ) !== false || strpos ( $inline, '{' ) !== false ); + + $explode = explode( ', ', $inline ); + $stringi = 0; $i = 0; + + while ( 1 ) { + + // Re-add the sequences + if ( !empty( $seqs ) ) { + foreach ( $explode as $key => $value ) { + if ( strpos( $value, 'YAMLSeq' ) !== false ) { + foreach ( $seqs as $seqk => $seq ) { + $explode[$key] = str_replace( ( 'YAMLSeq' . $seqk . 's' ), $seq, $value ); + $value = $explode[$key]; + } + } + } + } + + // Re-add the mappings + if ( !empty( $maps ) ) { + foreach ( $explode as $key => $value ) { + if ( strpos( $value, 'YAMLMap' ) !== false ) { + foreach ( $maps as $mapk => $map ) { + $explode[$key] = str_replace( ( 'YAMLMap' . $mapk . 's' ), $map, $value ); + $value = $explode[$key]; + } + } + } + } + + + // Re-add the strings + if ( !empty( $saved_strings ) ) { + foreach ( $explode as $key => $value ) { + while ( strpos( $value, 'YAMLString' ) !== false ) { + $explode[$key] = preg_replace( '/YAMLString/', $saved_strings[$stringi], $value, 1 ); + unset( $saved_strings[$stringi] ); + ++$stringi; + $value = $explode[$key]; + } + } + } + + $finished = true; + foreach ( $explode as $key => $value ) { + if ( strpos( $value, 'YAMLSeq' ) !== false ) { + $finished = false; break; + } + if ( strpos( $value, 'YAMLMap' ) !== false ) { + $finished = false; break; + } + if ( strpos( $value, 'YAMLString' ) !== false ) { + $finished = false; break; + } + } + if ( $finished ) break; + + $i++; + if ( $i > 10 ) + break; // Prevent infinite loops. + } + + return $explode; + } + + private function literalBlockContinues ( $line, $lineIndent ) { + if ( !trim( $line ) ) return true; + if ( strlen( $line ) - strlen( ltrim( $line ) ) > $lineIndent ) return true; + return false; + } + + private function referenceContentsByAlias ( $alias ) { + do { + if ( !isset( $this->SavedGroups[$alias] ) ) { echo "Bad group name: $alias."; break; } + $groupPath = $this->SavedGroups[$alias]; + $value = $this->result; + foreach ( $groupPath as $k ) { + $value = $value[$k]; + } + } while ( false ); + return $value; + } + + private function addArrayInline ( $array, $indent ) { + $CommonGroupPath = $this->path; + if ( empty ( $array ) ) return false; + + foreach ( $array as $k => $_ ) { + $this->addArray( array( $k => $_ ), $indent ); + $this->path = $CommonGroupPath; + } + return true; + } + + private function addArray ( $incoming_data, $incoming_indent ) { + + // print_r ($incoming_data); + + if ( count ( $incoming_data ) > 1 ) + return $this->addArrayInline ( $incoming_data, $incoming_indent ); + + $key = key ( $incoming_data ); + $value = isset( $incoming_data[$key] ) ? $incoming_data[$key] : null; + if ( $key === '__!YAMLZero' ) $key = '0'; + + if ( $incoming_indent == 0 && !$this->_containsGroupAlias && !$this->_containsGroupAnchor ) { // Shortcut for root-level values. + if ( $key || $key === '' || $key === '0' ) { + $this->result[$key] = $value; + } else { + $this->result[] = $value; end ( $this->result ); $key = key ( $this->result ); + } + $this->path[$incoming_indent] = $key; + return; + } + + + + $history = array(); + // Unfolding inner array tree. + $history[] = $_arr = $this->result; + foreach ( $this->path as $k ) { + $history[] = $_arr = $_arr[$k]; + } + + if ( $this->_containsGroupAlias ) { + $value = $this->referenceContentsByAlias( $this->_containsGroupAlias ); + $this->_containsGroupAlias = false; + } + + + // Adding string or numeric key to the innermost level or $this->arr. + if ( is_string( $key ) && $key == '<<' ) { + if ( !is_array ( $_arr ) ) { $_arr = array (); } + + $_arr = array_merge ( $_arr, $value ); + } else if ( $key || $key === '' || $key === '0' ) { + $_arr[$key] = $value; + } else { + if ( !is_array ( $_arr ) ) { $_arr = array ( $value ); $key = 0; } + else { $_arr[] = $value; end ( $_arr ); $key = key ( $_arr ); } + } + + $reverse_path = array_reverse( $this->path ); + $reverse_history = array_reverse ( $history ); + $reverse_history[0] = $_arr; + $cnt = count( $reverse_history ) - 1; + for ( $i = 0; $i < $cnt; $i++ ) { + $reverse_history[$i + 1][$reverse_path[$i]] = $reverse_history[$i]; + } + $this->result = $reverse_history[$cnt]; + + $this->path[$incoming_indent] = $key; + + if ( $this->_containsGroupAnchor ) { + $this->SavedGroups[$this->_containsGroupAnchor] = $this->path; + if ( is_array ( $value ) ) { + $k = key ( $value ); + if ( !is_int ( $k ) ) { + $this->SavedGroups[$this->_containsGroupAnchor][$incoming_indent + 2] = $k; + } + } + $this->_containsGroupAnchor = false; + } + + } + + private static function startsLiteralBlock ( $line ) { + $lastChar = substr ( trim( $line ), - 1 ); + if ( $lastChar != '>' && $lastChar != '|' ) return false; + if ( $lastChar == '|' ) return $lastChar; + // HTML tags should not be counted as literal blocks. + if ( preg_match ( '#<.*?>$#', $line ) ) return false; + return $lastChar; + } + + private static function greedilyNeedNextLine( $line ) { + $line = trim ( $line ); + if ( !strlen( $line ) ) return false; + if ( substr ( $line, - 1, 1 ) == ']' ) return false; + if ( $line[0] == '[' ) return true; + if ( preg_match ( '#^[^:]+?:\s*\[#', $line ) ) return true; + return false; + } + + private function addLiteralLine ( $literalBlock, $line, $literalBlockStyle ) { + $line = self::stripIndent( $line ); + $line = rtrim ( $line, "\r\n\t " ) . "\n"; + if ( $literalBlockStyle == '|' ) { + return $literalBlock . $line; + } + if ( strlen( $line ) == 0 ) + return rtrim( $literalBlock, ' ' ) . "\n"; + if ( $line == "\n" && $literalBlockStyle == '>' ) { + return rtrim ( $literalBlock, " \t" ) . "\n"; + } + if ( $line != "\n" ) + $line = trim ( $line, "\r\n " ) . " "; + return $literalBlock . $line; + } + + function revertLiteralPlaceHolder ( $lineArray, $literalBlock ) { + foreach ( $lineArray as $k => $_ ) { + if ( is_array( $_ ) ) + $lineArray[$k] = $this->revertLiteralPlaceHolder ( $_, $literalBlock ); + else if ( substr( $_, - 1 * strlen ( $this->LiteralPlaceHolder ) ) == $this->LiteralPlaceHolder ) + $lineArray[$k] = rtrim ( $literalBlock, " \r\n" ); + } + return $lineArray; + } + + private static function stripIndent ( $line, $indent = - 1 ) { + if ( $indent == - 1 ) $indent = strlen( $line ) - strlen( ltrim( $line ) ); + return substr ( $line, $indent ); + } + + private function getParentPathByIndent ( $indent ) { + if ( $indent == 0 ) return array(); + $linePath = $this->path; + do { + end( $linePath ); $lastIndentInParentPath = key( $linePath ); + if ( $indent <= $lastIndentInParentPath ) array_pop ( $linePath ); + } while ( $indent <= $lastIndentInParentPath ); + return $linePath; + } + + + private function clearBiggerPathValues ( $indent ) { + + + if ( $indent == 0 ) $this->path = array(); + if ( empty ( $this->path ) ) return true; + + foreach ( $this->path as $k => $_ ) { + if ( $k > $indent ) unset ( $this->path[$k] ); + } + + return true; + } + + + private static function isComment ( $line ) { + if ( !$line ) return false; + if ( $line[0] == '#' ) return true; + if ( trim( $line, " \r\n\t" ) == '---' ) return true; + return false; + } + + private static function isEmpty ( $line ) { + return ( trim ( $line ) === '' ); + } + + + private function isArrayElement ( $line ) { + if ( !$line ) return false; + if ( $line[0] != '-' ) return false; + if ( strlen ( $line ) > 3 ) + if ( substr( $line, 0, 3 ) == '---' ) return false; + + return true; + } + + private function isHashElement ( $line ) { + return strpos( $line, ':' ); + } + + private function isLiteral ( $line ) { + if ( $this->isArrayElement( $line ) ) return false; + if ( $this->isHashElement( $line ) ) return false; + return true; + } + + + private static function unquote ( $value ) { + if ( !$value ) return $value; + if ( !is_string( $value ) ) return $value; + if ( $value[0] == '\'' ) return trim ( $value, '\'' ); + if ( $value[0] == '"' ) return trim ( $value, '"' ); + return $value; + } + + private function startsMappedSequence ( $line ) { + return ( $line[0] == '-' && substr ( $line, - 1, 1 ) == ':' ); + } + + private function returnMappedSequence ( $line ) { + $array = array(); + $key = self::unquote( trim( substr( $line, 1, - 1 ) ) ); + $array[$key] = array(); + $this->delayedPath = array( strpos ( $line, $key ) + $this->indent => $key ); + return array( $array ); + } + + private function returnMappedValue ( $line ) { + $array = array(); + $key = self::unquote ( trim( substr( $line, 0, - 1 ) ) ); + $array[$key] = ''; + return $array; + } + + private function startsMappedValue ( $line ) { + return ( substr ( $line, - 1, 1 ) == ':' ); + } + + private function isPlainArray ( $line ) { + return ( $line[0] == '[' && substr ( $line, - 1, 1 ) == ']' ); + } + + private function returnPlainArray ( $line ) { + return $this->_toType( $line ); + } + + private function returnKeyValuePair ( $line ) { + $array = array(); + $key = ''; + if ( strpos ( $line, ':' ) ) { + // It's a key/value pair most likely + // If the key is in double quotes pull it out + if ( ( $line[0] == '"' || $line[0] == "'" ) && preg_match( '/^(["\'](.*)["\'](\s)*:)/', $line, $matches ) ) { + $value = trim( str_replace( $matches[1], '', $line ) ); + $key = $matches[2]; + } else { + // Do some guesswork as to the key and the value + $explode = explode( ':', $line ); + $key = trim( $explode[0] ); + array_shift( $explode ); + $value = trim( implode( ':', $explode ) ); + } + // Set the type of the value. Int, string, etc + $value = $this->_toType( $value ); + if ( $key === '0' ) $key = '__!YAMLZero'; + $array[$key] = $value; + } else { + $array = array ( $line ); + } + return $array; + + } + + + private function returnArrayElement ( $line ) { + if ( strlen( $line ) <= 1 ) return array( array() ); // Weird %) + $array = array(); + $value = trim( substr( $line, 1 ) ); + $value = $this->_toType( $value ); + $array[] = $value; + return $array; + } + + + private function nodeContainsGroup ( $line ) { + $symbolsForReference = 'A-z0-9_\-'; + if ( strpos( $line, '&' ) === false && strpos( $line, '*' ) === false ) return false; // Please die fast ;-) + if ( $line[0] == '&' && preg_match( '/^(&[' . $symbolsForReference . ']+)/', $line, $matches ) ) return $matches[1]; + if ( $line[0] == '*' && preg_match( '/^(\*[' . $symbolsForReference . ']+)/', $line, $matches ) ) return $matches[1]; + if ( preg_match( '/(&[' . $symbolsForReference . ']+)$/', $line, $matches ) ) return $matches[1]; + if ( preg_match( '/(\*[' . $symbolsForReference . ']+$)/', $line, $matches ) ) return $matches[1]; + if ( preg_match ( '#^\s*<<\s*:\s*(\*[^\s]+).*$#', $line, $matches ) ) return $matches[1]; + return false; + + } + + private function addGroup ( $line, $group ) { + if ( $group[0] == '&' ) $this->_containsGroupAnchor = substr ( $group, 1 ); + if ( $group[0] == '*' ) $this->_containsGroupAlias = substr ( $group, 1 ); + // print_r ($this->path); + } + + private function stripGroup ( $line, $group ) { + $line = trim( str_replace( $group, '', $line ) ); + return $line; + } } diff --git a/includes/api/ApiQueryBacklinks.php b/includes/api/ApiQueryBacklinks.php index 438f8d75a2..49f30ba579 100644 --- a/includes/api/ApiQueryBacklinks.php +++ b/includes/api/ApiQueryBacklinks.php @@ -123,8 +123,8 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase { if ( $this->params['filterredir'] == 'redirects' ) $this->addWhereFld( 'page_is_redirect', 1 ); else if ( $this->params['filterredir'] == 'nonredirects' && !$this->redirect ) - //bug 22245 - Check for !redirect, as filtering nonredirects, when getting what links to them is contradictory - $this->addWhereFld( 'page_is_redirect', 0 ); + // bug 22245 - Check for !redirect, as filtering nonredirects, when getting what links to them is contradictory + $this->addWhereFld( 'page_is_redirect', 0 ); $this->addOption( 'LIMIT', $this->params['limit'] + 1 ); $this->addOption( 'ORDER BY', $this->bl_from ); @@ -221,6 +221,7 @@ class ApiQueryBacklinks extends ApiQueryGeneratorBase { $this->pageMap[$row->page_namespace][$row->page_title] = $row->page_id; if ( $row->page_is_redirect ) $this->redirTitles[] = Title::makeTitle( $row->page_namespace, $row->page_title ); + $resultPageSet->processDbRow( $row ); } } diff --git a/includes/api/ApiQueryDeletedrevs.php b/includes/api/ApiQueryDeletedrevs.php index 7b94c84cf6..6c32a206d7 100644 --- a/includes/api/ApiQueryDeletedrevs.php +++ b/includes/api/ApiQueryDeletedrevs.php @@ -193,7 +193,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase { $rev['user'] = $row->ar_user_text; if ( $fld_comment ) $rev['comment'] = $row->ar_comment; - if ( $fld_minor && $row->ar_minor_edit == 1) + if ( $fld_minor && $row->ar_minor_edit == 1 ) $rev['minor'] = ''; if ( $fld_len ) $rev['len'] = $row->ar_len; diff --git a/includes/api/ApiQueryWatchlist.php b/includes/api/ApiQueryWatchlist.php index ddfcf75b85..be253b2ad7 100644 --- a/includes/api/ApiQueryWatchlist.php +++ b/includes/api/ApiQueryWatchlist.php @@ -262,7 +262,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { } if ( $this->fld_notificationtimestamp ) - $vals['notificationtimestamp'] = ( $row->wl_notificationtimestamp == null ) ? '' : wfTimestamp( TS_ISO_8601, $row->wl_notificationtimestamp); + $vals['notificationtimestamp'] = ( $row->wl_notificationtimestamp == null ) ? '' : wfTimestamp( TS_ISO_8601, $row->wl_notificationtimestamp ); if ( $this->fld_comment && isset( $row->rc_comment ) ) $vals['comment'] = $row->rc_comment; -- 2.20.1