public function deleteExistingObject(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node EntityNode */ $bundle = $node->getName(); $exists = (int) db_query("SELECT 1 FROM {node} WHERE type = :type", array(':type' => $bundle)); if ($exists) { $context->logDataloss(sprintf("%s: node type has nodes", $node->getPath())); } node_type_delete($bundle); }
public function deleteExistingObject(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node FieldInstanceNode */ $existing = field_info_instance($node->getEntityType(), $node->getName(), $node->getBundle()); if (!$existing) { $context->logWarning(sprintf("%s: does not exists", $node->getPath())); return false; } field_delete_instance($existing); }
/** * Return the filter name depending on the tree structure * * @param NodeInterface $node * @param Context $context * @return array|mixed|string */ protected function getFormatName(NodeInterface $node, Context $context) { if ($node->hasChild('name')) { $value = $node->getChild('name')->getValue(); if (!is_string($value)) { $context->logCritical(sprintf("%s: name attribute is not a string", $node->getPath())); } return $value; } return $node->getName(); }
public function deleteExistingObject(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node EntityNode */ $bundle = $node->getBundle(); $vocabulary = taxonomy_vocabulary_machine_name_load($bundle); $exists = (int) db_query("SELECT 1 FROM {taxonomy_term_data} d WHERE d.vid = :vid", [':vid' => $vocabulary->vid]); if ($exists) { $context->logDataloss(sprintf("%s: taxonomy vocabulary has terms", $node->getPath())); } taxonomy_vocabulary_delete($vocabulary->vid); }
/** * {@inheritdoc} */ public function synchronize(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node \USync\AST\Drupal\MenuNode */ $object = ['menu_name' => $node->getName()]; if ($node->hasChild('name')) { $object['title'] = (string) $node->getChild('name')->getValue(); } if ($node->hasChild('description')) { $object['description'] = (string) $node->getChild('description')->getValue(); } $object += self::$defaults; if ($node->shouldDropOnUpdate()) { $context->log(sprintf("%s: deleting menu and children", $node->getPath())); menu_delete($object); } menu_save($object); return $node->getName(); }
public function execute(Node $node, Context $context) { if ($node instanceof MacroReferenceNode) { $path = $node->getMacroPath(); // Provided that users might want some things hardcoded, everything // under the 'macro' root node will be considered as macros if (false === strpos($path, Path::SEP)) { $path = 'macro' . Path::SEP . $path; } $macro = (new Path($path))->find($context->getGraph()); if (!$macro) { throw new CompilerException(sprintf("'%s': '%s' macro does not exist", $node->getPath(), $node->getValue())); } if (1 !== count($macro)) { throw new CompilerException(sprintf("'%s': '%s' multiple targets found", $node->getPath(), $node->getValue())); } $node->getParent()->replaceChild($node->getName(), reset($macro)->duplicate($node->getName())); } }
public function execute(Node $node, Context $context) { $sorted = array(); $orphans = array(); $path = $node->getPath(); foreach ($node->getChildren() as $key => $child) { if ($child->hasChild('inherit')) { $parent = $child->getChild('inherit')->getValue(); if (!is_string($parent)) { $context->logCritical(sprintf("%s: %s: malformed inherit directive", $path, $key)); } if (!$node->hasChild($parent)) { $context->logCritical(sprintf("%s: %s: cannot inherit from non existing: %s", $path, $key, $parent)); } if ($key === $parent) { $context->logCritical(sprintf("%s: %s: cannot inherit from itself", $path, $key)); } $child->removeChild('inherit'); $orphans[$key] = $parent; } else { $sorted[$key] = array(); } } while (!empty($orphans)) { $count = count($orphans); foreach ($orphans as $key => $parent) { if (isset($sorted[$parent])) { $sorted[$parent][] = $key; $sorted[$key] = array(); unset($orphans[$key]); } } if (count($orphans) === $count) { $context->logCritical(sprintf("%s: circular dependency detected", $path)); } } foreach (array_filter($sorted) as $parent => $children) { foreach ($children as $name) { $node->getChild($name)->setAttribute('inherits', $node->getChild($parent)->getPath()); } } }
/** * Build graph from provided sources */ public function build() { $context = new Context(); $global = $context->time('compiler'); $timer = $context->time('compiler:parse'); $ast = (new ArrayTreeBuilder())->parse($this->buildRawArray($context)); $timer->stop(); // We have a "naked" AST with no business meaning whatsover, now we // need to process low level and meaningless transformations, such // as macro processing $context->setGraph($ast); // First, macro processing, this will deeply change the graph, so it // needs to happen first and alone, prior to anything else $timer = $context->time('compiler:macro'); $visitor = new Visitor(); $visitor->addProcessor(new MacroPass()); $visitor->execute($ast, $context); $timer->stop(); // Same goes for inheritance, it is business-free and low level $timer = $context->time('compiler:inheritance'); $visitor = new Visitor(); $visitor->addProcessor(new InheritancePass()); $visitor->execute($ast, $context); $timer->stop(); // Then, we need to have a business mean-something graph, so let's // apply path map conversion, so let's go! $timer = $context->time('compiler:conversion'); $visitor = new Visitor(); $visitor->addProcessor(new BusinessConversionPass()); $visitor->execute($ast, $context); $timer->stop(); // From this point, graph should not be modified anymore, which means // we can safely count nodes from this point $timer = $context->time('compiler:attributes'); $visitor = new Visitor(); $visitor->addProcessor(new CountPass()); $visitor->addProcessor(new ExpressionProcessor()); $visitor->addProcessor(new DrupalAttributesProcessor()); $visitor->execute($ast, $context); $timer->stop(); $global->stop(); return $context; }
public function synchronize(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node ViewNode */ $entityType = $node->getEntityType(); $bundle = $node->getBundle(); $name = $node->getName(); // First populate the variable that will be used during the // hook_entity_info_alter() call to populate the view modes $viewModes = variable_get(USYNC_VAR_VIEW_MODE, []); $viewModes[$entityType][$name] = $name; variable_set(USYNC_VAR_VIEW_MODE, $viewModes); // First grab a list of everything that can be displayed in view // modes with both extra fields and real fields $instances = field_info_instances($entityType, $bundle); $bundleSettings = field_bundle_settings($entityType, $bundle); $extra = $this->getExtraFieldsDisplay($entityType, $bundle); $weight = 0; $displayExtra = []; $displayField = []; // Then deal with fields and such foreach ($node->getValue() as $propertyName => $formatter) { if (isset($instances[$propertyName])) { $display = array(); // We are working with a field if (!is_array($formatter)) { if (true === $formatter || 'default' === $formatter) { $formatter = array(); } else { if (false === $formatter || null === $formatter || 'delete' === $formatter) { continue; } else { if (!is_string($formatter)) { $context->logWarning(sprintf("%s: %s invalid value for formatter", $node->getPath(), $propertyName)); $formatter = array(); } else { $display['type'] = $formatter; } } } } else { $display = $formatter; } // Merge default and save $displayField[$propertyName] = drupal_array_merge_deep($this->getFieldDefault($node, $entityType, $bundle, $propertyName, $context), $display, array('weight' => $weight++)); } else { if (isset($extra[$propertyName])) { // We are working with and extra field if (!is_array($formatter)) { if (true === $formatter || 'default' === $formatter) { $formatter = array(); } else { if (false === $formatter || null === $formatter || 'delete' === $formatter) { continue; } else { $context->logWarning(sprintf("%s: %s extra fields can only be delete or default", $node->getPath(), $propertyName)); } } } // Merge default and save $displayExtra[$propertyName] = ['visible' => true, 'weight' => $weight++]; } else { $context->logError(sprintf("%s: %s property is nor a field nor an extra field", $node->getPath(), $propertyName)); } } } // Iterate over the fields and update each instance: we don't // need to do it with the $displayExtra property since it is // already the correctly formatted variable foreach ($displayField as $fieldName => $display) { $instances[$fieldName]['display'][$name] = $display; } // Remove non configured fields and extra fields from display foreach ($instances as $fieldName => $instance) { if (!isset($displayField[$fieldName])) { $instance['display'][$name] = array('type' => 'hidden'); } if ($dirtyAllowed) { $data = $instance; unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']); db_update('field_config_instance')->condition('id', $instance['id'])->fields(['data' => serialize($data)])->execute(); } else { field_update_instance($instance); } } foreach (array_keys($extra) as $propertyName) { if (isset($displayExtra[$propertyName])) { $bundleSettings['extra_fields']['display'][$propertyName][$name] = $displayExtra[$propertyName]; } else { $bundleSettings['extra_fields']['display'][$propertyName][$name] = ['visible' => false, 'weight' => $weight++]; } } $bundleSettings['view_modes'][$name] = ['label' => $name, 'custom_settings' => true]; if ($dirtyAllowed) { // Hopefully nothing about display is really cached into the // internal field cache class, except the raw display array // into each instance, but nothing will use that except this // specific view mode implementation, we are going to delay // a few cache clear calls at the very end of the processing. // From field_bundle_settings(). variable_set('field_bundle_settings_' . $entityType . '__' . $bundle, $bundleSettings); } else { field_bundle_settings($entityType, $bundle, $bundleSettings); } if ($dirtyAllowed) { // From field_update_instance() cache_clear_all('*', 'cache_field', true); // From field_info_cache_clear() drupal_static_reset('field_view_mode_settings'); // We need to clear cache in order for later view modes to // load the right instance and prevent them for overriding // what we actually did here entity_info_cache_clear(); _field_info_field_cache()->flush(); } }
public function synchronize(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node FieldNode */ $object = $node->getValue(); if (!is_array($object)) { $object = array(); } if (!isset($object['type'])) { $context->logCritical(sprintf("%s: has no type", $node->getPath())); } $name = $node->getName(); $type = $object['type']; $typeInfo = field_info_field_types($type); if (empty($typeInfo)) { $context->logCritical(sprintf("%s: type %s does not exist", $node->getPath(), $type)); } if ($this->exists($node, $context)) { $existing = $this->getExistingObject($node, $context); } else { $existing = null; } if (array_key_exists('settings', $object) && !is_array($object['settings'])) { $context->log(sprintf("%s: no settings provided, defaulting with empty array", $node->getPath())); $object['settings'] = array(); } $object['field_name'] = $name; if (empty($object['cardinality'])) { $object['cardinality'] = 1; } // Consistency check, prior to do anything, ensure the database tables // are not already there, this happens, sometimes if (!$existing) { if (empty($object['storage']) || 'field_sql_storage' === $object['storage']['type']) { // Prevents warning on unspecified key if (!isset($object['deleted'])) { $object['deleted'] = false; } $tables = [_field_sql_storage_tablename($object), _field_sql_storage_revision_tablename($object)]; foreach ($tables as $table) { if (db_table_exists($table)) { $context->logDataloss(sprintf("%s: %s: table already exists prior to creating field", $node->getPath(), $table)); // If code has not broken here, then go for deletion db_drop_table($table); } } } } if ($existing) { $doDelete = false; $eType = $existing['type']; // Ensure the cardinality change if any is safe to proceed with $cardinality = $object['cardinality'] - $existing['cardinality']; if (0 !== $cardinality) { if (0 < $cardinality || -1 == $object['cardinality']) { $context->log(sprintf("%s: safe cardinality change", $node->getPath())); } else { // @todo Ensure there is data we can save in field if (false) { $context->log(sprintf("%s: safe cardinality change due to data shape", $node->getPath())); } else { $context->logDataloss(sprintf("%s: unsafe cardinality change", $node->getPath())); } } } if ($type !== $eType) { $doDelete = true; $instances = $this->getInstances($name); if (empty($instances)) { $context->logWarning(sprintf("%s: type change (%s -> %s): no instances", $node->getPath(), $type, $eType)); } else { // @todo Ensure there is data if there is instances if (false) { $context->logWarning(sprintf("%s: type change (%s -> %s): existing instances are empty", $node->getPath(), $type, $eType)); } else { // @todo Safe should ensure schema is the same if (false) { $context->logWarning(sprintf("%s: type change (%s -> %s): field schema is the same", $node->getPath(), $type, $eType)); } else { $context->logDataloss(sprintf("%s: type change (%s -> %s): data loss detected", $node->getPath(), $type, $eType)); } } } } if ($doDelete) { $this->deleteExistingObject($node, $context); field_create_field($object); // @todo Recreate instances } else { field_update_field($object); } } else { field_create_field($object); } }
public function execute(Node $node, Context $context) { $context->incr('node'); }
/** * Extract meaningfull objects from the graph, and apply dependency sort * * @param Context $context * @param LoaderInterface[] $loaders */ protected function extractObjects(Context $context, array $loaders) { $dependencyMap = []; $timer = $context->time('loader:extract'); $visitor = new Visitor(); $visitor->addProcessor(function (NodeInterface $node, Context $context) use($loaders, &$dependencyMap) { $path = $node->getPath(); foreach ($loaders as $loader) { if ($loader->canProcess($node)) { $dependencyMap[$path] = []; foreach ($loader->getDependencies($node, $context) as $dependency) { $dependencyMap[$path][] = $dependency; } } } }); $visitor->execute($context->getGraph(), $context); $timer->stop(); return $this->resolveDependencies($dependencyMap, $context); }