class FivestarItem in Fivestar 8
Plugin implementation of the 'fivestar' field type.
Plugin annotation
@FieldType(
id = "fivestar",
label = @Translation("Fivestar rating"),
description = @Translation("Store a rating for this piece of content."),
default_widget = "fivestar_stars",
default_formatter = "fivestar_stars",
)
Hierarchy
- class \Drupal\Core\TypedData\TypedData implements PluginInspectionInterface, TypedDataInterface uses DependencySerializationTrait, StringTranslationTrait, TypedDataTrait
- class \Drupal\Core\TypedData\Plugin\DataType\Map implements \Drupal\Core\TypedData\Plugin\DataType\IteratorAggregate, ComplexDataInterface
- class \Drupal\Core\Field\FieldItemBase implements FieldItemInterface
- class \Drupal\fivestar\Plugin\Field\FieldType\FivestarItem
- class \Drupal\Core\Field\FieldItemBase implements FieldItemInterface
- class \Drupal\Core\TypedData\Plugin\DataType\Map implements \Drupal\Core\TypedData\Plugin\DataType\IteratorAggregate, ComplexDataInterface
Expanded class hierarchy of FivestarItem
File
- src/
Plugin/ Field/ FieldType/ FivestarItem.php, line 24
Namespace
Drupal\fivestar\Plugin\Field\FieldTypeView source
class FivestarItem extends FieldItemBase {
/**
* {@inheritdoc}
*/
public static function schema(FieldStorageDefinitionInterface $field_definition) {
return [
'columns' => [
'rating' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE,
'sortable' => TRUE,
],
'target' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE,
],
],
];
}
/**
* {@inheritdoc}
*/
public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
$property_definitions['rating'] = DataDefinition::create('integer')
->setLabel(t('Rating'));
$property_definitions['target'] = DataDefinition::create('integer')
->setLabel(t('Target'));
return $property_definitions;
}
/**
* {@inheritdoc}
*/
public static function mainPropertyName() {
return 'rating';
}
/**
* {@inheritdoc}
*/
public static function defaultFieldSettings() {
return [
'stars' => 5,
'allow_clear' => FALSE,
'allow_revote' => TRUE,
'allow_ownvote' => TRUE,
'rated_while' => 'viewing',
'enable_voting_target' => FALSE,
'target_bridge_field' => '',
'target_fivestar_field' => '',
] + parent::defaultFieldSettings();
}
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return [
'vote_type' => 'vote',
] + parent::defaultStorageSettings();
}
/**
* {@inheritdoc}
*/
public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {
$element = [];
$vote_manager = \Drupal::service('fivestar.vote_manager');
$vote_types_link = Link::createFromRoute($this
->t('here'), 'entity.vote_type.collection')
->toString();
$element['vote_type'] = [
'#type' => 'select',
'#required' => TRUE,
'#title' => $this
->t('Vote type'),
'#options' => $vote_manager
->getVoteTypes(),
'#description' => $this
->t('The vote type this rating will affect. Enter a property on which that this rating will affect, such as <em>quality</em>, <em>satisfaction</em>, <em>overall</em>, etc. You can add new vote type %vote_types_link.', [
'%vote_types_link' => $vote_types_link,
]),
'#default_value' => $this
->getSetting('vote_type'),
'#disabled' => $has_data,
];
return $element;
}
/**
* {@inheritdoc}
*/
public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
$element = [];
$element['stars'] = [
'#type' => 'select',
'#title' => $this
->t('Number of stars'),
'#options' => array_combine(range(1, 10), range(1, 10)),
'#default_value' => $this
->getSetting('stars'),
];
$element['allow_clear'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Allow users to cancel their ratings.'),
'#default_value' => $this
->getSetting('allow_clear'),
'#return_value' => 1,
];
$element['allow_revote'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Allow users to re-vote on already voted content.'),
'#default_value' => $this
->getSetting('allow_revote'),
'#return_value' => 1,
];
$element['allow_ownvote'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Allow users to vote on their own content.'),
'#default_value' => $this
->getSetting('allow_ownvote'),
'#return_value' => 1,
];
$element['rated_while'] = [
'#type' => 'radios',
'#default_value' => $this
->getSetting('rated_while'),
'#title' => $this
->t('Select when user can rate the field'),
'#options' => [
'viewing' => 'Rated while viewing',
'editing' => 'Rated while editing',
],
];
$element['enable_voting_target'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Set voting target'),
'#default_value' => $this
->getSetting('enable_voting_target'),
];
$states = [
'visible' => [
':input[name="settings[enable_voting_target]"]' => [
'checked' => TRUE,
],
],
'required' => [
':input[name="settings[enable_voting_target]"]' => [
'checked' => TRUE,
],
],
];
$element['target_bridge_field'] = [
'#type' => 'textfield',
'#title' => $this
->t('Target bridge field'),
'#description' => $this
->t('Machine name of field that binds current entity with entity that contain target fivestar field.
The field should have "entity_reference" type.'),
'#states' => $states,
'#default_value' => $this
->getSetting('target_bridge_field'),
];
$element['target_fivestar_field'] = [
'#type' => 'textfield',
'#title' => $this
->t('Target fivestar field'),
'#description' => $this
->t('Machine name of fivestar field which should affect after vote.'),
'#states' => $states,
'#default_value' => $this
->getSetting('target_fivestar_field'),
];
$element['#element_validate'] = [
[
get_class($this),
'fieldSettingsFormValidate',
],
];
// @todo try to find the way to omit it.
$form_state
->set('host_entity', $this
->getEntity());
return $element;
}
/**
* Validate callback: check field settings.
*/
public static function fieldSettingsFormValidate(array $form, FormStateInterface $form_state) {
$host_entity = $form_state
->get('host_entity');
$field_settings = $form_state
->getValue('settings');
// Validate voting target settings.
if ($field_settings['enable_voting_target'] == 1) {
// Check if bridge field exist.
if (!$host_entity
->hasField($field_settings['target_bridge_field'])) {
$form_state
->setErrorByName('target_bridge_field', t('The host entity doesn\'t contain field: "@field_name"', [
'@field_name' => $field_settings['target_bridge_field'],
]));
return;
}
// Check if bridge field has correct type.
$field_type = $host_entity
->get($field_settings['target_bridge_field'])
->getFieldDefinition()
->getType();
if ($field_type != 'entity_reference') {
$form_state
->setErrorByName('target_bridge_field', t('The bridge field must have "entity_reference" type. The entered field has type: "@field_type"', [
'@field_type' => $field_type,
]));
return;
}
}
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
$rating = $this
->get('rating')
->getValue();
return empty($rating) || $rating == '-';
}
/**
* {@inheritdoc}
*/
public function postSave($update) {
$entity = $this
->getEntity();
$field_definition = $this
->getFieldDefinition();
$field_settings = $field_definition
->getSettings();
$vote_manager = \Drupal::service('fivestar.vote_manager');
$target_entity = $this
->getTargetEntity($entity, $field_settings);
$vote_rating = $entity
->get($field_definition
->getName())->rating ?: 0;
$owner = $this
->getVoteOwner($entity, $field_settings['rated_while']);
if ($update) {
// Delete previous votes.
$criteria = [
'entity_id' => $entity
->id(),
'entity_type' => $entity
->getEntityTypeId(),
'type' => $field_settings['vote_type'],
'user_id' => $owner
->id(),
];
if ($owner
->isAnonymous()) {
$ip_address = \Drupal::request()
->getClientIp();
$criteria['vote_source'] = hash('sha256', serialize($ip_address));
}
foreach ($vote_manager
->getVotesByCriteria($criteria) as $vote) {
$vote
->delete();
}
// Delete votes from target entity.
if (!empty($target_entity)) {
$criteria['entity_id'] = $target_entity
->id();
$criteria['entity_type'] = $target_entity
->getEntityTypeId();
foreach ($vote_manager
->getVotesByCriteria($criteria) as $target_vote) {
$target_vote
->delete();
}
}
}
// Add new vote.
$vote_manager
->addVote($entity, $vote_rating, $field_settings['vote_type'], $owner
->id());
if (!empty($target_entity) && $entity
->isPublished()) {
$vote_manager
->addVote($target_entity, $vote_rating, $field_settings['vote_type'], $owner
->id());
}
// No changes made to the Fivestar field item in this method.
return FALSE;
}
/**
* Get target entity.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* @param array $field_settings
*
* @return \Drupal\Core\Entity\FieldableEntityInterface|null
*/
public function getTargetEntity(FieldableEntityInterface $entity, array $field_settings) {
if ($field_settings['enable_voting_target'] !== TRUE) {
return NULL;
}
if (!$entity
->hasField($field_settings['target_bridge_field'])) {
return NULL;
}
$bridge_entity = $entity->{$field_settings['target_bridge_field']}->entity;
if ($bridge_entity && $bridge_entity
->hasField($field_settings['target_fivestar_field'])) {
return $bridge_entity;
}
return NULL;
}
/**
* {@inheritdoc}
*/
public function delete() {
$del_entity = $this
->getEntity();
$field_settings = $this
->getFieldDefinition()
->getSettings();
$target_entity = $this
->getTargetEntity($del_entity, $field_settings);
if (!$target_entity) {
return;
}
$vote_storage = \Drupal::entityTypeManager()
->getStorage('vote');
$votes = $vote_storage
->loadByProperties([
'entity_type' => $del_entity
->getEntityTypeId(),
'entity_id' => $del_entity
->id(),
]);
foreach ($votes as $vote) {
// Get target vote.
$target_votes = $vote_storage
->loadByProperties([
'entity_type' => $target_entity
->getEntityTypeId(),
'entity_id' => $target_entity
->id(),
'type' => $vote
->bundle(),
'user_id' => $vote
->getOwnerId(),
'value' => $vote
->getValue(),
'vote_source' => $vote
->getSource(),
]);
foreach ($target_votes as $target_vote) {
$target_vote
->delete();
}
}
}
/**
* Get owner for vote.
*
* In order to get correct vote owner need to do it based on fivestar field
* settings, when selected "Rating mode viewing" mode, then have to use
* current user. For "Rating mode editing" mode - if entity have method
* "getOwner" use entity owner, otherwise the current user has to be used.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity from which try to get owner.
* @param string $rating_mode
* Determines under what conditions a user can leave a review.
*
* @return \Drupal\Core\Session\AccountInterface
* The account of the vote owner.
*/
protected function getVoteOwner(FieldableEntityInterface $entity, $rating_mode) {
switch ($rating_mode) {
case 'editing':
if ($entity instanceof EntityOwnerInterface) {
return $entity
->getOwner();
}
// Fall through.
case 'viewing':
default:
return \Drupal::currentUser();
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FieldItemBase:: |
public static | function |
Calculates dependencies for field items. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public static | function |
Calculates dependencies for field items on the storage level. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public | function |
Defines custom revision delete behavior for field values. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public static | function |
Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public static | function |
Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public static | function |
Generates placeholder field values. Overrides FieldItemInterface:: |
18 |
FieldItemBase:: |
public | function |
Gets the entity that field belongs to. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Gets the field definition. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Gets the langcode of the field values held in the object. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
protected | function | Returns the value of a field setting. | |
FieldItemBase:: |
protected | function | Returns the array of field settings. | |
FieldItemBase:: |
public static | function |
Informs the plugin that a dependency of the field will be deleted. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public | function |
Defines custom presave behavior for field values. Overrides FieldItemInterface:: |
7 |
FieldItemBase:: |
public | function |
Sets the data value. Overrides Map:: |
4 |
FieldItemBase:: |
public static | function |
Returns a settings array in the field type's canonical representation. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public static | function |
Returns a settings array that can be stored as a configuration value. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public | function |
Returns a renderable array for a single field item. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
protected | function |
Different to the parent Map class, we avoid creating property objects as
far as possible in order to optimize performance. Thus we just update
$this->values if no property object has been created yet. Overrides Map:: |
|
FieldItemBase:: |
public | function |
Constructs a TypedData object given its definition and context. Overrides TypedData:: |
1 |
FieldItemBase:: |
public | function |
Magic method: Gets a property value. Overrides FieldItemInterface:: |
2 |
FieldItemBase:: |
public | function |
Magic method: Determines whether a property is set. Overrides FieldItemInterface:: |
|
FieldItemBase:: |
public | function |
Magic method: Sets a property value. Overrides FieldItemInterface:: |
1 |
FieldItemBase:: |
public | function |
Magic method: Unsets a property. Overrides FieldItemInterface:: |
|
FivestarItem:: |
public static | function |
Defines the field-level settings for this plugin. Overrides FieldItemBase:: |
|
FivestarItem:: |
public static | function |
Defines the storage-level settings for this plugin. Overrides FieldItemBase:: |
|
FivestarItem:: |
public | function |
Defines custom delete behavior for field values. Overrides FieldItemBase:: |
|
FivestarItem:: |
public | function |
Returns a form for the field-level settings. Overrides FieldItemBase:: |
|
FivestarItem:: |
public static | function | Validate callback: check field settings. | |
FivestarItem:: |
public | function | Get target entity. | |
FivestarItem:: |
protected | function | Get owner for vote. | |
FivestarItem:: |
public | function |
Determines whether the data structure is empty. Overrides Map:: |
|
FivestarItem:: |
public static | function |
Returns the name of the main property, if any. Overrides FieldItemBase:: |
|
FivestarItem:: |
public | function |
Defines custom post-save behavior for field values. Overrides FieldItemBase:: |
|
FivestarItem:: |
public static | function |
Defines field item properties. Overrides FieldItemInterface:: |
|
FivestarItem:: |
public static | function |
Returns the schema for the field. Overrides FieldItemInterface:: |
|
FivestarItem:: |
public | function |
Returns a form for the storage-level settings. Overrides FieldItemBase:: |
|
Map:: |
protected | property |
The data definition. Overrides TypedData:: |
|
Map:: |
protected | property | The array of properties. | |
Map:: |
protected | property | An array of values for the contained properties. | |
Map:: |
public | function |
Applies the default value. Overrides TypedData:: |
4 |
Map:: |
public | function |
Gets a property object. Overrides ComplexDataInterface:: |
|
Map:: |
public | function | ||
Map:: |
public | function |
Gets an array of property objects. Overrides ComplexDataInterface:: |
|
Map:: |
public | function |
Returns a string representation of the data. Overrides TypedData:: |
|
Map:: |
public | function |
Gets the data value. Overrides TypedData:: |
1 |
Map:: |
public | function |
Overrides TraversableTypedDataInterface:: |
4 |
Map:: |
public | function |
Sets a property value. Overrides ComplexDataInterface:: |
|
Map:: |
public | function |
Returns an array of all property values. Overrides ComplexDataInterface:: |
1 |
Map:: |
public | function | Magic method: Implements a deep clone. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TypedData:: |
protected | property | The property name. | |
TypedData:: |
protected | property | The parent typed data object. | |
TypedData:: |
public static | function |
Constructs a TypedData object given its definition and context. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Gets a list of validation constraints. Overrides TypedDataInterface:: |
9 |
TypedData:: |
public | function |
Gets the data definition. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the name of a property or item. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the parent data structure; i.e. either complex data or a list. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
|
TypedData:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
TypedData:: |
public | function |
Returns the property path of the data. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Returns the root of the typed data tree. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Sets the context of a property or item via a context aware parent. Overrides TypedDataInterface:: |
|
TypedData:: |
public | function |
Validates the currently set data value. Overrides TypedDataInterface:: |
|
TypedDataTrait:: |
protected | property | The typed data manager used for creating the data types. | |
TypedDataTrait:: |
public | function | Gets the typed data manager. | 2 |
TypedDataTrait:: |
public | function | Sets the typed data manager. | 2 |