একটি নোড সংরক্ষণের আগে কাস্টম ফর্মের জেনারিকভাবে পরিবর্তিত ক্ষেত্রগুলি সনাক্ত করা


12

আমি ফিল্ড_ট্যাচ_ফর্ম () ব্যবহার করে একটি সামগ্রী প্রকার থেকে একটি কাস্টম ফর্মে নির্দিষ্ট ক্ষেত্র যুক্ত করছি। ফর্মটি জমা দেওয়া হলে আমি এই ক্ষেত্রগুলিকে # বৈধ এবং # সাবমিট কলব্যাকগুলি থেকে ফিল্ড_আটাচ_ফর্ম_অালিডিয়েট () এবং ফিল্ড_আত্তাচ_সাম্বিট () কল করে প্রক্রিয়াজাত করছি।

এই মুহুর্তে, আমি পোস্ট-জমা দেওয়ার সাথে তুলনা করতে চাই, নোড অবজেক্টটি মূল নোডের সাথে এবং কেবল ক্ষেত্রগুলির কোনও পরিবর্তন হয়ে থাকলে নোড_সেভ () এ বিরক্ত করব। অতএব, আমি ব্যবহার করে মূল নোড লোড করে শুরু করি entity_load_unchanged()

দুর্ভাগ্যক্রমে, মূল নোড অবজেক্টের ক্ষেত্রের অ্যারেগুলি প্রস্তুত নোড অবজেক্টে ফিল্ড অ্যারের সাথে মেলে না, যা সংরক্ষণের জন্য অপেক্ষা করছে, এমনকি ক্ষেত্রগুলিতে কোনও পরিবর্তন না করা হলেও, সরল "$ old_field == $ new_field "তুলনা অসম্ভব। উদাহরণস্বরূপ, একটি সাধারণ পাঠ্য ক্ষেত্রটি আসলটিতে এর মতো প্রদর্শিত হয়:

$old_node->field_text['und'][0] = array(
  'value' => 'Test',
  'format' => NULL,
  'safe_value' => 'Test',
);

যেখানে প্রস্তুত নোডে এটি প্রদর্শিত হয়।

$node->field_text['und'][0] = array(
  'value' => 'Test',
);

আপনি কেবল 'মান' কীটি তুলনা করার কথা ভাবতে পারেন, তবে তারপরে আপনি অন্যান্য উপাদানগুলির সাথে তৈরি ক্ষেত্রগুলিতে চলে যাবেন যেখানে 'মান' কী নেই। উদাহরণস্বরূপ, আসুন এমন কোনও ঠিকানা ক্ষেত্রটি দেখুন যেখানে কোনও 'মান' কী নেই এবং পুরানো এবং প্রস্তুত উভয় নোডে কীগুলি রয়েছে যাগুলির অংশগুলি নেই।

পুরানো নোড

$old_node->field_address['und'][0] = array(
  'country' => 'GB',
  'administrative_area' => 'Test',
  'sub_administrative_area' => NULL,
  'locality' => 'Test',
  'dependent_locality' => NULL,
  'postal_code' => 'Test',
  'thoroughfare' => 'Test',
  'premise' => 'Test',
  'sub_premise' => NULL,
  'organisation_name' => 'Test',
  'name_line' => 'Test',
  'first_name' => NULL,
  'last_name' => NULL,
  'data' => NULL,
);

নোড প্রস্তুত

$node->field_address['und'][0] = array(
  'element_key' => 'node|page|field_address|und|0',
  'thoroughfare' => 'Test',
  'premise' => 'Test',
  'locality' => 'Test',
  'administrative_area' => 'Test',
  'postal_code' => 'Test',
  'country' => 'GB',
  'organisation_name' => 'Test',
  'name_line' => 'Test',
);

খালি মাঠগুলির জন্য, আরও একটি তাত্পর্য রয়েছে।

পুরানো নোড

$old_node->field_text = array();

নোড প্রস্তুত

$node->field_text = array(
  'und' => array(),
);

আমি কোনও ক্ষেত্রের পুরানো এবং নতুন মানটি পরিবর্তিত হয়েছে কিনা তা সনাক্ত করতে সাধারণভাবে তুলনা করতে পারি?
এটি কি কেবল অসম্ভব?


আমি মনে করি আপনি _field_invoke()"প্রস্তুত" নোড থেকে পুরো ফিল্ড স্ট্রাকচার তৈরির সাথে খেলতে বা সম্পর্কিত কিছু করতে পারেন , উভয় ক্ষেত্র রেন্ডার করতে পারেন এবং এই এইচটিএমএল স্ট্রিংকে কেবল তুলনা করতে পারেন। শুধু একটি ধারণা।
কালব্রো

@ ক্যালাব্রো হ্যাঁ এটি অবশ্যই যাওয়ার উপায়, আমি পারফরম্যান্সের পক্ষে যথেষ্ট খারাপ লাগা অনুভব করতে সাহায্য করতে পারি না - এটিকে জেনারিক করার জন্য আপনাকে ফর্ম জমা দেওয়ার মাধ্যমে প্রতিটি বিট ফিল্ডের তথ্য পৃথকভাবে লোড করতে হবে। অথবা আমি অনুমান করি যে আপনি ডেটা পাওয়ার জন্য একটি সামগ্রিক ক্যোয়ারী লিখতে পারেন, তবে তারপরে গুরুত্বপূর্ণ হুকগুলি আগুনে না লাগতে পারে। ধারণাগতভাবে এটি সম্ভব বলে মনে হচ্ছে, তবে আমি মনে করি একটি বাস্তবায়ন বেশ জটিল হবে
ক্লাইভ

@ ক্যালাব্রো আমি এই ধারণাটি বেশ বুঝতে পারি না। ক্ষেত্রের কাঠামোটি কীভাবে প্রস্তুত করা যায় তা প্রদর্শনের জন্য আপনি কিছু সিউডোকোড পোস্ট করতে পারেন এবং আপনি বর্ণিত হিসাবে এটি রেন্ডার করতে পারেন?
মরবিডি

উত্তর:


9

এটি শেষ পর্যন্ত, জেনেরিক সমাধান হিসাবে কাজ করা উচিত। সমস্ত ইনপুট জন্য ক্লাইভ এবং morbiD ধন্যবাদ।

নোডের দুটি সংস্করণ নিম্নলিখিত ফাংশনে পাস করুন। এটি হবে:

  1. সনাক্তকৃত সামগ্রীর ধরণের সমস্ত সম্পাদনাযোগ্য ক্ষেত্র এবং তাদের সম্পাদনাযোগ্য কলামগুলি (যেমন আইটেমগুলি সম্ভবত কাস্টম ফর্মটিতে প্রদর্শিত হতে পারে) একটি একক কোয়েরিতে ডাটাবেস থেকে টানুন।

  2. উভয় সংস্করণে সম্পূর্ণ ফাঁকা ক্ষেত্র এবং কলামগুলি উপেক্ষা করুন।

  3. একটি ক্ষেত্রের সাথে পরিবর্তন হিসাবে দুটি সংস্করণের মধ্যে বিভিন্ন সংখ্যার মান রয়েছে বলে বিবেচনা করুন।

  4. প্রতিটি ক্ষেত্র, মান, এবং কলামের মাধ্যমে আইট্রেট করুন এবং দুটি সংস্করণ তুলনা করুন।

  5. আইটেমগুলি অ-অভিন্নভাবে (! =) সাথে তুলনা করুন যদি তারা সংখ্যায় হয় এবং অভিন্ন ((= ==)) অন্য কিছু হয় তবে।

  6. এটি সনাক্ত করে এমন প্রথম পরিবর্তনের সাথে সাথে সত্যটি ফিরিয়ে আনুন (যেহেতু আমাদের নোডটি পুনঃস্থাপন করতে হবে তা জানতে একটি পরিবর্তনই যথেষ্ট)।

  7. সমস্ত মান তুলনা করার পরে কোনও পরিবর্তন সনাক্ত না হলে FALSE প্রত্যাবর্তন করুন।

  8. ক্ষেত্রের সংগ্রহগুলি তাদের এবং তাদের স্কিমা লোড করে এবং ফলাফলগুলিকে নিজের কাছে স্থান দিয়ে পুনরাবৃত্তভাবে তুলনা করুন। এমনকি এটি নেস্টেড ফিল্ড সংগ্রহগুলি তুলনা করার অনুমতিও দেওয়া উচিত। ক্ষেত্র সংগ্রহের মডিউলে কোডের কোনও নির্ভরতা থাকা উচিত নয়।

এই কোডটিতে আরও কোনও বাগ বা টাইপস রয়েছে কিনা তা আমাকে জানান।

/*
 * Pass both versions of the node to this function. Returns TRUE if it detects any changes and FALSE if not.
 * Pass field collections as an array keyed by field collection ID.
 *
 * @param object $old_entity
 *   The original (stored in the database) node object.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 * @param object $new_entity
 *   The prepared node object for comparison.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 */
function _fields_changed($old_entity, $new_entity) {
  // Check for node or field collection.
  $entity_is_field_collection = (get_class($old_entity) == 'FieldCollectionItemEntity');

  $bundle = ($entity_is_field_collection ? $old_entity->field_name : $old_entity->type);

  // Sanity check. Exit and throw an error if the content types don't match.
  if($bundle !== ($entity_is_field_collection ? $new_entity->field_name : $new_entity->type)) {
    drupal_set_message('Content type mismatch. Unable to save changes.', 'error');
    return FALSE;
  }

  // Get field info.
  $field_read_params = array(
    'entity_type' => ($entity_is_field_collection ? 'field_collection_item' : 'node'),
    'bundle' => $bundle
  );
  $fields_info = field_read_fields($field_read_params);

  foreach($fields_info as $field_name => $field_info) {
    $old_field = $old_entity->$field_name;
    $new_field = $new_entity->$field_name;

    // Check the number of values for each field, or if they are populated at all.
    $old_field_count = (isset($old_field[LANGUAGE_NONE]) ? count($old_field[LANGUAGE_NONE]) : 0);
    $new_field_count = (isset($new_field[LANGUAGE_NONE]) ? count($new_field[LANGUAGE_NONE]) : 0);

    if ($old_field_count != $new_field_count) {
      // The two versions have a different number of values. Something has changed.
      return TRUE;
    } elseif ($old_field_count > 0 && $new_field_count > 0) {
      // Both versions have an equal number of values. Time to compare.

      // See if this field is a field collection.
      if ($field_info['type'] == 'field_collection') {

        foreach ($new_field[LANGUAGE_NONE] as $delta => $values) {
          $old_field_collection = entity_load_unchanged('field_collection_item', $values['entity']->item_id);
          $new_field_collection = $values['entity'];

          if (_fields_changed($old_field_collection, $new_field_collection)) {
            return TRUE;
          }
        }
        unset($delta, $values);

      } else {
        foreach($old_field[LANGUAGE_NONE] as $delta => $value) {
          foreach($field_info['columns'] as $field_column_name => $field_column_info) {
            $old_value = $old_field[LANGUAGE_NONE][$delta][$field_column_name];
            $new_value = $new_field[LANGUAGE_NONE][$delta][$field_column_name];
            $field_column_type = $field_column_info['type'];

            // As with the overall field, exit if one version has a value and the other doesn't.
            if (isset($old_value) != isset($new_value)) {
              return TRUE;
            } elseif (isset($old_value) && isset($new_value)) {
              // The column stores numeric data so compare values non-identically.
              if (in_array($field_column_type, array('int', 'float', 'numeric'))) {
                if ($new_value != $old_value) {
                  return TRUE;
                }
              }
              // The column stores non-numeric data so compare values identically,
              elseif ($new_value !== $old_value) {
                return TRUE;
              }
            } else {
              // Included for clarity. Both values are empty so there was obviously no change.
            }
          } 
          unset($field_column_name, $field_column_info);
        }
        unset($delta, $value);
      }
    } else {
      // Included for clarity. Both values are empty so there was obviously no change.
    }
  }
  unset($field_name, $field_info);
  // End of field comparison loop.

  // We didn't find any changes. Don't resave the node.
  return FALSE;
}

কখনও কখনও আপনি কোন ক্ষেত্র পরিবর্তন হয়েছে তা জানতে আগ্রহী। এটি জানতে, আপনি ফাংশনের এই সংস্করণটি ব্যবহার করতে পারেন:

/*
 * Pass both versions of the node to this function. Returns an array of
 * fields that were changed or an empty array if none were changed.
 * Pass field collections as an array keyed by field collection ID.
 *
 * @param object $old_entity
 *   The original (stored in the database) node object.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 * @param object $new_entity
 *   The prepared node object for comparison.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 */
function _fields_changed($old_entity, $new_entity) {
  // Check for node or field collection.
  $entity_is_field_collection = (get_class($old_entity) == 'FieldCollectionItemEntity');

  $bundle = ($entity_is_field_collection ? $old_entity->field_name : $old_entity->type);

  // Sanity check. Exit and throw an error if the content types don't match.
  if ($bundle !== ($entity_is_field_collection ? $new_entity->field_name : $new_entity->type)) {
    drupal_set_message('Content type mismatch. Unable to save changes.', 'error');
    return FALSE;
  }

  // Get field info.
  $field_read_params = array(
    'entity_type' => ($entity_is_field_collection ? 'field_collection_item' : 'node'),
    'bundle' => $bundle
  );
  $fields_info = field_read_fields($field_read_params);

  $fields_changed = array();

  foreach ($fields_info as $field_name => $field_info) {
    $old_field = $old_entity->$field_name;
    $new_field = $new_entity->$field_name;

    // Check the number of values for each field, or if they are populated at all.
    $old_field_count = (isset($old_field[LANGUAGE_NONE]) ? count($old_field[LANGUAGE_NONE]) : 0);
    $new_field_count = (isset($new_field[LANGUAGE_NONE]) ? count($new_field[LANGUAGE_NONE]) : 0);

    if ($old_field_count != $new_field_count) {
      // The two versions have a different number of values. Something has changed.
      $fields_changed[] = $field_name;
    }
    elseif ($old_field_count > 0 && $new_field_count > 0) {
      // Both versions have an equal number of values. Time to compare.

      // See if this field is a field collection.
      if ($field_info['type'] == 'field_collection') {

        foreach ($new_field[LANGUAGE_NONE] as $delta => $values) {
          $old_field_collection = entity_load_unchanged('field_collection_item', $values['entity']->item_id);
          $new_field_collection = $values['entity'];

          $fields_changed = array_merge($fields_changed, _fields_changed($old_field_collection, $new_field_collection));
        }
        unset($delta, $values);

      }
      else {
        foreach ($old_field[LANGUAGE_NONE] as $delta => $value) {
          foreach ($field_info['columns'] as $field_column_name => $field_column_info) {
            $old_value = $old_field[LANGUAGE_NONE][$delta][$field_column_name];
            $new_value = $new_field[LANGUAGE_NONE][$delta][$field_column_name];
            $field_column_type = $field_column_info['type'];

            // As with the overall field, exit if one version has a value and the other doesn't.
            if (isset($old_value) != isset($new_value)) {
              $fields_changed[] = $old_field;
            }
            elseif (isset($old_value) && isset($new_value)) {
              // The column stores numeric data so compare values non-identically.
              if (in_array($field_column_type, array(
                'int',
                'float',
                'numeric'
              ))) {
                if ($new_value != $old_value) {
                  $fields_changed[] = $field_name;
                }
              }
              // The column stores non-numeric data so compare values identically,
              elseif ($new_value !== $old_value) {
                $fields_changed[] = $field_name;
              }
            }
            else {
              // Included for clarity. Both values are empty so there was obviously no change.
            }
          }
          unset($field_column_name, $field_column_info);
        }
        unset($delta, $value);
      }
    }
    else {
      // Included for clarity. Both values are empty so there was obviously no change.
    }
  }
  unset($field_name, $field_info);
  // End of field comparison loop.

  return $fields_changed;
}

কখনও কখনও আপনি এটি তৈরি করতে চাইতে পারেন যাতে নোডের নির্দিষ্ট ক্ষেত্রগুলি পরিবর্তনের ফলে নোডের "পরিবর্তিত" টাইমস্ট্যাম্পটি আপডেট হওয়ার কারণ না ঘটে। এটি নিম্নলিখিত হিসাবে প্রয়োগ করা যেতে পারে:

/**
 * Implements hook_node_presave().
 */
function mymodule_node_presave($node) {
  $fields_changed = _fields_changed($node->original, $node);
  $no_update_timestamp_fields = array('field_subject', 'field_keywords');
  if (!empty($fields_changed) &&
    empty(array_diff($fields_changed, $no_update_timestamp_fields))) {
    // Don't change the $node->changed timestamp if one of the fields has
    // been changed that should not affect the timestamp.
    $node->changed = $node->original->changed;
  }
}

সম্পাদনা (7/30/2013) ক্ষেত্র সংগ্রহ সমর্থন শক্তিশালী । একাধিক মান সহ ক্ষেত্রগুলির জন্য সমর্থন যুক্ত করা হয়েছে।

সম্পাদনা (7/31/2015) ফাংশনের যুক্ত সংস্করণ যা কোন ক্ষেত্রগুলি পরিবর্তিত হয়েছে এবং উদাহরণস্বরূপ ব্যবহারের ক্ষেত্রে ফিরে আসে।


এটি দুর্দান্ত, আমি বোধ করি এটি বিকাশকারীদের ব্যবহারের জন্য কিছুটা এপিআই মডিউলে থাকা উচিত।
জেল

3

এখানে অন্য একটি সহজ, পদ্ধতির যা জটিল সার্ভারের পার্শ্ব মানের তুলনাগুলি এড়িয়ে চলে এবং যে কোনও ফর্মের সাথে কাজ করবে:

  1. ফর্মের মান পরিবর্তন হয়েছে কিনা তা সনাক্ত করতে jQuery ব্যবহার করুন
  2. ফর্মটি পরিবর্তিত হয়েছে তা চিহ্নিত করতে একটি লুকানো উপাদান মান সেট করুন।
  3. লুকানো উপাদান মান সার্ভারের পাশ এবং প্রয়োজনীয় হিসাবে প্রক্রিয়া পরীক্ষা করুন।

আপনি একটি jQuery নোংরা ফর্ম প্লাগইন ব্যবহার করতে পারেন যেমন https://github.com/codedance/jquery.AreYouSure

যদিও অন্যরা আপনাকে ফর্মটি পরিবর্তিত / নোংরা স্ট্যাটাস শুনতে দেয় সেগুলিও কাজ করবে।

কোনও লুকানো ফর্ম উপাদানের মান সেট করতে শ্রোতা যুক্ত করুন:

জাভাস্ক্রিপ্ট অক্ষম করা ব্যবহারকারীদের (~ 2%) ডিফল্টরূপে সংরক্ষণ করতে লুকানো ফর্ম উপাদানটিকে 'পরিবর্তিত' এর একটি ডিফল্ট মানতে সেট করুন।

উদাহরণ:

// Clear initial state for js-enabled user
$('input#hidden-indicator').val('')
// Add changed listener
$('#my-form').areYouSure({
    change: function() {
      // Set hidden element value
      if ($(this).hasClass('dirty')) {
        $('input#hidden-indicator').val('changed');
      } else {
        $('input#hidden-indicator').val('');
      }
    }
 });

তারপরে আপনি লুকানো উপাদানটির মান পরীক্ষা করতে পারেন

if ($form_state['values']['hidden_indicator'] == 'changed') { /* node_save($node) */ }

আপনার ফর্মটিতে বৈধতা জমা / হ্যান্ডলারগুলি জমা দিন।


2
দুর্দান্ত সমাধান, যদিও স্পষ্টতই js ছাড়া কিছু ব্যবহারকারী রয়েছে। এছাড়াও, Drupal.behaviors.for- এর আপডেট মিস্র / ফর্ম.জেস ফাইলটিতে ড্রপাল কোরের আপডেট করুন। আরেকটি বিষয় লক্ষণীয় হ'ল কিছু উইসইভিগ সম্পাদক এবং তাদের দ্রুপাল মডিউলগুলি যেভাবে কাজ করে, একটি পরিবর্তিত মান সনাক্ত করা সর্বদা যথাসম্ভব সোজা এগিয়ে থাকে না it
গোলাপী

হ্যাঁ, লুকানো উপাদানটির জন্য 'পরিবর্তিত' এর একটি ডিফল্ট মান নির্ধারণ করা জেএস সক্ষম না করে এমন কয়েকটি ব্যবহারকারীর জন্য ডিফল্টরূপে সংরক্ষণ করতে পারে - ছোট শতাংশ। সম্পর্কিত Drupal.behaviors.formUpdatedসম্ভবত আকর্ষণীয় নোটটি val()এটির সাথে যুক্ত করা যেতে পারে যদিও মনে হচ্ছে এটি আসলে পরিবর্তিত মান (উদাহরণস্বরূপ ক্লিক ইভেন্ট সহ) ব্যতীত ট্রিগার করবে, যদিও উত্সর্গীকৃত প্লাগইনগুলি প্রকৃত পরিবর্তিত ফর্মের মানগুলি সনাক্ত করতে আরও ভাল।
ডেভিড থমাস

0

আমি নিশ্চিত যে এটি নিখুঁত, তবে কেন নোড অবজেক্টগুলির পরিবর্তে ফর্মগুলির তুলনা করে এটিকে অন্য পথে নেওয়া হচ্ছে না ?

আমি নিশ্চিত নই যে আপনি নোডের আকারে কঠোর হন তবে আপনি নিজের পুরানো নোড এবং আপনার নতুন নোড দিয়ে ফর্মটি রেন্ডার করতে পারেন:

module_load_include('inc', 'node', 'node.pages');
node_object_prepare($new_node);
$new_form = drupal_get_form($new_node->node_type . '_node_form', $new_node);
node_object_prepare($old_node);
$old_form = drupal_get_form($old_node->node_type . '_node_form', $old_node);

আপনার ফর্মগুলির সাথে তুলনা করুন ...

আমি আশা করি এটি একটি ভাল ট্র্যাক ... আমাকে জানান


আমি ইতিমধ্যে drupal_get_form () দেখেছি কিন্তু আমি বুঝতে পারি নি যে আপনি এটি 2 য় প্যারামিটার হিসাবে নোড দিতে পারবেন। তবে, আমি স্রেফ উপরে উদাহরণস্বরূপ কোডটি পরীক্ষা করেছি এবং দুর্ভাগ্যক্রমে, যখন ফিরে অ্যারে স্ট্রাকচারগুলি একই, মানগুলি নেই। আমি যে পরীক্ষার ক্ষেত্রটি দিয়ে পরীক্ষা করছি তার জন্য এই পুনরাবৃত্তির অ্যারে_ডিফ_সোক () দেখুন: i.imgur.com/LUDPu1R.jpg
মরবিডি

আমি এই অ্যারে_ডিফ_ম্যাসোকটি দেখতে পাচ্ছি, তবে আপনারা কি দ্রুপাল_গেট_রফর্ম উভয়ের ডিপিএম দেওয়ার জন্য সময় পাবেন? এই কাছাকাছি একটি উপায় হতে পারে।
গ্রেগরি কাপুস্টিন

0

Hook_node_presave (res node) ব্যবহার করে এখানে একটি পদ্ধতি। এটি কেবল একটি মকআপ, যদি আপনি মনে করেন এটি সহায়তা করে, এটি পরীক্ষা করুন এবং এটি আপনার প্রয়োজনের উন্নতি করুন!

  /**
   * Implements hook_node_presave().
   *
   * Look for changes in node fields, before they are saved
   */
  function mymodule_node_presave($node) {

    $changes = array();

    $node_before = node_load($node->nid);

    $fields = field_info_instances('node', $node->type);
    foreach (array_keys($fields) as $field_name) {

      $val_before = field_get_items('node', $node_before, $field_name);
      $val = field_get_items('node', $node, $field_name);

      if ($val_before != $val) {

        //if new field values has more instances then old one, it has changed
        if (count($val) != count($val_before)) {
          $changes[] = $field_name;
        } else {
          //cycle throught 1 or multiple field value instances
          foreach ($val as $k_i => $val_i) {
            if (is_array($val_i)) {
              foreach ($val_i as $k => $v) {
                if (isset($val_before[$k_i][$k]) && $val_before[$k_i][$k] != $val[$k_i][$k]) {
                  $changes[] = $field_name;
                }
              }
            }
          }
        }
      }
    }
    dpm($changes);
  }

আমি মনে করি, প্রতিটি ক্ষেত্রের মানের জন্য, $ নোডে সংজ্ঞায়িত দৃষ্টান্তগুলি অবশ্যই সংজ্ঞায়িত করতে হবে এবং equal নোড_বরে সমান হবে। আমি ক্ষেত্রের মানের ক্ষেত্রগুলি $ নোড_বরে এবং $ নোডে নেই for সেগুলি যত্ন করি না, আমি মনে করি তারা একই থাকে stay


সম্ভবত আমি কিছু মিস করছি, কিন্তু হুক_নোড_প্রসেস () ইঙ্গিত নোড_সভে () বলা হয়নি? আমরা যদি ক্ষেত্র পরিবর্তন না করা হয় তবে নোড_সেভ () কল করা এড়াতে চেষ্টা করছি।
মর্বিডি

সত্য, এই হুকটি নোড_সেভ () এর ভিতরে ডাকা হয়। তবে আপনি এখনও মাইমডিউল_নোড_প্রেসভে () এর ভিতরে ড্রপাল_গোটো () কল করে সঞ্চয় করা বাতিল করতে পারেন।
dxvargas

2
@ শিপ এটি সত্যিই ভাল ধারণা নয়, আপনি যদি মাঝখানে পুনর্নির্দেশ করেন তবে আপনি নোডটি একটি বেমানান অবস্থায় রেখে যাবেন
ক্লাইভ

0

এটি কেবল কিছু কোড যা আমি একসাথে cobbled। লেগের সমস্ত কাজ করার জন্য সমস্ত ক্রেডিট অবশ্যই @ সিলেক্টোর কাছে যেতে হবে। এটি কেবলমাত্র (একইভাবে অনির্ধারিত) প্রকরণ যা নোড অবজেক্টগুলিকে সরাসরি নিয়ে যায়, ডিবি কিছুটা হিট করে এবং ভাষার আলোচনার যত্ন নেয়।

function _node_fields_have_changed($old_node, $new_node) {
  // @TODO Sanity checks (e.g. node types match).

  // Get the fields attached to the node type.
  $params = array('entity_type' => 'node', 'bundle' => $old_node->type);
  foreach (field_read_fields($params) as $field) {
    // Get the field data for both nodes.
    $old_field_data = field_get_items('node', $old_node, $field['field_name']);
    $new_field_data = field_get_items('node', $new_node, $field['field_name']);

    // If the field existed on the old node, but not the new, it's changed.
    if ($old_field_data && !$new_field_data) {
      return TRUE;
    }
    // Ditto but in reverse.
    elseif ($new_field_data && !$old_field_data) {
      return TRUE;
    }

    foreach ($field['columns'] as $column_name => $column) {
      // If there's data in both columns we need an equality check.
      if (isset($old_field_data[$column_name]) && isset($new_field_data[$column_name])) {
        // Equality checking based on column type.
        if (in_array($column['type'], array('int', 'float', 'numeric')) && $old_field_data[$column_name] != $new_field_data[$column_name]) {
          return TRUE;
        }
        elseif ($old_field_data[$column_name] !== $new_field_data[$column_name]) {
          return TRUE;
        }
      }
      // Otherwise, if there's data for one column but not the other,
      // something changed.
      elseif (isset($old_field_data[$column_name]) || isset($new_field_data[$column_name])) {
        return TRUE;
      }
    } 
  }

  return FALSE;
}

1
আপনি আমার নতুন সংস্করণে আমাকে একই লাইন ধরে ভাবতে শুরু করেছেন। আমি এমনকি নোড টাইপ স্যানিটি চেক অন্তর্ভুক্ত।
এরিক এন

0

প্রদত্ত উত্তরটি দুর্দান্ত এবং এটি আমাকে সহায়তা করেছিল, তবে আমার কিছু সংশোধন করতে হয়েছিল।

// See if this field is a field collection.
if ($field_info['type'] == 'field_collection') {
  foreach ($old_field[LANGUAGE_NONE] as $delta => $values) {
    $old_field_collection = entity_load_unchanged('field_collection_item', $values['entity']->item_id);
    $new_field_collection = $values['entity'];

    $fields_changed = array_merge($fields_changed, erplain_api_fields_changed($old_field_collection, $new_field_collection));
  }
  unset($delta, $values);
}

ইন foreach()লুপ, আমি থেকে পরিবর্তন করতে হয়েছে $new_fieldথেকে $old_field। আমি জানি না এটি দ্রুপালের নতুন সংস্করণ বা কেবলমাত্র আমার কোড (অন্য কোনও কোডের কারণে অন্য কোথাও হতে পারে), তবে আমার অ্যাক্সেস নেই $new_field['entity']


আমি সবেমাত্র একটি টাটকা দ্রুপাল 7.41 ইনস্টল-এ _ ফিল্ডস_চেঞ্জড () ফাংশনটি পরীক্ষা করেছি এবং একটি ফিল্ড_ক্লিকেশন সহ একটি নোড সংরক্ষণ করে আমাকে এই $ পুরানো_ফিল্ড এবং $ নতুন_ফিল্ড দেয় । আমার কাছে দেখে মনে হচ্ছে আপনি সম্ভবত _ ফিল্ডস_চেঞ্জড () কে $ old_entity এবং $ new_entity পরামিতিগুলি ভুল উপায়ে রাউন্ডে ডাকছেন (বা আপনি ঘটনাক্রমে আপনার কোডে ভেরিয়েবলের নামগুলি কোথাও সরিয়ে নিয়েছেন)।
morbiD

0

পোস্টের জন্য ধন্যবাদ, সত্যই আমাকে অনেক সময় বাঁচিয়েছে। ফাংশনটি আউটপুট করছিল এমন সতর্কতা এবং বিজ্ঞপ্তিগুলির একটি গুচ্ছ আমি স্থির করেছিলাম:

/*
 * Pass both versions of the node to this function. Returns an array of
 * fields that were changed or an empty array if none were changed.
 * Pass field collections as an array keyed by field collection ID.
 *
 * @param object $old_entity
 *   The original (stored in the database) node object.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 * @param object $new_entity
 *   The prepared node object for comparison.
 *   This function may also pass itself a FieldCollectionItemEntity object to compare field collections.
 */
function _fields_changed($old_entity, $new_entity) {
  $fields_changed = array();

  // Check for node or field collection.
  if (is_object($old_entity)) {
    $entity_is_field_collection = (get_class($old_entity) == 'FieldCollectionItemEntity');
    $bundle = !empty($entity_is_field_collection) ? $old_entity->field_name : $old_entity->type;
  }

  // Sanity check. Exit and throw an error if the content types don't match.
  if (is_object($new_entity)) {
    if ($bundle !== (!empty($entity_is_field_collection) ? $new_entity->field_name : $new_entity->type)) {
      drupal_set_message('Content type mismatch. Unable to save changes.', 'error');
      return FALSE;
    }
  }

  // Get field info.
  $field_read_params = array(
    'entity_type' => !empty($entity_is_field_collection) ? 'field_collection_item' : 'node',
  );

  if (!empty($bundle)) {
    $field_read_params['bundle'] = $bundle;
  }

  $fields_info = field_read_fields($field_read_params);

  foreach ($fields_info as $field_name => $field_info) {
    $old_field = isset($old_entity->$field_name) ? $old_entity->$field_name : NULL;
    $new_field = isset($new_entity->$field_name) ? $new_entity->$field_name : NULL;

    // Check the number of values for each field, or if they are populated at all.
    $old_field_count = (isset($old_field[LANGUAGE_NONE]) ? count($old_field[LANGUAGE_NONE]) : 0);
    $new_field_count = (isset($new_field[LANGUAGE_NONE]) ? count($new_field[LANGUAGE_NONE]) : 0);

    if ($old_field_count != $new_field_count) {
      // The two versions have a different number of values. Something has changed.
      $fields_changed[] = $field_name;
    }
    elseif ($old_field_count > 0 && $new_field_count > 0) {
      // Both versions have an equal number of values. Time to compare.

      // See if this field is a field collection.
      if ($field_info['type'] == 'field_collection') {

        foreach ($new_field[LANGUAGE_NONE] as $delta => $values) {
          $old_field_collection = NULL;
          if (!empty($values['entity']->item_id)) {
            $old_field_collection = entity_load_unchanged('field_collection_item', $values['entity']->item_id);
          }

          $new_field_collection = NULL;
          if (isset($values['entity'])) {
            $new_field_collection = $values['entity'];
          }

          $fields_changed = array_merge($fields_changed, _fields_changed($old_field_collection, $new_field_collection));
        }
        unset($delta, $values);

      }
      else {
        foreach ($old_field[LANGUAGE_NONE] as $delta => $value) {
          foreach ($field_info['columns'] as $field_column_name => $field_column_info) {
            $old_value = isset($old_field[LANGUAGE_NONE][$delta][$field_column_name]) ? $old_field[LANGUAGE_NONE][$delta][$field_column_name] : NULL;
            $new_value = isset($new_field[LANGUAGE_NONE][$delta][$field_column_name]) ? $new_field[LANGUAGE_NONE][$delta][$field_column_name] : NULL;
            $field_column_type = $field_column_info['type'];

            // As with the overall field, exit if one version has a value and the other doesn't.
            if (isset($old_value) != isset($new_value)) {
              $fields_changed[] = $old_field;
            }
            elseif (isset($old_value) && isset($new_value)) {
              // The column stores numeric data so compare values non-identically.
              if (in_array($field_column_type, array(
                'int',
                'float',
                'numeric'
              ))) {
                if ($new_value != $old_value) {
                  $fields_changed[] = $field_name;
                }
              }
              // The column stores non-numeric data so compare values identically,
              elseif ($new_value !== $old_value) {
                $fields_changed[] = $field_name;
              }
            }
            else {
              // Included for clarity. Both values are empty so there was obviously no change.
            }
          }
          unset($field_column_name, $field_column_info);
        }
        unset($delta, $value);
      }
    }
    else {
      // Included for clarity. Both values are empty so there was obviously no change.
    }
  }
  unset($field_name, $field_info);
  // End of field comparison loop.

  return $fields_changed;
}

দয়া করে ব্যাখ্যা করুন যে এই কোডটি কীভাবে মূল প্রশ্নের উত্তর দেয় (কেবলমাত্র কিছু কোড পোস্ট করা এখানকার নিয়মের সাথে সম্মতিযুক্ত নয়)।
পিয়ের.ভ্রিয়েন্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.