View source
<?php
function ref_field_sync_help($path, $arg) {
switch ($path) {
case 'admin/help#ref_field_sync':
return '<p>' . t('With Entity Reference Field Synchronized you can link 2 fields so that they can back-reference their entities. When one of them is updated, a reference is created/updated/deleted in the other to keep a 2-way reference.') . '</p>';
}
}
function ref_field_sync_field_info_alter(&$info) {
if (isset($info['ref_field'])) {
$info['ref_field']['settings']['sync'] = '';
}
}
function ref_field_sync_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
if ($form['#field']['type'] == 'ref_field' && count($form['#field']['bundles']) == 1) {
$fields = field_read_fields(array(
'type' => 'ref_field',
));
unset($fields[$form['#field']['field_name']]);
if (isset($form_state['values']['field']['settings']['entity'])) {
$entity = $form_state['values']['field']['settings']['entity'];
if (isset($form_state['values']['field']['settings']['bundles'])) {
$bundles = $form_state['values']['field']['settings']['bundles'];
}
}
else {
$entity = $form['#field']['settings']['entity'];
$bundles = $form['#field']['settings']['bundles'];
}
if (!$entity || !entity_type_supports($entity, 'save')) {
return;
}
$entity_info = entity_get_info($entity);
$bundles = empty($bundles) ? $entity_info['bundles'] : $bundles;
$options = array(
'' => t('- Select -'),
);
foreach ($fields as $field_name => $field) {
$field = field_info_field_by_id($field['id']);
$fields[$field_name] = $field;
if ($field['cardinality'] >= 1) {
continue;
}
if (count($field['bundles']) > 1) {
continue;
}
foreach ($bundles as $bundle => $data) {
if (!isset($field['bundles'][$entity]) || !in_array($bundle, $field['bundles'][$entity])) {
continue 2;
}
}
$ref_entity = $field['settings']['entity'];
if (!entity_type_supports($ref_entity, 'save')) {
continue;
}
$ref_entity_info = entity_get_info($ref_entity);
$ref_bundles = empty($field['settings']['bundles']) ? $ref_entity_info['bundles'] : $field['settings']['bundles'];
foreach ($ref_bundles as $bundle => $data) {
if (!isset($form['#field']['bundles'][$ref_entity]) || !in_array($bundle, $form['#field']['bundles'][$ref_entity])) {
continue 2;
}
}
$in_sync = '';
if (isset($field['settings']['sync']) && $field['settings']['sync']) {
$sync_field = field_read_field($field['settings']['sync']);
$in_sync = ' - ' . t('Currently syncing with: @field', array(
'@field' => $sync_field['field_name'],
));
}
$options[$field_name] = $field_name . $in_sync;
}
if (isset($form_state['values']['field']['settings']['sync'])) {
$default = $form_state['values']['field']['settings']['sync'];
}
elseif (isset($form['#field']['settings']['sync'])) {
$default = $form['#field']['settings']['sync'];
}
else {
$default = '';
}
$form['field']['settings']['sync'] = array(
'#default_value' => $default,
'#type' => 'select',
'#title' => 'Synchronize with',
'#options' => $options,
'#description' => t('Select a field to syncronize references with. Any changes made to a relationship on this field will automaticaly update the referenced entity on the selected field. If the selecetd field is being synced already, the current link for that field will be lost.'),
'#element_validate' => array(
'ref_field_sync_form_field_ui_field_edit_form_validate',
),
);
}
}
function ref_field_sync_form_field_ui_field_edit_form_validate($element, &$form_state, $form) {
if ($form_state['values']['field']['cardinality'] >= 1 && $form_state['values']['field']['settings']['sync']) {
form_error($element, t('Only fields with unlimited values can be kept in sync. please change to "Number of values" to unlimited or remove the syncronization option.'));
}
}
function ref_field_sync_field_update_field($field, $prior_field, $has_data) {
if (isset($field['settings']['sync']) && $field['settings']['sync']) {
$sync_field_name = $field['settings']['sync'];
$sync_field = field_read_field($sync_field_name);
if ($sync_field && $sync_field['settings']['sync'] != $field['field_name']) {
$sync_field['settings']['sync'] = $field['field_name'];
field_update_field($sync_field);
}
}
if (isset($prior_field['settings']['sync'])) {
$prior_sync_field_name = $prior_field['settings']['sync'];
$prior_sync_field = field_read_field($prior_sync_field_name);
if ($prior_sync_field && $prior_sync_field['settings']['sync'] == $field['field_name']) {
$prior_sync_field['settings']['sync'] = FALSE;
field_update_field($prior_sync_field);
}
}
}
function ref_field_sync_entity_insert($entity, $type) {
$lng = isset($entity->language) && $entity->language ? $entity->language : LANGUAGE_NONE;
$info = entity_get_info($type);
if (entity_type_supports($type, 'save') && (!isset($entity->ref_field_caller) || $entity->ref_field_caller != TRUE)) {
$fields = field_read_fields(array(
'type' => 'ref_field',
));
foreach ($fields as $field_name => $field) {
$field = field_info_field_by_id($field['id']);
$fields[$field_name] = $field;
if (isset($entity->{$field_name}) && isset($field['settings']['sync']) && $field['settings']['sync']) {
$new = array();
if (isset($entity->{$field_name}[$lng])) {
foreach ($entity->{$field_name}[$lng] as $value) {
$new[] = $value['eid'];
}
}
foreach ($new as $eid) {
$entities = entity_load($field['settings']['entity'], array(
$eid,
));
ref_field_sync_add_reference($field['settings']['entity'], $entities[$eid], $entity->{$info['entity keys']['id']}, $field['settings']['sync']);
}
}
}
}
}
function ref_field_sync_entity_update($entity, $type) {
$lng = isset($entity->language) && $entity->language ? $entity->language : LANGUAGE_NONE;
$info = entity_get_info($type);
if (entity_type_supports($type, 'save') && (!isset($entity->ref_field_caller) || $entity->ref_field_caller != TRUE)) {
$original = $entity->original;
$org_lng = isset($original->language) && $original->language ? $original->language : LANGUAGE_NONE;
$fields = field_read_fields(array(
'type' => 'ref_field',
));
foreach ($fields as $field_name => $field) {
$field = field_info_field_by_id($field['id']);
$fields[$field_name] = $field;
if (isset($entity->{$field_name}) && isset($field['settings']['sync']) && $field['settings']['sync']) {
$new = $old = array();
if (isset($entity->{$field_name}[$lng])) {
foreach ($entity->{$field_name}[$lng] as $value) {
$new[] = $value['eid'];
}
}
if (isset($original->{$field_name}[$lng])) {
foreach ($original->{$field_name}[$org_lng] as $value) {
$old[] = $value['eid'];
}
}
$removed = array_diff($old, $new);
foreach ($removed as $eid) {
$entities = entity_load($field['settings']['entity'], array(
$eid,
));
ref_field_sync_remove_reference($field['settings']['entity'], $entities[$eid], $entity->{$info['entity keys']['id']}, $field['settings']['sync']);
}
$added = array_diff($new, $old);
foreach ($added as $eid) {
$entities = entity_load($field['settings']['entity'], array(
$eid,
));
ref_field_sync_add_reference($field['settings']['entity'], $entities[$eid], $entity->{$info['entity keys']['id']}, $field['settings']['sync']);
}
}
}
}
}
function ref_field_sync_remove_reference($type, $entity, $eid, $field_name) {
$lng = isset($entity->language) && $entity->language ? $entity->language : LANGUAGE_NONE;
if (isset($entity->{$field_name}[$lng])) {
foreach ($entity->{$field_name}[$lng] as $key => $value) {
if ($value['eid'] == $eid) {
unset($entity->{$field_name}[$lng][$key]);
$entity->ref_field_caller = TRUE;
entity_save($type, $entity);
}
}
}
}
function ref_field_sync_add_reference($type, $entity, $eid, $field_name) {
$lng = isset($entity->language) && $entity->language ? $entity->language : LANGUAGE_NONE;
$entity->{$field_name}[$lng][]['eid'] = $eid;
$entity->ref_field_caller = TRUE;
entity_save($type, $entity);
}