activity_stream-1.0.x-dev/src/Helper.php
src/Helper.php
<?php declare(strict_types = 1);
namespace Drupal\activity_stream;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\activity_stream\ActivityDestinationInterface;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\field\FieldConfigInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\user\UserInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\activity_stream\ActivityConfigInterface;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemList;
/**
* @todo Add class description.
*/
final class Helper {
use LoggerChannelTrait;
use StringTranslationTrait;
/**
* Constructs a Helper object.
*/
public function __construct(
private readonly EntityTypeManagerInterface $entityTypeManager,
private readonly EntityFieldManagerInterface $entityFieldManager,
private readonly ConfigFactoryInterface $configFactory,
) {}
/**
* Create activity
*
* @param [type] $entity
* @param [type] $recipients
* @param [type] $destinations
* @param [type] $activity_date
* @return void
*/
public function createActivity($entity, $recipients, $destinations, $activity_date = NULL): void {
// Read the entity Type from the Entity
$entity_type_id = $entity->getEntityTypeId();
// Read current user
$current_user = \Drupal::currentUser();
$storage_activity = $this->entityTypeManager->getStorage('activity_stream_activity')->create();
$storage_activity->field_activity_entity->target_type = $entity_type_id;
$storage_activity->field_activity_entity->target_id = $entity->id();
$users = $this->entityTypeManager->getStorage('user')->loadMultiple($recipients);
if ($activity_date !== NULL) {
$storage_activity->set('field_activity_date', $activity_date);
}
else {
$storage_activity->set('field_activity_date', time());
}
if (isset($users) && is_array($users) && !empty($users)) {
foreach($users as $user) {
$storage_activity->field_activity_recipient_user[] = $user->id();
}
}
if(isset($destinations) && is_array($destinations) && !empty($destinations)) {
foreach($destinations as $key => $destination) {
if ($this->validateDestination($destination)) {
$storage_activity->field_activity_destinations[] = $destination;
}
}
}
$violations = $storage_activity->validate();
if ($violations->count() > 0) {
$this->getLogger('activity_stream')->error('Activity was not created due to validation errors. This usally happens when you miss out some required fields.');
}
else {
$storage_activity->save();
}
}
/**
* Validate destination
*
* @param [type] $destination
* @return boolean
*/
public function validateDestination($destination): bool {
$activity_destination = $this->entityTypeManager->getStorage('activity_destination')->load($destination);
if ($activity_destination instanceof ActivityDestinationInterface) {
return TRUE;
}
return FALSE;
}
/**
* Get supported content entities.
*
* @return array
* Options of content entities.
*/
public function getSupportedContentEntities() {
$entity_type_manager = $this->entityTypeManager;
$options = [];
foreach ($entity_type_manager->getDefinitions() as $entity_id => $entity_type) {
// Content entity.
if ($entity_type instanceof ContentEntityTypeInterface
&& $entity_id !== 'activity'
&& $entity_id !== 'message'
&& $entity_id !== 'message_template') {
$entity_type_bundle_info = \Drupal::service('entity_type.bundle.info');
$config_entity_bundles = $entity_type_bundle_info->getBundleInfo($entity_type->id());
foreach ($config_entity_bundles as $key => $value) {
// Dot character in key names is not allowed in config, so we use "-".
$options[$entity_id . '-' . $key] = $entity_type->getLabel() . ': ' . $value['label'];
}
}
}
asort($options);
return $options;
}
/**
* Get supported message templates
*
* @return array
* Message templates.
*/
public function getSupportedMessageTemplates() {
$message_templates = [
'_none' => t('Do not use a message template')
];
// Message type storage.
$message_storage = $this->entityTypeManager->getStorage('message_template');
// Check all enabled messages.
foreach ($message_storage->loadByProperties(['status' => '1']) as $key => $message_type) {
if ($this->checkActivityStreamSupport($key)) {
$message_templates[$key] = $key;
}
}
return $message_templates;
}
/**
* Get supported date fields
*
* @param $bundles
* The bundles of an entity.
* @return array
* Supported date fields.
*/
public function getSupportedDateFields($bundles) {
$supported_fields = ['_none' => $this->t('Do not use Entity date field for activity date')];
if (isset($bundles) && is_array($bundles) && !empty($bundles)) {
foreach ($bundles as $key => $bundle) {
$bundle_string = $key;
}
// Check if we have a group relationship
if (str_contains($bundle_string, 'group_relationship')) {
$entity = $this->getGroupRelationshipEntityFromString($bundle_string);
if ($entity instanceof EntityInterface) {
$entity_type_id = $entity->getEntityTypeId();
$entity_bundle = $entity->bundle();
}
}
else {
$entity_type_id = $this->getEntityTypeIdFromString($bundle_string);
$entity_bundle = $this->getEntityBundleFromString($bundle_string);
}
if (isset($entity_type_id) && isset($entity_bundle)) {
// Check on that bundle
$fields = $this->entityFieldManager
->getFieldDefinitions($entity_type_id,
$entity_bundle);
foreach ($fields as $key => $field) {
if ($field->getType() === 'datetime' || $field->getType() === 'smartdate') {
$supported_fields[$key] = $field->getName();
}
}
}
}
return $supported_fields;
}
/**
* Get activity stream supported fields
*
* @return array
* Supported fields by activity stream.
*/
protected function getActivityStreamSupportedFields() {
$supported_fields = NULL;
// Check on that bundle
$fields = $this->entityFieldManager
->getFieldDefinitions('activity_stream_activity','activity_stream_activity');
foreach ($fields as $key => $field) {
$supported_fields[$key] = $key;
}
return $supported_fields;
}
/**
* Get Group Relationship Entity From String.
*
* @param $string
*
* @return object
* The entity object.
*/
protected function getGroupRelationshipEntityFromString($string) {
$entity = NULL;
$plugin_id = str_replace('group_relationship-', '', $string);
$group_relationships = $this->entityTypeManager->getStorage('group_relationship')->loadByProperties(['type' => $plugin_id]);
if ($group_relationship = reset($group_relationships)) {
$entity = $group_relationship->getEntity();
}
return $entity;
}
/**
* Get entity type id from string.
*
* @param $string
* A string containing entity type id and bundle.
* @return string
* The entity type id.
*/
protected function getEntityTypeIdFromString($string) {
$pos = strpos($string, '-');
$entity_type_id = substr($string, 0, $pos);
return $entity_type_id;
}
/**
* Get entity bundle form string.
*
* @param $string
* A string containing entity type id and bundle.
* @return string
* The entity bundle.
*/
protected function getEntityBundleFromString($string) {
$pos = strpos($string, '-') + 1;
$entity_bundle = substr($string, $pos);
return $entity_bundle;
}
/**
* Check activity stream support
*
* @param string $message_type
* The message type.
* @return boolean
* TRUE | FALSE
*/
protected function checkActivityStreamSupport(string $message_type): bool {
$config_storage = $this->entityTypeManager
->getStorage('field_config');
$field_message_context = $config_storage->load("message.$message_type.field_message_context");
if (!$field_message_context instanceof FieldConfigInterface) {
return FALSE;
}
$field_message_destination = $config_storage->load("message.$message_type.field_message_destination");
if (!$field_message_destination instanceof FieldConfigInterface) {
return FALSE;
}
$field_message_related_object = $config_storage->load("message.$message_type.field_message_related_object");
if (!$field_message_related_object instanceof FieldConfigInterface) {
return FALSE;
}
return TRUE;
}
/**
* Check for a valid timestamp
*
* @param string $timestamp
* The timestamp string.
* @return boolean
* TRUE | FALSE
*/
public function isValidTimestamp(string $timestamp) {
return (is_numeric($timestamp) && (int) $timestamp == $timestamp);
}
/**
* Validate entity type
*
* @param string $entity_type_id
* The entity type id as string.
* @return boolean
* TRUE | FALSE
*/
public function isValidEntityType(string $entity_type_id) {
$storage = $this->entityTypeManager->getStorage($entity_type_id);
if (!$storage) {
return FALSE;
}
return TRUE;
}
/**
* Validate entity bundle.
*
* @param string $entity_type_id
* The entity type id.
*
* @param string $entity_bundle
* The entity bundle.
*
* @return boolean
* TRUE | FALSE
*/
public function isValidEntityBundle(string $entity_type_id, string $entity_bundle) {
$storage = $this->entityTypeManager->getStorage($entity_type_id);
if (!$storage) {
return FALSE;
}
else {
$bundle_entity_class = $storage->getEntityClass($entity_bundle);
if (!$bundle_entity_class) {
return FALSE;
}
}
return TRUE;
}
/**
* Validate user UUID
*
* @param string $user_uuid
* The user uuid string.
* @return boolean
* TRUE | FALSE
*/
public function isValidUserUUID(string $user_uuid) {
$users = $this->entityTypeManager->getStorage('user')->loadByProperties(['uuid' => $user_uuid]);
if ($user = reset($users)) {
if ($user instanceof UserInterface) {
return TRUE;
}
}
return FALSE;
}
/**
* Check if activity has been set to direct
*
* @param $activity_config
* The activity config.
* @return boolean
* TRUE | FALSE
*/
public function isActivityDirect($activity_config) {
$direct = FALSE;
// Load Activity config from activity config id
$activity_config = $this->entityTypeManager
->getStorage('activity_config')
->load($activity_config);
if ($activity_config instanceof ActivityConfigInterface) {
if ($activity_config->get('activity_direct')) {
$direct = TRUE;
}
}
return $direct;
}
/**
* Validate sort value
*
* @param string $sort_value
* The sort value.
* @return boolean
* TRUE | FALSE
*/
public function isValidSortValue(string $sort_value) {
if ($sort_value === 'DESC' || $sort_value === 'ASC') {
return TRUE;
}
return FALSE;
}
/**
* Validate sort field
*
* @param string $sort_field
* The sort field.
* @return boolean
* TRUE | FALSE
*/
public function isValidSortField(string $sort_field) {
// Check the possible fields to sort
$fields = $this->getActivityStreamSupportedFields();
if (in_array($sort_field, $fields)) {
return TRUE;
}
return FALSE;
}
/**
* Get back multiple entities.
*
* @param $field
* The field instance.
* @return array
* Data array of fields.
*/
public function getMultipleEntities($field) {
$data = [];
$entities = $field->referencedEntities();
foreach ($entities as $key => $entity) {
if ($entity instanceof EntityInterface && !$entity instanceof ConfigEntityInterface) {
foreach ($entity as $field_key => $field) {
if ($this->isReferenceType($field)) {
$referenced_field = $field->entity;
if ($referenced_field instanceof EntityInterface) {
foreach ($referenced_field as $referenced_field_key => $referenced_field_value) {
$data[$key][$field_key][$referenced_field_key] = $this->getFieldAtrributes($referenced_field_value);
}
}
}
else {
$data[$key][$field_key] = $this->getFieldAtrributes($field);
}
}
}
else {
$data[$key][$entity->id()] = $entity->id();
}
}
return $data;
}
/**
* Validate reference type
*
* @param $field
* The field instance.
* @return boolean
* TRUE | FALSE
*/
public function isReferenceType($field) {
// Only works on object
if (!is_object($field)) {
return FALSE;
}
$field_defintion = $field->getFieldDefinition();
$reference_types = ['entity_reference','dynamic_entity_reference', 'file', 'image'];
if (in_array($field_defintion->getType(), $reference_types)) {
return TRUE;
}
return FALSE;
}
/**
* Get fields form referenced data.
*
* @param $field
* The field instance.
* @return mixed
* FALSE | array
*/
public function isReferenceFieldType($field) {
// Only works on object
if (!is_object($field)) {
return FALSE;
}
$field_defintion = $field->getFieldDefinition();
$reference_types = ['entity_reference','dynamic_entity_reference', 'file', 'image'];
if (in_array($field_defintion->getType(), $reference_types)) {
if ($this->isUnlimited($field_defintion)) {
return $this->getMultipleEntities($field);
}
else {
return $field->entity;
}
}
return FALSE;
}
/**
* Check if field is set to unlimited
*
* @param $field_defintion
* The field defintion.
* @return boolean
* TRUE | FALSE
*/
public function isUnlimited($field_defintion) {
$cardinality = FALSE;
if ($field_defintion->getFieldStorageDefinition()->getCardinality() === -1) {
$cardinality = TRUE;
}
return $cardinality;
}
/**
* Get flat attributes
*
* @param $field_defintion
* The field defintion.
* @return boolean
* TRUE | FALSE
*/
protected function getFlatAttributes($field_defintion) {
$field_types = [
'boolean',
'string',
'email',
'integer',
'language',
'uuid'
];
if (in_array($field_defintion->getType(), $field_types)) {
return TRUE;
}
return FALSE;
}
/**
* Get the field atrributes
*
* @param $field
* The field as object or array.
* @return array
* The field attribute.
*/
protected function getFieldAtrributes($field) {
if (is_object($field) && !$this->isUnlimited($field->getFieldDefinition())) {
if ($this->getFlatAttributes($field->getFieldDefinition())) {
return $field->value;
}
else {
return $field[0];
}
}
return $field;
}
/**
* Get an data array of fields for a given entity.
*
* @param $entity
* The entity
* @return array
* The data array of fields.
*/
public function loadTree($entity) {
$tree = [];
foreach($entity as $field_key => $field) {
// Now check if we need to build a new tree
if ($referenced_field = $this->isReferenceFieldType($entity->get($field_key))) {
if ($referenced_field instanceof EntityInterface) {
$tree[$field_key] = $this->buildTree($referenced_field, 'reference');
}
else {
$tree[$field_key] = $referenced_field;
}
}
else {
$tree[$field_key] = $this->getFieldAtrributes($field);
}
}
return $tree;
}
/**
* Get back data array of fields.
*
* @param $entity
* The entity object.
* @return array
* Data array of fields.
*/
protected function listFields($entity) {
$tree = [];
foreach($entity as $field_key => $field) {
if ($referenced_field = $this->isReferenceFieldType($field)) {
if ($referenced_field instanceof EntityInterface) {
foreach ($referenced_field as $referenced_field_key => $referenced_field_value) {
$tree[$field_key][$referenced_field_key] = $this->getFieldAtrributes($referenced_field_value);
}
}
}
else {
$tree[$field_key] = $this->getFieldAtrributes($field);
}
}
return $tree;
}
/**
* Build a tree by given entity.
*
* @param $entity
* The entity object.
* @return array
* The data array of fields.
*/
protected function buildTree($entity) {
$tree = [];
foreach($entity as $field_key => $field) {
if ($referenced_field = $this->isReferenceFieldType($field)) {
if ($referenced_field instanceof EntityInterface) {
$tree[$field_key] = $this->listFields($referenced_field);
}
else {
$tree[$field_key] = $referenced_field;
}
}
else {
$tree[$field_key] = $this->getFieldAtrributes($field);
}
}
return $tree;
}
}
