| Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/lib/includes/Serialization/SerializationModifier.php |
<?php
namespace Wikibase\Lib\Serialization;
/**
* Class which can be used to easily modify serializations and arrays.
*
* This could easily be factored out into a library.
*
* @since 0.5
* @author Addshore
*/
class SerializationModifier {
/**
* @param array $array the array to modify
* @param null|string $path the path that we want to modify.
* Element keys should be seperated with / characters.
* * characters can be used to match all keys at a given level.
* null can be used to modify $array directly.
* Examples:
* null
* 'foo/*'
* 'root/entities/*\/statement/references/*\/snaks/*'
* @param callback $callback
* Callback accepts 1 parameter which is the element to touch
* Callback should return the altered element
*
* @return array the altered array
*/
public function modifyUsingCallback( array $array, $path, $callback ) {
$elementsToTouch = $this->getElementsMatchingPath(
$array,
$this->getPathParts( $path )
);
foreach ( $elementsToTouch as $key => $element ) {
$newElement = call_user_func( $callback, $element );
$this->setArrayValueAtKey( $array, $key, $newElement );
}
return $array;
}
/**
* @param array $array
* @param string $path
* @param mixed $value
*/
private function setArrayValueAtKey( array &$array, $path, $value ) {
$current = &$array;
$pathParts = $this->getPathParts( $path );
foreach ( $pathParts as $key ) {
$current = &$current[$key];
}
$current = $value;
}
/**
* Method to get elements that match the path given.
* This is called recursively along with getElementsForAllKeys and getElementsForKey
* The number of calls depends on the depth of the array.
*
* @param array $array
* @param string[] $pathElements
* @param string $currentPath
*
* @return array
*/
private function getElementsMatchingPath( array $array, array $pathElements, $currentPath = '' ) {
$elements = array();
if ( empty( $pathElements ) ) {
$elements[$currentPath] = $array;
} else {
$currentKey = array_shift( $pathElements );
if ( $currentKey === '*' ) {
$elements = array_merge(
$elements,
$this->getElementsForAllKeys( $array, $pathElements, $currentPath )
);
} else {
$elements = array_merge(
$elements,
$this->getElementsForKey( $array, $pathElements, $currentPath, $currentKey )
);
}
}
return $elements;
}
/**
* @param array $array
* @param string[] $pathElements
* @param string $currentPath
*
* @return array
*/
private function getElementsForAllKeys( array $array, array $pathElements, $currentPath ) {
$elements = array();
foreach ( array_keys( $array ) as $arrayKey ) {
$elements = array_merge(
$elements,
$this->getElementsForKey( $array, $pathElements, $currentPath, $arrayKey )
);
}
return $elements;
}
/**
* @param array $array
* @param string[] $pathElements
* @param string $currentPath
* @param string $key
*
* @return array
*/
private function getElementsForKey( array $array, array $pathElements, $currentPath, $key ) {
$elements = array();
if ( isset( $array[$key] ) ) {
$thisPath = $this->getJoinedPath( $currentPath, $key );
if ( is_array( $array[$key] ) ) {
$elements = array_merge(
$elements,
$this->getElementsMatchingPath( $array[$key], $pathElements, $thisPath )
);
} else {
$elements[$thisPath] = $array[$key];
}
}
return $elements;
}
/**
* @param string $prefix
* @param string $key
*
* @return string
*/
private function getJoinedPath( $prefix, $key ) {
if ( $prefix === '' ) {
return $key;
}
return $prefix . '/' . $key;
}
/**
* @param null|string $path
*
* @return string[]
*/
private function getPathParts( $path ) {
if ( $path === null || $path === '' ) {
return array();
}
return explode( '/', $path );
}
}