namespaceURI === W2ML_NS) { if ($template !== NULL) { log_error('"template" attribute on W2ML element', $econf->log); } if ($instance !== NULL) { log_error('"instance" attribute on W2ML element', $econf->log); } return; } if ($template !== NULL) { $econf->req->store_template($in_elm, $template); $econf->edrun = 'auto'; } if ($instance !== NULL) { $econf->req->store_template($in_elm, $instance); } } function process_new_attribute($econf, $in_elm, $out_elm) { if (!$econf->n_access) { return NULL; } $new = get_w2ml_attribute_value($in_elm, 'new'); if ($new === NULL) { return NULL; } if ($in_elm->namespaceURI === W2ML_NS) { log_error('"new" attribute on W2ML element', $econf->log); return NULL; } $from = get_w2ml_attribute_value($in_elm, 'from'); $to = get_w2ml_attribute_value($in_elm, 'to'); if ($from === NULL) { log_error('no "from" attribute with "new" attribute', $econf->log); } if ($to === NULL) { log_error('no "to" attribute with "new" attribute', $econf->log); } if ($from === NULL || $to === NULL) { return NULL; } if (!is_relative_to_attribute($to)) { log_error('unknown relative template instance destination for to="'.$to.'"', $econf->log); return NULL; } $template = $econf->req->get_template($from); if ($template === NULL) { log_error('no template for from="'.$from.'"', $econf->log); return NULL; } return new_instances($econf, $in_elm, $out_elm, $new, $template, $to); } function new_instances($econf, $in_elm, $out_elm, $new, $template, $to) { $last_instance = NULL; $new_id = make_edition_request_str($econf, $new); for ($n = 1; ; ++$n) { $instance_id = $new_id . '-' . $n; $new_req = get_http_parameter(NEW_TPL_PREFIX . $instance_id); if ($new_req === NULL) { break; } $last_instance = new_instance($econf, $in_elm, $out_elm, $instance_id, $template, $to); if ($in_elm->parentNode === NULL) { break; # $in_elm was replaced } } return $last_instance; } function new_instance($econf, $in_elm, $out_elm, $instance_id, $template, $to) { $instance = $template->cloneNode(TRUE); prepare_instance($instance, $instance_id); switch ($to) { case 'firstChild': return $in_elm->insertBefore($instance, $in_elm->firstChild); case 'lastChild': return $in_elm->appendChild($instance); case 'previousSibling': $instance = $in_elm->parentNode->insertBefore($instance, $in_elm); process_previous_sibling_instance($econf, $in_elm, $out_elm, $instance); return $instance; case 'here': $in_elm->parentNode->replaceChild($instance, $in_elm); return $instance; case 'nextSibling': if ($in_elm->nextSibling !== NULL) { return $in_elm->parentNode->insertBefore($instance, $in_elm->nextSibling); } # no nextSibling yet, so it's lastSibling -> fall through case 'lastSibling': return $in_elm->parentNode->appendChild($instance); } } function process_previous_sibling_instance($econf, $in_elm, $out_elm, $instance) { $next_sibling = process_element($econf->parent_conf(), $instance, $out_elm); while ($next_sibling !== $in_elm) { $next_sibling = process_element($econf->parent_conf(), $next_sibling, $out_elm); } } function prepare_instance($element, $instance_id) { $qname_instance_ = qname($element, W2ML_NS, 'instance_'); $element->setAttributeNS(W2ML_NS, $qname_instance_, $instance_id); $synced_ids = prepare_instance_1($element); prepare_instance_2($element, $synced_ids); } function prepare_instance_1($element) { static $synced_attr_names = array('new', 'del', 'template', 'instance'); $synced_ids = array(); foreach ($synced_attr_names as $attr_name) { $attr = get_w2ml_attribute($element, $attr_name); if ($attr !== NULL) { $new_id = generate_str_id(ALPHA_STR, 10); $synced_ids[$attr->value] = $new_id; $attr->value = $new_id; } } for ($child = $element->firstChild; $child !== NULL; $child = $child->nextSibling) { if ($child->nodeType === XML_ELEMENT_NODE) { $synced_ids = array_merge($synced_ids, prepare_instance_1($child)); } } return $synced_ids; } function prepare_instance_2($element, $synced_ids) { static $synced_attr_names = array('to', 'from'); foreach ($synced_attr_names as $attr_name) { $attr = get_w2ml_attribute($element, $attr_name); if ($attr !== NULL) { $new_id = $synced_ids[$attr->value]; if ($new_id !== NULL) { $attr->value = $new_id; } } } for ($child = $element->firstChild; $child !== NULL; $child = $child->nextSibling) { if ($child->nodeType === XML_ELEMENT_NODE) { prepare_instance_2($child, $synced_ids); } } } function process_instance__attribute($econf, $in_elm) { $instance__attr = get_w2ml_attribute($in_elm, 'instance_'); if ($instance__attr !== NULL) { $econf->new_instance_id = $instance__attr->value; $econf->new_instance_editable_counter = new Counter; $in_elm->removeAttributeNode($instance__attr); $econf->modified_now(); } } function process_del_attribute($econf, $in_elm) { if (!$econf->d_access) { return; } $del = get_w2ml_attribute_value($in_elm, 'del'); if ($del === NULL) { return; } if ($in_elm->namespaceURI === W2ML_NS) { log_error('"del" attribute on W2ML element', $econf->log); return; } $del_req_id = DEL_TPL_PREFIX . make_edition_request_str($econf, $del); if (get_http_parameter($del_req_id) !== NULL) { $in_elm->parentNode->removeChild($in_elm); $econf->modified_now(); } } function process_ed_del_attribute($econf, $in_elm, $out_elm) { if (!$econf->d_access) { return; } $to = get_w2ml_attribute_value($in_elm, 'to'); if ($to === NULL) { log_error('ed="del" attribute without to attribute', $econf->log); return; } $out_elm->setAttributeNS(NULL, 'w2mled', 'del'); $out_elm->setAttributeNS(NULL, 'w2mlto', $to); $econf->req->need_editor_support('del'); } function process_ed_new_attribute($econf, $in_elm, $out_elm) { if (!$econf->n_access) { return; } $to = get_w2ml_attribute_value($in_elm, 'to'); if ($to === NULL) { log_error('ed="new" attribute without to attribute', $econf->log); return; } if (is_relative_to_attribute($to) && get_w2ml_attribute($in_elm, $new) === NULL) { create_new_attribute($econf, $in_elm, $out_elm); } $out_elm->setAttributeNS(NULL, 'w2mled', 'new'); $econf->req->need_editor_support('new'); } function create_new_attribute($econf, $in_elm, $out_elm) { $qname_new = qname($in_elm, W2ML_NS, 'new'); $new_id = generate_str_id(ED_ID_CHARS, 10); $in_elm->setAttributeNS(W2ML_NS, $qname_new, $new_id); $econf->modified_now(); } function process_template_attributes_2($econf, $in_elm, $out_elm) { process_template_and_instance_attribute_2($econf, $in_elm, $out_elm); process_del_attribute_2($econf, $in_elm, $out_elm); process_new_from_to_attributes_2($econf, $in_elm, $out_elm); } function process_template_and_instance_attribute_2($econf, $in_elm, $out_elm) { $template = get_w2ml_attribute_value($in_elm, 'template'); if ($template === NULL) { $template = get_w2ml_attribute_value($in_elm, 'instance'); if ($template === NULL) { return; } } $out_elm->setAttributeNS(NULL, 'w2mltemplate', $template); } function process_del_attribute_2($econf, $in_elm, $out_elm) { if (!$econf->d_access) { return; } $del = get_w2ml_attribute_value($in_elm, 'del'); if ($del === NULL) { return; } $out_elm->setAttributeNS(NULL, 'w2mldel', $del); } function process_new_from_to_attributes_2($econf, $in_elm, $out_elm) { if (!$econf->n_access) { return; } $new = get_w2ml_attribute_value($in_elm, 'new'); $from = get_w2ml_attribute_value($in_elm, 'from'); $to = get_w2ml_attribute_value($in_elm, 'to'); if ($to !== NULL) { if ($new !== NULL) { $out_elm->setAttributeNS(NULL, 'w2mlnew', $new); } if ($from !== NULL) { $out_elm->setAttributeNS(NULL, 'w2mlfrom', $from); } $out_elm->setAttributeNS(NULL, 'w2mlto', $to); } } function is_relative_to_attribute($to) { static $relative_to_targets = array('firstChild', 'lastChild', 'previousSibling', 'here', 'nextSibling', 'lastSibling'); return in_array($to, $relative_to_targets, TRUE); } ?>