You are here

function configuration_check_context in Configuration Management 6

Check and fix the integrity of the context object in case changes were made to the data

TODO If performance seems to be a problem, test using checksums against the data to determine if changes have been made

Parameters

$context: The referenced context object needing checked and possibly fixed.

1 call to configuration_check_context()
configuration_context_process_property in ./configuration.module
Process a single mapping config property. Various properties will mark static data that will be processed later on in the configuration phases.

File

./configuration.module, line 1604
Provide a unified method for defining site configurations abstracted from their data format. Various data formats should be supported via a plugin architecture such as XML, YAML, JSON, PHP

Code

function configuration_check_context(&$context) {

  // Start from the top of the context
  while (isset($context->parent)) {
    $context =& $context->parent;
  }

  // Start the check array that will recurse through the context.
  // Set it to the first item that has a key/parent instead of the root.
  $checklist = array(
    &$context->children[0],
  );
  while ($check =& $checklist[0]) {
    array_shift($checklist);

    // Check if this particular item has been removed.
    if (!isset($check->parent->item[$check->key])) {

      // Find this context item in the parent and remove it
      for ($i = 0; isset($check->parent->children[$i]); $i++) {
        $find =& $check->parent->children[$i];
        if ($find === $check) {

          // We need to set it to null as well as unsetting it so that
          // any existing references pointing to it will be unset. We can't
          // splice here either because of the reorder later on
          unset($check->parent->children[$i]);
          $check = null;
          break;
        }
      }
      $check_order = true;
    }

    // Check if an item that didn't exist before is here
    if (is_array($check->parent->item) && !empty($check->parent->item)) {
      $keys = array_keys($check->parent->item);
      $keys = array_combine($keys, $keys);
      for ($i = 0; isset($check->parent->children[$i]); $i++) {
        unset($keys[$check->parent->children[$i]->key]);
      }

      // Any left overs here should be new. $i should be set to where the next item should be set
      if (!empty($keys)) {
        foreach ($keys as $key) {
          $check->parent->children[$i++] = configuration_build_context($check->parent->item[$key], $key, configuration_trace_context($check->parent), $check->parent);
        }
      }
    }

    // Check that this contexts data changed from no children to having children
    // The above check will pick up additional children when there some to start
    if (empty($check->children) && is_array($check->item) && !empty($check->item)) {
      $i = 0;
      foreach ($check->item as $key => &$data) {
        $check->children[$i] = configuration_build_context($check->item[$key], $key, configuration_trace_context($check), $check);
      }
    }

    // Check that this context data changed from having children to no children
    if (!empty($check->children) && !is_array($check->item)) {
      for ($i = 0; isset($check->children[$i]); $i++) {
        $check->children[$i] = null;
        unset($check->children[$i]);
      }
    }

    // If this is marked empty, but is not, remove marker
    if ($check->empty && isset($check->item)) {
      unset($check->empty);
    }

    // Check if a reorder for an indexed array is needed and reorder
    // TODO Make an appropriate test case and test this
    if ($check_order) {
      if (isset($check->parent->item[0]) || isset($check->parent->item[1])) {

        // First go to the hole in the indexed array
        for ($i = 0; isset($check->parent->item[$i]); $i++) {
          continue;
        }

        // Confirm that the context does not exist or remove it
        if (isset($check->parent->children[$i])) {
          $check->parent->children[$i] = null;
          unset($check->parent->children[$i]);
        }

        // Move all the consecutive items back one
        while (isset($check->parent->item[++$i])) {
          $fix =& $check->parent->children[$i];
          $check->parent->item[$i - 1] =& $fix->item;

          // Fix the key
          $fix->key = $i - 1;

          // Fix child traces
          configuration_fix_context_trace($fix);
        }

        // Remove the last item since it was moved up one
        unset($check->parent->item[$i - 1]);

        // Sort on the index to finish up
        ksort($check->parent->item);

        // Sort the children contexts as well
        usort($check->children, '_configuration_sort_context');
      }
    }
    $i = 0;
    while (isset($check->children[$i])) {
      $checklist[count($checklist)] =& $check->children[$i++];
    }
  }
}