Projet

Général

Profil

Révision 76e2e7c3

Ajouté par Assos Assos il y a environ 10 ans

Weekly update of contrib modules

Voir les différences:

drupal7/sites/all/modules/flag/includes/flag/flag_flag.inc
2 2

  
3 3
/**
4 4
 * @file
5
 *  Contains the flag_flag class.
6
 *  Flag type classes use an object oriented style inspired by that
7
 *  of Views 2.
5
 * Contains the flag_flag class.
6
 * Flag type classes use an object oriented style inspired by that
7
 * of Views 2.
8 8
 */
9 9

  
10 10
/**
11
 * This abstract class represents a flag, or, in Views 2 terminology, "a handler".
11
 * This abstract class represents a flag, or, in Views 2 terminology,
12
 * "a handler".
12 13
 *
13 14
 * This is the base class for all flag implementations. Notable derived
14 15
 * classes are flag_node and flag_comment.
......
29 30
 * - flag_flag::factory_by_array(), creates a flag handler from a configuration
30 31
 *   array. This is used by flag_get_default_flags() and the flag import form.
31 32
 * - flag_flag::factory_by_entity_type(), creates an empty flag handler for the
32
 *   given entity type. This is used when a new or dummy flag handler is required
33
 *   and there is no configuration yet.
33
 *   given entity type. This is used when a new or dummy flag handler is
34
 *   required and there is no configuration yet.
34 35
 *
35 36
 * The factory methods in turn all call the low-level function
36 37
 * flag_create_handler(), which obtains the correct handler for the flag, or if
......
94 95
  );
95 96

  
96 97
  /**
97
   * An associative array containing textual errors that may be created during validation.
98
   * An associative array containing textual errors that may be created during
99
   * validation.
98 100
   *
99 101
   * The array keys should reflect the type of error being set. At this time,
100 102
   * the only "special" behavior related to the array keys is that
......
103 105
   *
104 106
   * @var array
105 107
   */
106
  var $errors = array();
108
  public $errors = array();
107 109

  
108 110
  /**
109 111
   * Creates a flag from a database row. Returns it.
......
135 137
    }
136 138

  
137 139
    if (!empty($row->type)) {
138
      // The loop loading from the database should further populate this property.
140
      // The loop loading from the database should further populate this
141
      // property.
139 142
      $flag->types[] = $row->type;
140 143
    }
141 144

  
......
189 192
      'unflag_long' => '',
190 193
      'unflag_message' => '',
191 194
      'unflag_denied_text' => '',
192
      // The link type used by the flag, as defined in hook_flag_link_type_info().
195
      // The link type used by the flag, as defined in
196
      // hook_flag_link_type_info().
193 197
      'link_type' => 'toggle',
194 198
      'weight' => 0,
195 199
    );
......
245 249
   */
246 250
  function form_input($form_values) {
247 251
    // Load the form fields indiscriminately unto the flag (we don't care about
248
    // stray FormAPI fields because we aren't touching unknown properties anyway.
252
    // stray FormAPI fields because we aren't touching unknown properties
253
    // anyway).
249 254
    foreach ($form_values as $field => $value) {
250 255
      $this->$field = $value;
251 256
    }
......
626 631
   *   TRUE if the flag is enabled for this type and subtype.
627 632
   */
628 633
  function access_entity_enabled($entity_type, $content_subtype = NULL) {
629
   $entity_type_matches = ($this->entity_type == $entity_type);
630
   $sub_type_matches = FALSE;
631
   if (!isset($content_subtype) || !count($this->types)) {
632
     // Subtype automatically matches if we're not asked about it,
633
     // or if the flag applies to all subtypes.
634
     $sub_type_matches = TRUE;
635
   }
636
   else {
637
     $sub_type_matches = in_array($content_subtype, $this->types);
638
   }
639
   return $entity_type_matches && $sub_type_matches;
640
 }
634
    $entity_type_matches = ($this->entity_type == $entity_type);
635
    $sub_type_matches = FALSE;
636
    if (!isset($content_subtype) || !count($this->types)) {
637
      // Subtype automatically matches if we're not asked about it,
638
      // or if the flag applies to all subtypes.
639
      $sub_type_matches = TRUE;
640
    }
641
    else {
642
      $sub_type_matches = in_array($content_subtype, $this->types);
643
    }
644
    return $entity_type_matches && $sub_type_matches;
645
  }
641 646

  
642 647
  /**
643 648
   * Determine whether the flag should show a flag link in entity links.
......
685 690
   *   - to update field data an existing flagging. The $action parameter should
686 691
   *     be set to 'flag'. The Flagging entity will need to be loaded first with
687 692
   *     flagging_load().
693
   *  As with Drupal core API functions for saving entities, no validation of
694
   *  Field API fields is performed here. It is the responsibility of the caller
695
   *  to take care of Field API validation, using either
696
   *  field_attach_form_validate() or field_attach_validate().
688 697
   *
689 698
   * @return
690 699
   *   FALSE if some error occured (e.g., user has no permission, flag isn't
......
695 704
    if (!isset($account)) {
696 705
      $account = $GLOBALS['user'];
697 706
    }
698
    if (!$account) {
699
      return FALSE;
700
    }
701 707

  
702 708
    // Check access and applicability.
703 709
    if (!$skip_permission_check) {
......
736 742
      }
737 743
    }
738 744

  
739
    // Set our uid and sid to the flagging object.
745
    // @todo: Discuss: Core wraps everything in a try { }, should we?
746

  
747
    $existing_flagging_id = $this->_is_flagged($entity_id, $uid, $sid);
748
    $flagged = (bool) $existing_flagging_id;
749

  
750
    // Ensure we have a Flagging entity and it is correctly formed.
740 751
    if (isset($flagging)) {
752
      // We were given a Flagging entity.
753
      // Ensure that it has the uid and sid that we were also given.
741 754
      $flagging->uid = $uid;
742 755
      $flagging->sid = $sid;
743
    }
744 756

  
745
    // @todo: Discuss: Should we call field_attach_validate()? None of the
746
    // entities in core does this (fields entered through forms are already
747
    // validated).
748
    //
749
    // @todo: Discuss: Core wraps everything in a try { }, should we?
757
      // This is an ugly hack to preserve previous behaviour.
758
      $flagging->given_as_parameter = TRUE;
759
    }
760
    else {
761
      // We were not given a Flagging entity.
762
      if ($flagged) {
763
        // Load the existing Flagging entity.
764
        $flagging = flagging_load($existing_flagging_id);
765
      }
766
      else {
767
        // Construct a new Flagging entity to flag with.
768
        $flagging = $this->new_flagging($entity_id, $uid, $sid);
769
      }
770
    }
750 771

  
751 772
    // Perform the flagging or unflagging of this flag.
752
    $existing_flagging_id = $this->_is_flagged($entity_id, $uid, $sid);
753
    $flagged = (bool) $existing_flagging_id;
754 773
    if ($action == 'unflag') {
755
      if ($this->uses_anonymous_cookies()) {
756
        $this->_unflag_anonymous($entity_id);
757
      }
758 774
      if ($flagged) {
759
        if (!isset($flagging)) {
760
          $flagging = flagging_load($existing_flagging_id);
761
        }
762
        $transaction = db_transaction();
763
        try {
764
          // Note the order: We decrease the count first so hooks have accurate
765
          // data, then invoke hooks, then delete the flagging entity.
766
          $this->_decrease_count($entity_id);
767
          module_invoke_all('flag_unflag', $this, $entity_id, $account, $flagging);
768
          // Invoke Rules event.
769
          if (module_exists('rules')) {
770
            $event_name = 'flag_unflagged_' . $this->name;
771
            // We only support flags on entities.
772
            if (entity_get_info($this->entity_type)) {
773
              $variables = array(
774
                'flag' => $this,
775
                'flagged_' . $this->entity_type => $entity_id,
776
                'flagging_user' => $account,
777
                'flagging' => $flagging,
778
              );
779
              rules_invoke_event_by_args($event_name, $variables);
780
            }
781
          }
782
          $this->_delete_flagging($flagging);
783
          $this->_unflag($entity_id, $flagging->flagging_id);
784
        }
785
        catch (Exception $e) {
786
          $transaction->rollback();
787
          watchdog_exception('flag', $e);
788
          throw $e;
789
        }
775
        $this->flagging_delete($flagging, $entity_id, $account);
790 776
      }
777
      // We do nothing in the case of an attempt to unflag something that isn't
778
      // actually flagged.
791 779
    }
792 780
    elseif ($action == 'flag') {
793
      if ($this->uses_anonymous_cookies()) {
794
        $this->_flag_anonymous($entity_id);
795
      }
796

  
797
      // By definition there is no flagging entity yet, but we may have been
798
      // passed one in to save.
799
      if (!isset($flagging)) {
800
        // Construct a new flagging object if we weren't passed one.
801
        $flagging = $this->new_flagging($entity_id, $uid, $sid);
802
      }
803

  
804
      // Invoke hook_entity_presave().
805
      // In the case that we have been passed in a flagging entity to update,
806
      // this is technically still a presave, even though the {flagging} table
807
      // itself is not changed.
808
      module_invoke_all('entity_presave', $flagging, 'flagging');
809

  
810 781
      if (!$flagged) {
811
        // The entity is unflagged.
812

  
813
        // Save the flagging entity (just our table).
814
        $this->_flag($flagging);
815
        $this->_increase_count($entity_id);
816
        // We're writing out a flagging entity even when we aren't passed one
817
        // (e.g., when flagging via JavaScript toggle links); in this case
818
        // Field API will assign the fields their default values.
819
        $this->_insert_flagging($flagging);
820
        module_invoke_all('flag_flag', $this, $entity_id, $account, $flagging);
821
        // Invoke Rules event.
822
        if (module_exists('rules')) {
823
          $event_name = 'flag_flagged_' . $this->name;
824
          // We only support flags on entities.
825
          if (entity_get_info($this->entity_type)) {
826
            $variables = array(
827
              'flag' => $this,
828
              'flagged_' . $this->entity_type => $entity_id,
829
              'flagging_user' => $account,
830
              'flagging' => $this->get_flagging($entity_id, $account->uid),
831
            );
832
            rules_invoke_event_by_args($event_name, $variables);
833
          }
834
        }
782
        $this->flagging_insert($flagging, $entity_id, $account);
835 783
      }
836 784
      else {
837
        // Nothing to do. Item is already flagged.
838
        //
839
        // Except in the case a $flagging object is one that was passed in: in
840
        // this case we're being requested to update the flagging. This occurs,
841
        // for example, when the user updates the flagging entity form.
842
        if (!empty($flagging->flagging_id)) {
843
          $this->_update_flagging($flagging);
844
        }
785
        $this->flagging_update($flagging, $entity_id, $account);
845 786
      }
846 787
    }
847 788

  
......
849 790
  }
850 791

  
851 792
  /**
852
   * The entity CRUD methods _{insert,update,delete}_flagging() are for private
853
   * use by the flag() method.
793
   * Create a new Flagging to flag an entity.
854 794
   *
855
   * The reason programmers should not call them directly is because a flagging
856
   * operation is also accompanied by some bookkeeping (calling hooks, updating
857
   * counters) or access control. These tasks are handled by the flag() method.
795
   * @param $flagging
796
   *  The flagging entity that is to be removed.
797
   * @param $entity_id
798
   *  The entity ID of entity being unflagged.
799
   * @param $account
800
   *  The account performing the unflagging.
858 801
   */
859
  private function _insert_flagging($flagging) {
802
  private function flagging_insert($flagging, $entity_id, $account) {
803
    if ($this->uses_anonymous_cookies()) {
804
      $this->_flag_anonymous($entity_id);
805
    }
806

  
807
    // Invoke presave hooks.
860 808
    field_attach_presave('flagging', $flagging);
809
    // Invoke hook_entity_presave().
810
    module_invoke_all('entity_presave', $flagging, 'flagging');
811

  
812
    // Set the timestamp.
813
    $flagging->timestamp = REQUEST_TIME;
814

  
815
    // Save the flagging entity.
816
    drupal_write_record('flagging', $flagging);
817

  
818
    // Clear various caches; we don't want code running after us to report
819
    // wrong counts or false flaggings.
820
    drupal_static_reset('flag_get_user_flags');
821
    drupal_static_reset('flag_get_entity_flags');
822
    // Despite being named in the same pattern as the count API functions, these
823
    // query the {flagging} table, so are reset here.
824
    drupal_static_reset('flag_get_entity_flag_counts');
825
    drupal_static_reset('flag_get_user_flag_counts');
826

  
827
    $this->_increase_count($entity_id);
828
    // We're writing out a flagging entity even when we aren't passed one
829
    // (e.g., when flagging via JavaScript toggle links); in this case
830
    // Field API will assign the fields their default values.
831

  
832
    // Invoke insert hooks.
861 833
    field_attach_insert('flagging', $flagging);
862 834
    // Invoke hook_entity_insert().
863 835
    module_invoke_all('entity_insert', $flagging, 'flagging');
836

  
837
    module_invoke_all('flag_flag', $this, $entity_id, $account, $flagging);
838
    // Invoke Rules event.
839
    if (module_exists('rules')) {
840
      $this->invoke_rules_event('flag', $flagging, $entity_id, $account);
841
    }
864 842
  }
865
  private function _update_flagging($flagging) {
843

  
844
  /**
845
   * Invoke a Rules event in reaction to a flagging or unflagging.
846
   *
847
   * @param $action
848
   *   Either 'flag' or 'unflag'.
849
   * @param $flagging
850
   *  The flagging entity that is to be removed.
851
   * @param $entity_id
852
   *  The entity ID of entity being unflagged.
853
   * @param $account
854
   *  The account performing the unflagging.
855
   */
856
  protected function invoke_rules_event($action, $flagging, $entity_id, $account) {
857
    // We only support flags on entities: do nothing in this class.
858
    // See flag_entity::invoke_rules_event().
859
    return;
860
  }
861

  
862
  /**
863
   * Update a Flagging.
864
   *
865
   * @param $flagging
866
   *  The flagging entity that is to be removed.
867
   * @param $entity_id
868
   *  The entity ID of entity being unflagged.
869
   * @param $account
870
   *  The account performing the unflagging.
871
   */
872
  private function flagging_update($flagging, $entity_id, $account) {
873
    // Invoke presave hooks.
874
    // This is technically still a presave, even though the {flagging} table
875
    // itself is not changed.
866 876
    field_attach_presave('flagging', $flagging);
867
    field_attach_update('flagging', $flagging);
868
    // Update the cache.
869
    entity_get_controller('flagging')->resetCache();
870
    // Invoke hook_entity_update().
871
    // Since there are no fields on the {flagging} table that can be
872
    // meaningfully changed, we don't perform an update on it. However, this
873
    // technically still counts as updating the flagging entity, since we update
874
    // its fields.
875
    module_invoke_all('entity_update', $flagging, 'flagging');
877
    // Invoke hook_entity_presave().
878
    module_invoke_all('entity_presave', $flagging, 'flagging');
879

  
880
    // This check exists solely to preserve previous behaviour with re-flagging.
881
    // TODO: consider removing it.
882
    if (!empty($flagging->given_as_parameter)) {
883
      field_attach_update('flagging', $flagging);
884
      // Update the cache.
885
      entity_get_controller('flagging')->resetCache();
886
      // Invoke hook_entity_update().
887
      // Since there are no fields on the {flagging} table that can be
888
      // meaningfully changed, we don't perform an update on it. However, this
889
      // technically still counts as updating the flagging entity, since we update
890
      // its fields.
891
      module_invoke_all('entity_update', $flagging, 'flagging');
892
    }
876 893
  }
877
  private function _delete_flagging($flagging) {
878
    field_attach_delete('flagging', $flagging);
879
    // Remove from the cache.
880
    entity_get_controller('flagging')->resetCache();
881
    // Invoke hook_entity_delete().
882
    module_invoke_all('entity_delete', $flagging, 'flagging');
894

  
895
  /**
896
   * Unflag an entity by deleting a Flagging.
897
   *
898
   * @param $flagging
899
   *  The flagging entity that is to be removed.
900
   * @param $entity_id
901
   *  The entity ID of entity being unflagged.
902
   * @param $account
903
   *  The account performing the unflagging.
904
   */
905
  private function flagging_delete($flagging, $entity_id, $account) {
906
    if ($this->uses_anonymous_cookies()) {
907
      $this->_unflag_anonymous($entity_id);
908
    }
909

  
910
    $transaction = db_transaction();
911
    try {
912
      // Note the order: We decrease the count first so hooks have accurate
913
      // data, then invoke hooks, then delete the flagging entity.
914
      $this->_decrease_count($entity_id);
915
      module_invoke_all('flag_unflag', $this, $entity_id, $account, $flagging);
916
      // Invoke Rules event.
917
      if (module_exists('rules')) {
918
        $this->invoke_rules_event('unflag', $flagging, $entity_id, $account);
919
      }
920

  
921
      // Invoke hook_entity_delete().
922
      module_invoke_all('entity_delete', $flagging, 'flagging');
923
      // Delete field data.
924
      field_attach_delete('flagging', $flagging);
925

  
926
      // Delete the flagging entity.
927
      db_delete('flagging')->condition('flagging_id', $flagging->flagging_id)->execute();
928

  
929
      // Remove from the cache.
930
      entity_get_controller('flagging')->resetCache();
931

  
932
      // Clear various caches; we don't want code running after us to report
933
      // wrong counts or false flaggings.
934
      drupal_static_reset('flag_get_user_flags');
935
      drupal_static_reset('flag_get_entity_flags');
936
      // Despite being named in the same pattern as the count API functions, these
937
      // query the {flagging} table, so are reset here.
938
      drupal_static_reset('flag_get_entity_flag_counts');
939
      drupal_static_reset('flag_get_user_flag_counts');
940
    }
941
    catch (Exception $e) {
942
      $transaction->rollback();
943
      watchdog_exception('flag', $e);
944
      throw $e;
945
    }
883 946
  }
884 947

  
885 948
  /**
......
986 1049
      ->fetchField();
987 1050
  }
988 1051

  
989
  /**
990
   * A low-level method to flag an object.
991
   *
992
   * You probably shouldn't call this raw private method: call the flag()
993
   * function instead.
994
   *
995
   * @param
996
   *   The flagging record.
997
   *
998
   * @private
999
   */
1000
  function _flag($flagging) {
1001
    // Set the timestamp.
1002
    $flagging->timestamp = REQUEST_TIME;
1003

  
1004
    drupal_write_record('flagging', $flagging);
1005

  
1006
    // Clear various caches; we don't want code running after us to report
1007
    // wrong counts or false flaggings.
1008
    drupal_static_reset('flag_get_user_flags');
1009
    drupal_static_reset('flag_get_entity_flags');
1010
    // Despite being named in the same pattern as the count API functions, these
1011
    // query the {flagging} table, so are reset here.
1012
    drupal_static_reset('flag_get_entity_flag_counts');
1013
    drupal_static_reset('flag_get_user_flag_counts');
1014
  }
1015

  
1016
  /**
1017
   * A low-level method to unflag an object.
1018
   *
1019
   * You probably shouldn't call this raw private method: call the flag()
1020
   * function instead.
1021
   *
1022
   * @private
1023
   */
1024
  function _unflag($entity_id, $flagging_id) {
1025
    db_delete('flagging')->condition('flagging_id', $flagging_id)->execute();
1026

  
1027
    // Clear various caches; we don't want code running after us to report
1028
    // wrong counts or false flaggings.
1029
    drupal_static_reset('flag_get_user_flags');
1030
    drupal_static_reset('flag_get_entity_flags');
1031
    // Despite being named in the same pattern as the count API functions, these
1032
    // query the {flagging} table, so are reset here.
1033
    drupal_static_reset('flag_get_entity_flag_counts');
1034
    drupal_static_reset('flag_get_user_flag_counts');
1035
  }
1036

  
1037 1052
  /**
1038 1053
   * Increases the flag count for an object and clears the static counts cache.
1039 1054
   *
......
1043 1058
   *   The amount of counts to increasing. Defaults to 1.
1044 1059
   *
1045 1060
   * @private
1046
  */
1061
   */
1047 1062
  function _increase_count($entity_id, $number = 1) {
1048 1063
    db_merge('flag_counts')
1049 1064
      ->key(array(
......
1076 1091
   *   The amount of counts to decrease. Defaults to 1.
1077 1092
   *
1078 1093
   * @private
1079
  */
1094
   */
1080 1095
  function _decrease_count($entity_id, $number = 1) {
1081 1096
    // Delete rows with count 0, for data consistency and space-saving.
1082 1097
    // Done before the db_update() to prevent out-of-bounds errors on "count".
......
1164 1179
   * @param $entity_id
1165 1180
   *   The ID in whose context to interpret tokens. If not given, only global
1166 1181
   *   tokens will be substituted.
1182
   *
1167 1183
   * @return
1168 1184
   *   The processed label.
1169 1185
   */
......
1511 1527
   * @param $variables = array()
1512 1528
   *  An array of further variables to pass to theme('flag'). For the full list
1513 1529
   *  of parameters, see flag.tpl.php. Of particular interest:
1514
   *  - after_flagging: Set to TRUE if this flag link is being displayed as the result
1515
   *    of a flagging action.
1530
   *  - after_flagging: Set to TRUE if this flag link is being displayed as the
1531
   *    result of a flagging action.
1516 1532
   *  - errors: An array of error messages.
1517 1533
   *
1518 1534
   * @return

Formats disponibles : Unified diff