You are here

function patterns_config_data in Patterns 7

Same name and namespace in other branches
  1. 6.2 patterns.module \patterns_config_data()
  2. 6 patterns.module \patterns_config_data()
  3. 7.2 includes/unused.inc \patterns_config_data()

Take a $data and $config object and adjust $data based on the supplied configuration

TODO Look for ways to optimize and increase performance

File

includes/unused.inc, line 320
Functions that are unused at the moment.

Code

function patterns_config_data(&$data, $configs) {
  foreach ($configs as $path => $config) {

    // An alias key requires multiple paths
    // for each alias and then a #real set
    // to change all of them to the same key
    // TODO test #alias
    if ($config['#alias'] && is_array($config['#alias'])) {
      $tokens = array_slice(preg_split('/(?<!=)\\/(?![a-z]*\\])/', $path), 1);
      $real = end($tokens);

      // Check for the real key
      $matches = patterns_array_fetch($path, $data);

      // If the real key was not found, get the aliases
      if (empty($matches)) {
        if (!$config['#key']) {
          $config['#key'] = $real;
        }
        foreach ($config['#alias'] as $alias) {
          $tokens[count($tokens) - 1] = $alias;
          $matches += patterns_array_fetch('/' . implode('/', $tokens), $data);
        }
      }
    }
    else {
      $matches = patterns_array_fetch($path, $data);
    }

    // If no matches were found and it is a required element
    // return an error
    if (empty($matches) && $config['#required']) {
      $error = TRUE;
    }
    foreach ($matches as &$match) {

      // Collect form_ids here.
      // TODO Think of a better way to migrate components form_id operations here
      if ($config['#form_id']) {
        patterns_config_form_ids($data['tag'], $config['#form_id'], $match);
      }

      // Make sure values that should be arrays are set as such
      if ($config['#array'] && !array_key_exists(0, $match['item'])) {
        if (is_null($match['item']) || is_array($match['item'] && empty($match['item']))) {
          $match['item'] = array();
        }
        else {
          $match['item'] = array(
            $match['item'],
          );
        }

        // Update the context object to reflect new changes
        $match = _patterns_array_context($match['item'], $match);
      }

      // Change the key of this match. Can get the key value via xpath as well.
      // Any duplicate keys will return an error
      if ($config['#key']) {

        // Check that a single match is found via this xpath and that the resulting value is scalar
        if ($config['#key'][0] == '/' && ($sub_matches = patterns_array_fetch($config['#key'], $match['item'], $match)) && count($sub_matches) == 1 && is_scalar($sub_matches[0]['item'])) {

          // an xpath from the matched item is used to get the key value
          $new_key = $sub_matches[0]['item'];
        }
        elseif ($config['#default key']) {
          $new_key = $config['#default key'];
        }
        elseif ($config['#key'][0] == '/') {

          // Could not find the appropriate key value from the xpath
          $error = TRUE;
        }
        else {

          // Set the key to a static value. Typically used for allowing more user readable keys
          $new_key = $config['#key'];
        }
        if ($new_key && array_key_exists($new_key, $match['parent']['item'])) {

          // The new key already exists.
          $error = TRUE;
        }
        elseif ($new_key) {
          $key = $match['key'];
          $match['parent']['item'][$new_key] = $match['item'];

          // TODO This is buggy. Skip for now.
          if (is_int($key) && FALSE) {
            array_splice($match['parent']['item'], $key, 1);
          }
          else {
            unset($match['parent']['item'][$key]);
          }

          // Update the parent context object to reflect new changes
          $match['parent'] = _patterns_array_context($match['parent']['item'], $match['parent']);

          // Update to the new current match
          for ($i = 0, $total = count($match['parent']); $i < $total; $i++) {
            if ($match['parent'][$i]['key'] == $new_key) {
              $match =& $match['parent'][$i];
              break;
            }
          }
        }
      }

      // Create empty key elements if they don't exist but should (and are not required)
      // This is useful when using 'move' to ensure that the destination exists
      if ($config['#create'] && is_array($match['item']) && !array_key_exists($config['#create'], $match['item'])) {
        $match['item'][$config['#create']] = $config['#create value'];
      }

      // Move(or copy) this match to somewhere else in the object. If more than one destination
      // match is found, this value is copied to each one
      // TODO Make move automatically create the destination if it doesn't exist
      // TODO Support move in (put inside array) and move to (replace) actions
      if (!empty($match['parent']) && ($config['#move'][0] == '/' && ($dest_path = $config['#move']) && ($op = 'move')) || $config['#copy'][0] == '/' && ($dest_path = $config['#copy']) && ($op = 'copy')) {
        $dests = patterns_array_fetch($dest_path, $match['item'], $match);
        $parent =& $match['parent'];
        $obj = $match['item'];
        foreach ($dests as $dest) {

          // Can't move to items that are not an array
          if (!is_array($dest['item'])) {
            continue;
          }
          if (!is_int($match['key'])) {
            $dest['item'][$match['key']] = $obj;
          }
          else {
            $dest['item'][] = $obj;
          }

          // Update the dest object to reflect the change
          $dest = _patterns_array_context($dest['item'], $dest);
        }
        if ($op == 'move') {
          if (!is_int($match['key'])) {
            unset($parent['item'][$match['key']]);
          }
          else {
            array_splice($parent['item'], $match['key'], 1);
          }

          // Update the parent object to reflect the change (removal)
          $parent = _patterns_array_context($parent['item'], $parent);
          unset($match);
        }
      }
    }
  }
}