123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- <?php
- define('UNIQUE_FIELD_SCOPE_NODE', 'node');
- define('UNIQUE_FIELD_SCOPE_TYPE', 'type');
- define('UNIQUE_FIELD_SCOPE_LANGUAGE', 'language');
- define('UNIQUE_FIELD_SCOPE_ALL', 'all');
- define('UNIQUE_FIELD_COMP_EACH', 'each');
- define('UNIQUE_FIELD_COMP_ALL', 'all');
- define('UNIQUE_FIELD_FIELDS_TITLE', 'title');
- define('UNIQUE_FIELD_FIELDS_AUTHOR', 'name');
- define('UNIQUE_FIELD_FIELDS_LANGUAGE', 'language');
- define('UNIQUE_FIELD_SHOW_MATCHES', 'show_matches');
- function unique_field_help($path, $arg) {
- switch ($path) {
- case 'admin/help#unique_field':
- $output = '<p>' . t("The Unique Field module allows administrators to require that content supplied for specified fields is unique. For example, you may require that each node has a unique title or a different author. For configuration options, please see the <em>Unique Field restrictions</em> section of a content type's administration page.") . '</p>';
- return $output;
- }
- }
- function unique_field_permission() {
- return array(
- 'unique_field_perm_admin' => array(
- 'title' => t('Designate fields as unique'),
- 'description' => t('Configure whether any fields of a content type should be unique.'),
- ),
- 'unique_field_perm_bypass' => array(
- 'title' => t('Bypass requirement that fields are unique'),
- 'description' => t('Allows users to ignore errors about duplicate content and submit it anyway.'),
- ),
- );
- }
- function unique_field_form_alter(&$form, &$form_state, $form_id) {
- if ($form_id === 'node_type_form' && user_access('unique_field_perm_admin') && isset($form['#node_type'])) {
- unique_field_node_settings_form($form);
- }
- elseif (strpos($form_id, 'node_form') !== FALSE && user_access('unique_field_perm_bypass')) {
- $form['unique_field_override'] = array(
- '#type' => 'hidden',
- '#default_value' => '0',
- );
- }
- }
- function unique_field_node_validate($node, $form) {
-
- if ((!empty($node->op) && !empty($node->delete) && $node->op === $node->delete) || (is_array($form) && isset($form['unique_field_override']) && is_array($form['unique_field_override']) && $form['unique_field_override']['#value'] && user_access('unique_field_perm_bypass'))) {
- return;
- }
-
- $fields = variable_get('unique_field_fields_' . $node->type, array());
-
- if (count($fields)) {
-
- $scope = variable_get('unique_field_scope_' . $node->type, UNIQUE_FIELD_SCOPE_TYPE);
- $comp = variable_get('unique_field_comp_' . $node->type, UNIQUE_FIELD_COMP_EACH);
- $var_show_matches = variable_get('unique_field_show_matches_' . $node->type, array());
- $show_matches = is_array($var_show_matches) && in_array(UNIQUE_FIELD_SHOW_MATCHES, $var_show_matches);
-
- $errmsg = NULL;
- $errfld = array();
- $matches = array();
- $allmatch = NULL;
-
- if ($scope === UNIQUE_FIELD_SCOPE_NODE) {
- $values = array();
- foreach ($fields as $field) {
- $new_values = array();
- if ($field === UNIQUE_FIELD_FIELDS_TITLE) {
- $new_values[] = $node->title;
- }
- else {
-
-
-
- $fvalues = field_get_items('node', $node, $field);
- if (empty($fvalues)) {
- continue;
- }
- $field_info = field_info_field($field);
- $field_keys = array_keys($field_info['columns']);
- foreach ($fvalues as $index => $value) {
- if (is_numeric($index)) {
- $field_combined = array();
- foreach ($field_keys as $key) {
- if (isset($fvalues[$index][$key]) && !empty($fvalues[$index][$key])) {
- $field_combined[$key] = $fvalues[$index][$key];
- }
- }
- if (!empty($field_combined)) {
- $new_values[] = serialize($field_combined);
- }
- }
- }
- }
- $new_values = array_merge($values, $new_values);
- $values = array_unique($new_values);
- if (serialize($values) !== serialize($new_values)) {
- $errfld[] = $field;
- }
- }
- if (count($errfld) > 0) {
- $errmsg = t('The @labels fields must have unique values. The @label field has a value that is already used.');
- }
- }
-
- else {
- foreach ($fields as $field) {
- $values = '';
- if ($field === UNIQUE_FIELD_FIELDS_TITLE) {
- $values = $node->title;
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_AUTHOR) {
- $values = $node->uid;
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_LANGUAGE) {
- $values = $node->language;
- }
- else {
-
-
-
- $fvalues = field_get_items('node', $node, $field);
- if (empty($fvalues)) {
- continue;
- }
- foreach ($fvalues as $index => $value) {
- if (!is_numeric($index) || !is_array($value)) {
- unset($fvalues[$index]);
- }
- }
- $field_info = field_info_field($field);
- $values = _field_filter_items($field_info, $fvalues);
- }
- if (empty($values)) {
- continue;
- }
- $match = unique_field_match_value($field, $values, $scope, $node->type, $node->language);
-
- if ($node->nid && is_array($match) && in_array($node->nid, $match)) {
- $key = array_search($node->nid, $match);
- unset($match[$key]);
- }
- if ($comp === UNIQUE_FIELD_COMP_EACH && is_array($match) && count($match)) {
- $errfld[] = $field;
- $errmsg = t('The @label field requires a unique value, and the specified value is already used.');
- }
- $matches[$field] = $match;
- $allmatch = is_array($allmatch) ? array_intersect($allmatch, $match) : $match;
- }
-
- if ($comp === UNIQUE_FIELD_COMP_ALL && is_array($allmatch) && count($allmatch)) {
- foreach ($fields as $field) {
- $errfld[] = $field;
- $matches[$field] = $allmatch;
- }
- $errmsg = t('This form requires that the fields @labels are a unique combination. The specified values are already used.');
- }
- }
-
- if ($errmsg && !empty($errmsg) && is_array($errfld) && count($errfld) > 0) {
- $labels = array();
- foreach ($errfld as $field) {
- if ($field === UNIQUE_FIELD_FIELDS_TITLE) {
- $nodetype = node_type_get_type($node->type);
- $labels[$field] = $nodetype->title_label;
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_AUTHOR) {
- $labels[$field] = t('Author');
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_LANGUAGE) {
- $labels[$field] = t('Language');
- }
- else {
- $fld = field_info_instance('node', $field, $node->type);
- $labels[$field] = $fld['label'];
- }
- }
- foreach ($errfld as $field) {
- $msg = strtr($errmsg, array('@label' => check_plain($labels[$field]), '@labels' => check_plain(join(', ', $labels))));
- if ($show_matches && isset($matches[$field]) && is_array($matches[$field]) && count($matches[$field])) {
- $list_items = array();
- foreach ($matches[$field] as $nid) {
- $match_node = node_load($nid);
- if (node_access('view', $match_node)) {
- $list_items[] = l($match_node->title, 'node/' . $nid);
- }
- }
- $list_html = theme('item_list', array('items' => $list_items));
- $msg .= ' ' . t('Matches are found in the following content: !list-html', array('!list-html' => $list_html));
- }
- if (user_access('unique_field_perm_bypass')) {
- $form_id = str_replace('_', '-', $form['#id']);
- $msg .= '<p>' . t('Click !here to bypass this check and resubmit.', array('!here' => "<a href=\"#\" onclick=\"jQuery('form#" . $form_id . " input[name=\'unique_field_override\']').val(1);jQuery('form#" . $form_id . "').submit();return false;\">" . t('here') . '</a>')) . '</p>';
- }
- form_set_error($field, $msg);
-
-
- if ($comp === UNIQUE_FIELD_COMP_ALL) {
- break;
- }
- }
- }
- }
- }
- function unique_field_match_value($field, $values, $scope, $ntype = NULL, $nlanguage = NULL) {
-
- $entity_type = 'node';
- $efq = new EntityFieldQuery();
- $efq->entityCondition('entity_type', $entity_type);
-
- if ($field === UNIQUE_FIELD_FIELDS_TITLE) {
-
- $efq->propertyCondition('title', $values);
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_AUTHOR) {
-
- $efq->propertyCondition('uid', $values);
- }
- elseif ($field === UNIQUE_FIELD_FIELDS_LANGUAGE) {
-
- $efq->propertyCondition('language', $values);
- }
- else {
-
- $field_info = field_info_field($field);
-
- foreach ($values as $index => $value) {
-
- foreach ($value as $key => $val) {
-
- if (!isset($field_info['columns'][$key]) || !is_array($field_info['columns'][$key])) {
- continue;
- }
-
- if (!strlen($val) || !is_scalar($val)) {
- continue;
- }
- $efq->fieldCondition($field, $key, $val);
- }
- }
- }
-
- if ($scope === UNIQUE_FIELD_SCOPE_TYPE && !empty($ntype)) {
-
- $efq->entityCondition('bundle', $ntype);
- }
- elseif ($scope === UNIQUE_FIELD_SCOPE_LANGUAGE && !empty($nlanguage)) {
-
- $efq->propertyCondition('language', $nlanguage);
- }
-
- $result = $efq->execute();
- $nids = array();
- if (isset($result[$entity_type]) && is_array($result[$entity_type])) {
- foreach ($result[$entity_type] as $item) {
- if (!empty($item->nid)) {
- $nids[] = $item->nid;
- }
- }
- }
- return array_unique($nids);
- }
- function unique_field_node_settings_form(&$form) {
-
- $ntype = $form['#node_type']->type;
- $nodetype = !empty($ntype) ? node_type_get_type($ntype) : FALSE;
- $fieldopts = array();
- $fieldopts[UNIQUE_FIELD_FIELDS_TITLE] = ($nodetype && !empty($nodetype->title_label)) ? check_plain($nodetype->title_label) . ' (' . t('title') . ')' : t('Title');
- $fieldopts[UNIQUE_FIELD_FIELDS_AUTHOR] = t('Author');
- if (module_exists('locale') && !empty($ntype) && variable_get('language_content_type_' . $ntype, 0)) {
- $fieldopts[UNIQUE_FIELD_FIELDS_LANGUAGE] = t('Language');
- }
- if (!empty($ntype)) {
- $fields = field_info_instances('node', $ntype);
- foreach ($fields as $fieldname => $info) {
- $fieldopts[$fieldname] = $info['label'] . ' (' . $fieldname . ')';
- }
- }
-
- $form['unique_field'] = array(
- '#type' => 'fieldset',
- '#title' => t('Unique Field restrictions'),
- '#weight' => 1,
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- '#group' => 'additional_settings',
- );
- $form['unique_field']['unique_field_fields'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Choose the fields that should be unique'),
- '#options' => $fieldopts,
- '#default_value' => !empty($ntype) ? variable_get('unique_field_fields_' . $ntype, array()) : array(),
- '#description' => t('After designating that certain fields should be unique, users will not be able to submit the content form to create a new node or update an existing one if it contains values in the designated fields that duplicate others.'),
- );
- $form['unique_field']['unique_field_scope'] = array(
- '#type' => 'radios',
- '#title' => t('Choose the scope for the unique values'),
- '#options' => array(
- UNIQUE_FIELD_SCOPE_TYPE => t('Content type'),
- UNIQUE_FIELD_SCOPE_LANGUAGE => t('Language'),
- UNIQUE_FIELD_SCOPE_ALL => t('All nodes'),
- UNIQUE_FIELD_SCOPE_NODE => t('Single node only'),
- ),
- '#default_value' => !empty($ntype) ? variable_get('unique_field_scope_' . $ntype, UNIQUE_FIELD_SCOPE_TYPE) : UNIQUE_FIELD_SCOPE_TYPE,
- '#description' => t('Choose whether the values in the specified fields must be unique among nodes of this content type, among nodes of the same language, among all nodes, or only among the fields of the present node.'),
- );
- $form['unique_field']['unique_field_comp'] = array(
- '#type' => 'radios',
- '#title' => t('Choose whether values must be unique individually or in combination'),
- '#options' => array(
- UNIQUE_FIELD_COMP_EACH => t('Each of the specified fields must have a unique value'),
- UNIQUE_FIELD_COMP_ALL => t('The combination of values from the specified fields must be unique'),
- ),
- '#default_value' => !empty($ntype) ? variable_get('unique_field_comp_' . $ntype, UNIQUE_FIELD_COMP_EACH) : UNIQUE_FIELD_COMP_EACH,
- '#description' => t('For example, if you have fields for the parts of a street address (street number and name, city, and zip code) on a node, and want to allow only one node per complete address, but not only one node per city or per zip code, then you would want to choose that the fields must be unique in combination.'),
- );
- $form['unique_field']['unique_field_show_matches'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Check this box to show which nodes match when duplicate values are found'),
- '#options' => array(UNIQUE_FIELD_SHOW_MATCHES => t('Enabled')),
- '#default_value' => !empty($ntype) ? variable_get('unique_field_show_matches_' . $ntype, array()) : array(),
- );
-
- $form['#validate'][] = 'unique_field_node_settings_form_validate';
- }
- function unique_field_node_settings_form_validate($form, &$form_state) {
- if ($form_state['values']['unique_field_scope'] === UNIQUE_FIELD_SCOPE_NODE) {
- if ($form_state['values']['unique_field_comp'] === UNIQUE_FIELD_COMP_ALL) {
- form_set_error('unique_field_comp', t('The scope of a single node requires that each field must be unique.'));
- }
- if (($form_state['values']['unique_field_fields'][UNIQUE_FIELD_FIELDS_AUTHOR] === UNIQUE_FIELD_FIELDS_AUTHOR) || (isset($form_state['values']['unique_field_fields'][UNIQUE_FIELD_FIELDS_LANGUAGE]) && $form_state['values']['unique_field_fields'][UNIQUE_FIELD_FIELDS_LANGUAGE] === UNIQUE_FIELD_FIELDS_LANGUAGE)) {
- form_set_error('unique_field_fields', t('The author and language fields are not supported within the scope of a single node.'));
- }
- }
- }
|