pigeon_paywall-1.0.x-dev/src/Plugin/Field/FieldFormatter/CheckboxPaywall.php
src/Plugin/Field/FieldFormatter/CheckboxPaywall.php
<?php
namespace Drupal\pigeon_paywall\Plugin\Field\FieldFormatter;
use Drupal\Core\Cache\Context\QueryArgsCacheContext;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Plugin implementation for the Pigeon Paywall formatter.
*
* @FieldFormatter(
* id = "pigeon_paywall_checkbox",
* module = "pigeon_paywall",
* label = @Translation("Pigeon Paywall controller"),
* field_types = {
* "boolean"
* }
* )
*/
class CheckboxPaywall extends FormatterBase {
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected $dateFormatter;
/**
* The HTTP query args from the request.
*
* @var \Drupal\Core\Cache\Context\QueryArgsCacheContext
*/
protected $queryArgs;
/**
* Used for loading field defintiions.
*
* @var \Drupal\Core\Entity\EntityFieldManager
*/
protected $entityFieldManager;
/**
* {@inheritdoc}
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, ConfigFactoryInterface $config_factory, DateFormatter $date_formatter, EntityFieldManager $entity_field_manager, QueryArgsCacheContext $query_args) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
$this->configFactory = $config_factory;
$this->dateFormatter = $date_formatter;
$this->entityFieldManager = $entity_field_manager;
$this->queryArgs = $query_args;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['label'],
$configuration['view_mode'],
$configuration['third_party_settings'],
$container->get('config.factory'),
$container->get('date.formatter'),
$container->get('entity_field.manager'),
$container->get('cache_context.url.query_args'),
);
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'bypass_field' => NULL,
];
}
/**
* Build a list of all suitalbe fields on this entity bundle.
*
* @return string[]
* A list of all fields.
*/
protected function getAllFields() {
$field = $this->fieldDefinition;
$entity_type = $field->getTargetEntityTypeId();
$bundle = $field->getTargetBundle();
$fields = $this->entityFieldManager
->getFieldDefinitions($entity_type, $bundle);
// Rework the list to remove unsuitable fields, make it a list of field
// labels.
/**
* @var string $field_name
* @var \Drupal\Core\Field\FieldConfigInterface $field_spec
*/
foreach ($fields as $field_name => $field_spec) {
// Skip Rabbit Hole fields.
if (strpos($field_name, 'rh_') === 0) {
unset($fields[$field_name]);
}
// Skip the title field, that would be just silly.
elseif ($field_name == 'title') {
unset($fields[$field_name]);
}
// Only accept basic string fields.
elseif ($field_spec->getType() != 'string') {
unset($fields[$field_name]);
}
else {
$fields[$field_name] = $this->t('@label (@name)', [
'@label' => $field_spec->getLabel(),
'@name' => $field_name,
]);
}
}
return $fields;
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state);
$form['bypass_field'] = [
'#title' => $this->t('Field to use for paywall bypass code'),
'#description' => $this->t('The paywall may be bypassed by passing the value stored in this field in the URL as the "pigeon" option.'),
'#type' => 'select',
'#options' => $this->getAllFields(),
'#default_value' => $this->getSetting('bypass_field') ?? '',
'#empty_option' => $this->t('- Not used -'),
'#empty_value' => '',
];
return $form;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$return = [
$this->t('Controls whether the paywall will be shown for this page.'),
];
$bypass_field = $this->settings['bypass_field'] ?? '';
if (!empty($bypass_field)) {
$all_fields = $this->getAllFields();
$return[] = $this->t('Bypass field: @field', [
'@field' => $all_fields[$bypass_field] ?? '<em>Unknown field?!?</em>',
]);
}
else {
$return[] = $this->t('No bypass field has been selected.');
}
return $return;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$paywall = FALSE;
// Are any of the checkboxes values enabled?
foreach ($items as $item) {
if (!empty($item->value)) {
$paywall = TRUE;
}
}
// Load the paywall logic if requested.
if ($paywall) {
// Load the global configuration.
// @todo Replace with DI.
$config = $this->configFactory->get('pigeon_paywall.settings');
// Don't bother doing anything if the subdomain value wasn't set.
if ($config->get('subdomain') != '') {
// The entity that this field is attached to.
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $items->getEntity();
$cache_contexts = [];
// Check to see if a bypass field was specified and the field is not
// empty.
if (!empty($this->settings['bypass_field'])) {
$url_key = $config->get('bypass_query_arg');
$cache_contexts = [
'#cache' => [
'contexts' => [
'url.query_args:' . $url_key,
],
],
];
$bypass_field = $this->settings['bypass_field'];
$bypass = $entity->get($bypass_field)->getValue();
if (!empty($bypass[0]['value'])) {
// Look to see if the correct string was passed as an argument to
// the page.
$argument = $this->queryArgs->getContext($url_key);
if ($argument == $bypass[0]['value']) {
return $cache_contexts;
}
}
}
// Only show the interface if the entity is published, or if the
// "published-only" option is not enabled.
if (!method_exists($entity, 'isPublished')
|| $entity->isPublished()
|| !$config->get('published_only')) {
return [
'#attached' => [
'drupalSettings' => [
'pigeon' => [
'subdomain' => trim($config->get('subdomain')),
'fingerprint' => (bool) $config->get('fingerprint'),
'idp' => (bool) $config->get('idp'),
// Use an ID in the format entitytype:entityid, e.g.
// "node:123".
'id' => $entity->getEntityTypeId() . ':' . $entity->id(),
'title' => $entity->label(),
'created' => $this->calculatetime($entity),
],
],
'library' => [
'pigeon_paywall/checkbox_paywall',
],
],
] + $cache_contexts;
}
}
}
return [];
}
/**
* Format the date & time the content was created.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity to process.
*
* @return string
* The entity's creation time value in the required format.
*/
protected function calculatetime(FieldableEntityInterface $entity) {
// Currently this only supports nodes.
if (method_exists($entity, 'getCreatedTime')) {
/** @var \Drupal\node\NodeInterface $entity */
// The time the entity was created.
$time = (int) $entity->getCreatedTime();
// Generate the required output format: 2022-01-01 00:00:00.
return $this->dateFormatter->format($time, 'custom', 'Y-m-d H:i:s');
}
else {
return '';
}
}
}
