Example #1
0
 /**
  * Reduce an array by a search value and keep the array structure.
  *
  * Comparison is type strict:
  * - For a given needle of type string, integer, array or boolean,
  * value and value type must match to occur in result array
  * - For a given object, a object within the array must be a reference to
  * the same object to match (not just different instance of same class)
  *
  * Example:
  * - Needle: 'findMe'
  * - Given array:
  * array(
  *   'foo' => 'noMatch',
  *   'bar' => 'findMe',
  *   'foobar => array(
  *     'foo' => 'findMe',
  *   ),
  * );
  * - Result:
  * array(
  *   'bar' => 'findMe',
  *   'foobar' => array(
  *     'foo' => findMe',
  *   ),
  * );
  *
  * See the unit tests for more examples and expected behaviour
  *
  * @param mixed $needle The value to search for
  * @param array $haystack The array in which to search
  * @return array $haystack array reduced matching $needle values
  */
 public static function filterByValueRecursive($needle = '', array $haystack = array())
 {
     $resultArray = array();
     // Define a lambda function to be applied to all members of this array dimension
     // Call recursive if current value is of type array
     // Write to $resultArray (by reference!) if types and value match
     $callback = function (&$value, $key) use($needle, &$resultArray) {
         if ($value === $needle) {
             $resultArray[$key] = $value;
         } elseif (is_array($value)) {
             $subArrayMatches = \TYPO3\CMS\Core\Utility\ArrayUtility::filterByValueRecursive($needle, $value);
             if (count($subArrayMatches) > 0) {
                 $resultArray[$key] = $subArrayMatches;
             }
         }
     };
     // array_walk() is not affected by the internal pointers, no need to reset
     array_walk($haystack, $callback);
     // Pointers to result array are reset internally
     return $resultArray;
 }
 /**
  * Add an item to a select field item list.
  *
  * Warning: Do not use this method for radio or check types, especially not
  * with $relativeToField and $relativePosition parameters. This would shift
  * existing database data 'off by one'.
  *
  * As an example, this can be used to add an item to tt_content CType select
  * drop-down after the existing 'mailform' field with these parameters:
  * - $table = 'tt_content'
  * - $field = 'CType'
  * - $item = array(
  * 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.I.10',
  * 'login',
  * 'i/tt_content_login.gif',
  * ),
  * - $relativeToField = mailform
  * - $relativePosition = after
  *
  * @throws \InvalidArgumentException If given parameters are not of correct
  * @throws \RuntimeException If reference to related position fields can not
  * @param string $table Name of TCA table
  * @param string $field Name of TCA field
  * @param array $item New item to add
  * @param string $relativeToField Add item relative to existing field
  * @param string $relativePosition Valid keywords: 'before', 'after'
  * @return void
  */
 public static function addTcaSelectItem($table, $field, array $item, $relativeToField = '', $relativePosition = '')
 {
     if (!is_string($table)) {
         throw new \InvalidArgumentException('Given table is of type "' . gettype($table) . '" but a string is expected.', 1303236963);
     }
     if (!is_string($field)) {
         throw new \InvalidArgumentException('Given field is of type "' . gettype($field) . '" but a string is expected.', 1303236964);
     }
     if (!is_string($relativeToField)) {
         throw new \InvalidArgumentException('Given relative field is of type "' . gettype($relativeToField) . '" but a string is expected.', 1303236965);
     }
     if (!is_string($relativePosition)) {
         throw new \InvalidArgumentException('Given relative position is of type "' . gettype($relativePosition) . '" but a string is expected.', 1303236966);
     }
     if ($relativePosition !== '' && $relativePosition !== 'before' && $relativePosition !== 'after' && $relativePosition !== 'replace') {
         throw new \InvalidArgumentException('Relative position must be either empty or one of "before", "after", "replace".', 1303236967);
     }
     if (!is_array($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'])) {
         throw new \RuntimeException('Given select field item list was not found.', 1303237468);
     }
     // Make sure item keys are integers
     $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'] = array_values($GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
     if ($relativePosition !== '') {
         // Insert at specified position
         $matchedPosition = ArrayUtility::filterByValueRecursive($relativeToField, $GLOBALS['TCA'][$table]['columns'][$field]['config']['items']);
         if (!empty($matchedPosition)) {
             $relativeItemKey = key($matchedPosition);
             if ($relativePosition === 'replace') {
                 $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][$relativeItemKey] = $item;
             } else {
                 if ($relativePosition === 'before') {
                     $offset = $relativeItemKey;
                 } else {
                     $offset = $relativeItemKey + 1;
                 }
                 array_splice($GLOBALS['TCA'][$table]['columns'][$field]['config']['items'], $offset, 0, array(0 => $item));
             }
         } else {
             // Insert at new item at the end of the array if relative position was not found
             $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
         }
     } else {
         // Insert at new item at the end of the array
         $GLOBALS['TCA'][$table]['columns'][$field]['config']['items'][] = $item;
     }
 }
Example #3
0
 /**
  * @test
  */
 public function filterByValueRecursiveDoesNotMatchDifferentInstancesOfSameClass()
 {
     $this->assertEquals(array(), ArrayUtility::filterByValueRecursive(new \stdClass(), array(new \stdClass())));
 }