public function synchronize(NodeInterface $node, Context $context, $dirtyAllowed = false) { /* @var $node EntityNode */ $machineName = $node->getBundle(); $object = $node->getValue(); if (!is_array($object)) { $object = []; } if (empty($object['description'])) { $description = ''; } else { $description = $object['description']; } if ($node->isMerge() && ($existing = $this->getExistingObject($node, $context))) { $info = ['machine_name' => $machineName, 'description' => $description] + $object + $existing; } else { $info = ['machine_name' => $machineName, 'description' => $description] + $object + self::$defaults; if ($vocabulary = taxonomy_vocabulary_machine_name_load($machineName)) { // So an existing object is here, but the vid parameter is // actually never loaded (we don't want to export it when we // are building a yml file) - therefore we need to load it // once again. In case we didn't set the vid, the taxonomy // save method will attempt an SQL INSERT and cause bad SQL // STATE errors (constraint violation) $info['vid'] = $vocabulary->vid; } } if (empty($info['name'])) { $context->logWarning(sprintf('%s: has no name', $node->getPath())); $info['name'] = $machineName; } taxonomy_vocabulary_save((object) $info); }
public function getDependencies(NodeInterface $node, Context $context) { /* @var $node EntityNode */ $order = []; $bundle = $node->getBundle(); // First, fields $field = []; foreach (field_info_instances('node', $bundle) as $instance) { $field[] = 'entity.node.' . $bundle . '.field.' . $instance['field_name']; $order[] = isset($instance['weight']) ? $instance['weight'] : 0; } array_multisort($order, $field); return $field; }
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 FieldInstanceNode */ $entityType = $node->getEntityType(); $bundle = $node->getBundle(); $fieldName = $node->getFieldName(); $existing = field_info_instance($entityType, $fieldName, $bundle); $field = field_info_field($fieldName); $default = array('entity_type' => $entityType, 'bundle' => $bundle, 'field_name' => $fieldName); $object = $node->getValue(); if (!is_array($object)) { $object = array(); } if (empty($object['label'])) { // Field data 'label' key is not part of the Drupal signature // but this module will inject it anyway and should be persisted // along the field 'data' key in database if (empty($field['label'])) { if ($label = $this->findFieldLabel($fieldName)) { $default['label'] = $label; } } else { $default['label'] = $field['label']; } } // This is a forced default from this module: never display new // fields without being explicitely told to $instance = $default + $object + array('display' => array('default' => array('type' => 'hidden'))); // Dynamically determine weight using position relative to parent node // @todo Find a quicker way if ($node->hasParent()) { $instance['weight'] = $node->getParent()->getChildPosition($node); } // Propagate defaults set at the field level if (!empty($field['instance'])) { foreach ($field['instance'] as $key => $value) { if (!isset($instance[$key])) { $instance[$key] = $value; } } } // Even thought this is not mandatory few modules such as the 'image' // module will attempt to access this attribute, without carying about // the field_update_instance() method documentation if (!isset($instance['settings'])) { $instance['settings'] = array(); } // Deal with widget if (!isset($instance['widget'])) { if (isset($field['widget'])) { $instance['widget'] = $field['widget']; } } if ($existing) { $this->alter(self::HOOK_UPDATE, $node, $instance); field_update_instance($instance); } else { $this->alter(self::HOOK_INSERT, $node, $instance); field_create_instance($instance); } }