/** * Add activity ratio. */ function add_activity_ratio() { /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $schema_repository */ $schema_repository = \Drupal::service('entity.last_installed_schema.repository'); /** @var Drupal\Core\Entity\EntityTypeBundleInfo $entity_bundle_info */ $entity_bundle_info = \Drupal::service('entity_type.bundle.info'); /** @var Drupal\Core\Entity\EntityFieldManager $entity_field_manager */ $entity_field_manager = \Drupal::service('entity_field.manager'); $definitions = \Drupal::entityTypeManager()->getDefinitions(); $entities = []; foreach ($definitions as $entity_type_id => $definition) { if (!$definition instanceof ConfigEntityType) { $entities[] = $entity_type_id; } } $spec = [ 'type' => 'numeric', 'unsigned' => TRUE, 'precision' => 5, 'scale' => 2, ]; $database = \Drupal::database(); $schema = $database->schema(); foreach ($entities as $entity_type_id) { $bundles = $entity_bundle_info->getBundleInfo($entity_type_id); foreach ($bundles as $bundle_id => $bundle) { $field_definitions = $entity_field_manager->getFieldDefinitions($entity_type_id, $bundle_id); foreach ($field_definitions as $field_definition) { if ($field_definition->getType() === 'pos_nace_field_type') { /** @var Drupal\field\Entity\FieldStorageConfig $storage */ $storage = $field_definition->getFieldStorageDefinition(); $storage->setSetting('activity_ratio', FALSE); $key_value = \Drupal::keyValue('entity.storage_schema.sql'); $key_name = $entity_type_id . '.field_schema_data.' . $field_definition->getName(); $storage_schema = $key_value->get($key_name); if ($storage instanceof FieldStorageConfig || $storage->isMultiple()) { foreach ([ $entity_type_id . '__' . $field_definition->getName(), $entity_type_id . '_revision' . '__' . $field_definition->getName(), ] as $table) { $field_name = $field_definition->getName(); if ($schema->tableExists($table) && !$schema->fieldExists($table, $field_name . '_activity_ratio')) { $schema->addField($table, $field_name . '_activity_ratio', $spec); } } } else { $table = $entity_type_id . '_field_data'; $field_name = $field_definition->getName(); if ($schema->tableExists($table) && !$schema->fieldExists($table, $field_name . '__activity_ratio')) { $schema->changeField($table, $field_name, $field_name . '__value', [ 'type' => 'varchar', 'length' => 255, 'binary' => FALSE, ]); $schema->addField($table, $field_name . '__activity_ratio', $spec); $storage_schema[$table]['fields'][$field_name . '__value'] = [ 'type' => 'varchar', 'length' => 255, 'binary' => FALSE, ]; if (isset($storage_schema[$table]['fields'][$field_name])) { unset($storage_schema[$table]['fields'][$field_name]); } $storage_schema[$table]['fields'][$field_name . '__activity_ratio'] = $spec; } } $schema_repository->setLastInstalledFieldStorageDefinition($storage); $key_value->set($key_name, $storage_schema); } } } } }
$database = \Drupal::database(); $entity_type_id = 'basic'; $fields = [ 'employees', 'employees_to_employ', 'average_statistical_number_of_em', ]; foreach ($fields as $field_name) { $old_rows = NULL; $table = $entity_type_id . '__' . $field_name; $new_fields_list = []; $field_storage = FieldStorageConfig::loadByName($entity_type_id, $field_name); if (!$field_storage) { continue; } // Get all current data from DB. if ($database->schema()->tableExists($table)) { // The table data to restore after the update is completed. $old_rows = $database->select($table, 'n') ->fields('n') ->execute() ->fetchAll(); } // Use existing field config for new field. foreach ($field_storage->getBundles() as $bundle => $label) { if ($bundle !== 'partner_data') { continue; } $field = FieldConfig::loadByName($entity_type_id, $bundle, $field_name); $new_field = $field->toArray(); $new_field['field_type'] = 'decimal'; $new_fields_list[] = $new_field; } // Deleting field storage which will also delete bundles(fields). $new_field_storage = $field_storage->toArray(); $new_field_storage['type'] = 'decimal'; $field_storage->delete(); // Purge field data now to allow new field and field_storage with same name // to be created. field_purge_batch(40); // Create new field storage. $new_field_storage = FieldStorageConfig::create($new_field_storage); $new_field_storage->save(); // Create new fields. foreach ($new_fields_list as $new_field) { $new_field_config = FieldConfig::create($new_field); $new_field_config->save(); } // Restore existing data in new table. if ($old_rows) { foreach ($old_rows as $row) { $database->insert($table) ->fields((array) $row) ->execute(); } } }
$pr = \Drupal::entityTypeManager()->getStorage('cfp_payment_request')->load(4221); $pr->setAmountDedicatedToAp(NULL); $pr->set('date_of_completion', NULL); $pr->setState('under_approval'); $pr->save(); $transition_history = $pr->get('transition_history')->getValue(); array_splice($transition_history, -2); $pr->set('transition_history', $transition_history); $pr->set('items_approvement_closed', FALSE); $pr->save();
/** BASE FIELD */ $entity_type_id = 'applicant'; $field_name = 'main_company_address'; $schema = \Drupal::database()->schema(); $schema_repository = \Drupal::service('entity.last_installed_schema.repository'); $key_value = \Drupal::keyValue('entity.storage_schema.sql'); $key_name = $entity_type_id . '.field_schema_data.' . $field_name; $storage_schema = $key_value->get($key_name); $storage_schema['applicant']['fields']['main_company_address__cadastral_municipality'] = [ 'type' => 'varchar', 'length' => 255, 'not null' => FALSE, ]; $key_value->set($key_name, $storage_schema); $schema->addField($entity_type_id, 'main_company_address__cadastral_municipality', $storage_schema['applicant']['fields']['main_company_address__cadastral_municipality']); $entity_field_manager = \Drupal::service('entity_field.manager'); $field_definitions = $entity_field_manager->getBaseFieldDefinitions($entity_type_id); $storage = $field_definitions[$field_name]->getFieldStorageDefinition(); $schema_repository->setLastInstalledFieldStorageDefinition($storage); /** CONFIG FIELD */ $entity_type_id = 'basic'; $field_name = 'cf_settlement'; $schema = \Drupal::database()->schema(); $key_value = \Drupal::keyValue('entity.storage_schema.sql'); $key_name = $entity_type_id . '.field_schema_data.' . $field_name; $storage_schema = $key_value->get($key_name); $storage_schema['basic__cf_settlement']['fields']['cf_settlement_cadastral_municipality'] = [ 'type' => 'varchar', 'length' => 255, 'not null' => FALSE, ]; $key_value->set($key_name, $storage_schema); $schema->addField('basic__cf_settlement', 'cf_settlement_cadastral_municipality', $storage_schema['basic__cf_settlement']['fields']['cf_settlement_cadastral_municipality']);
/** * Implements hook_theme(). */ function application_theme() { return [ 'application_info' => [ 'variables' => [ 'application_type_label' => NULL, 'funding_amount' => NULL, 'application_started' => NULL, 'contact_person' => NULL, 'project_leader' => [ 'first_name' => NULL, 'last_name' => NULL, 'phone' => NULL, ], 'files' => [], 'criteria_link' => NULL, ], ] }
$element = [ '#theme' => 'application_info', '#application_type_label' => $application->getApplicationType()->label(), '#funding_amount' => $application->getFundingAmountPrinted(), '#project_leader' => [ 'first_name' => $advisor_address->given_name, 'last_name' => $advisor_address->family_name, 'phone' => $advisor->get('field_ezs_festnetz_telefon')->value, ], '#files' => [], '#criteria_link' => Url::fromRoute('application.application_files', [ 'application_type' => $application->bundle(), 'file_type' => 'criteria', ])->toString(), // [ // '#type' => 'link', // '#title' => t('Here'), // '#url' => Url::fromRoute('application.application_files', [ // 'application_type' => $application->bundle(), // 'file_type' => 'criteria', // ]) // ], '#cache' => [ 'context' => [ 'user.roles', 'languages:language_interface', ] ] ];
<div class="application-info-block"> <h3>{% trans %}Information{% endtrans %}</h3> <div><span class="field-label">{{ 'Application program'|trans }} {{ application_type_label }}</span></div> {% if funding_amount %} <div><span class="field-label">{{ 'Founding Amount'|trans }} {{ funding_amount }}</span></div> {% endif %} <div><span class="field-label">{{ 'EZS project manager'|trans }}</span> {{ _self.render_person(project_leader) }}</div> {% if contact_person %} <div><span class="field-label">{{ 'Contact'|trans }}</span> {{ _self.render_person(contact_person) }}</div> {% endif %} {% if files %} <label>{{ 'Files'|trans }}</label> <div>{{ files }}</div> {% endif %} <div> {# TODO: Replace for renderable element #} {{ '<a target="_blank" href="@url">Here</a> you will find the latest funding criteria'|trans({'@url': criteria_link }) }} </div> </div> {% macro render_person(person) %} {% if person.company %} <span>{{ person.company }}</span> {% endif %} {% if person.salutation %} <span>{{ person.salutation }}</span> {% endif %} <span>{{ person.first_name }} {{ person.last_name }}</span> {% if person.street %} <span>{{ person.street }}</span> {% endif %} <span> {% if person.postal_code %} {{ person.postal_code }} {% endif %} {% if person.locality %} {{ person.locality }} {% endif %} {% if person.country %} {{ person.country }} {% endif %} </span> {% if person.email %} <span>{{ person.email }}</span> {% endif %} <span>{{ person.phone }} </span> {% if person.availability %} <span>{{ person.availability }}</span> {% endif %} {% endmacro %}
<?php namespace Drupal\cfp_payment_request\Form; use Drupal\cfp_payment_request\Entity\PaymentRequestItem; use Drupal\cfp_payment_request\Entity\PaymentRequestItemType; use Drupal\Component\Serialization\Json; use Drupal\Core\Entity\Display\EntityFormDisplayInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\inline_entity_form\Form\EntityInlineForm; class PaymentRequestItemInlineForm extends EntityInlineForm { const DATA_SOURCE_CLASS = 'pr-data-source'; const DATA_COPY_NAME = 'data-pr-set'; const DATA_NAME_STARTS_WITH = 'data-pr-name-starts-with'; /** * {@inheritdoc} */ public function entityForm(array $entity_form, FormStateInterface $form_state) { $parent_entity = $form_state->getFormObject()->getEntity(); if ($parent_entity->getEntityTypeId() === 'cfp_payment_request') { $entity_form['#entity']->setParent($parent_entity); } $entity = $entity_form['#entity']; $form_display = $this->getFormDisplay($entity, $entity_form['#form_mode']); $this->extraFields($entity_form, $entity, $form_display); $entity_form = parent::entityForm($entity_form, $form_state); $this->attachValuesCopyBehaviour($entity_form, $parent_entity); return $entity_form; } /** * {@inheritdoc} */ public function isTableDragEnabled($element) { return FALSE; } protected function extraFields(&$form, PaymentRequestItem $entity, EntityFormDisplayInterface $form_display) { if ($form_display->getComponent('item_support_intensity') && $form_display->getComponent('cost_item_name')) { $form['#after_build'][] = '\Drupal\cfp_payment_request\Form\PaymentRequestItemInlineForm::statesToSupportIntensity'; $form['item_support_intensity'] = [ '#type' => 'container', ]; $entity = $form['#entity']; if (($pr = $entity->getParent()) && ($cfp = $pr->getParent())) { $name = 'will_be_build_after'; /** @var \Drupal\pos_entity_cost_item\AdditionalCostItem $items */ $items = $cfp->getWrappedAllItems(FALSE, TRUE); foreach ($items as $item_id => $item) { $form['item_support_intensity'][$item_id] = [ '#type' => 'container', 'contents' => [ '#markup' => '<label>Tételhez kapcsolódó támogatási intenzitás: </label><span class="price">' . $item->getSupportRatio() . '%</span>' ], '#states' => [ 'visible' => [ $name => ['value' => $item_id], ], ], '#attributes' => [ 'class' => ['item-support-intensity'] ], ]; } } } if ($form_display->getComponent('participation_type')) { $payment_request = $entity->getParent(); $cfp = $entity->getCfp(); $cost_item = $cfp->getCostItemEntities(); $cost_item = reset($cost_item); $own_participation = $cost_item->get('cost_item_participation'); if ($own_participation_value = $own_participation->value) { $own_participation_definition = $cost_item->getFieldDefinition('cost_item_participation'); $own_participation_label = $own_participation_definition->getSettings()['allowed_values'][$own_participation_value]; } $form['participation_type'] = [ '#type' => 'markup', '#markup' => '<div class="own-participation"><b>Vrsta sopstvenog učešća: </b>' . $own_participation_label . '</div>', '#weight' => 10, ]; } $payment_request_item_type = PaymentRequestItemType::load($entity->bundle()); if (!empty($payment_request_item_type->get('documents_helptext')) && $form_display->getComponent('documents_helptext')) { $helptext = $payment_request_item_type->get('documents_helptext'); $form['documents_helptext'] = [ '#type' => 'container', 'helptext' => [ '#type' => 'markup', '#markup' => '<div class="documents_helptext">' . $helptext . '</div>', ], ]; } } public static function statesToSupportIntensity($form, FormStateInterface $form_state) { if (isset($form['cost_item_name']['widget']['#name']) && isset($form['item_support_intensity'])) { $name = $form['cost_item_name']['widget']['#name']; foreach ($form['item_support_intensity'] as $item_id => &$element) { if (isset($element['#states']['visible'])) { $element['#states']['visible'] = [ '[name="' . $name . '"]' => ['value' => $item_id], ]; } } } // if (isset($form['cost_item_name']['widget']['#name'])) { // $entity = $form['#entity']; // if (($pr = $entity->getParent()) && ($cfp = $pr->getParent())) { // $name = $form['cost_item_name']['widget']['#name']; // /** @var \Drupal\pos_entity_cost_item\AdditionalCostItem $items */ // $items = $cfp->getWrappedAllItems(FALSE, TRUE); // // foreach ($items as $item_id => $item) { // // $form['item_support_intensity'][$item_id] = [ // '#type' => 'container', // 'contents' => [ // '#markup' => $item->getSupportRatio(), // ], // '#states' => [ // 'visible' => [ // '[name="' . $name . '"]' => ['value' => $item_id], // ], // ] // ]; // } // } // } return $form; } /** * @param $entity_form * */ protected function attachValuesCopyBehaviour(&$entity_form, $parent_entity) { if (isset($entity_form['cost_item_name']['widget'])) { $entity_form['cost_item_name']['widget']['#attributes']['class'][] = self::DATA_SOURCE_CLASS; $entity_form['cost_item_name']['widget']['#after_build'][] = '\Drupal\cfp_payment_request\Form\PaymentRequestItemInlineForm::constructNameStartsWithAfterBuild'; } else { return; } /** @var \Drupal\pos_entity_cfp\Entity\Cfp $cfp */ $cfp = $parent_entity->getParent(); $wrapped_items = $cfp->getWrappedAllItems(FALSE, TRUE); /** * Second parameter is either method for wrapped item, or field name of cost * item. * * @var $field_mapper */ $field_mapper = [ 'cf_manufacturer' => 'cost_item_manufacturer', 'cf_unique_item_id' => 'cost_item_identificator', 'cf_distributor' => 'cost_item_distributor', 'cf_distributor_vat_number' => 'cost_item_vat_number', 'cf_distributor_bank_account_num' => 'cost_item_distributor_account', 'item_support' => 'getSupportValue', 'item_pay_off' => 'getEligibleCost', 'item_net_unit' => 'cost_item_neto_price', 'item_unit_vat' => 'cost_item_vat', 'item_quantity' => 'cost_item_quantity', ]; foreach ($field_mapper as $value_field_name => $method_or_field) { $values = []; if (!isset($entity_form[$value_field_name]['widget'][0]['value'])) { continue; } foreach ($wrapped_items as $id => $wrapped_item) { if (method_exists($wrapped_item, $method_or_field)) { // $wrapped_item->getEligibleCost(); $values[$id] = $wrapped_item->$method_or_field(); } elseif ($wrapped_item->getCostItem()?->hasField($method_or_field)) { $values[$id] = $wrapped_item->getCostItem()->get($method_or_field)->value; } } $entity_form[$value_field_name]['widget'][0]['value']['#attributes'][self::DATA_COPY_NAME] = Json::encode($values); } $entity_form['#attached']['library'][] = 'cfp_payment_request/pr_item_autopopulate.js'; } /** * Constructs name starts with for inline entity form. */ public static function constructNameStartsWithAfterBuild($element, FormStateInterface $form_state) { $name_starts_with = explode('['. $element['#field_name'] . ']', $element['#name'])[0]; $element['#attributes'][self::DATA_NAME_STARTS_WITH] = $name_starts_with; return $element; } }
(function (Drupal, once) { 'use strict'; const DATA_COPY_NAME = 'data-pr-set'; const DATA_SOURCE_CLASS = 'pr-data-source'; const DATA_NAME_STARTS_WITH = 'data-pr-name-starts-with'; const handleCopy = (context, value, name_starts_with) => { context.querySelectorAll(`[name^="${name_starts_with}"][${DATA_COPY_NAME}]`).forEach((element) => { const values = JSON.parse(element.getAttribute(DATA_COPY_NAME)); if (values.hasOwnProperty(value)) { setElementValue(element, values[value]); } else { setElementValue(element); } }); } const setElementValue = (element, value) => { if (element.classList.contains('mask-money--apply')) { // element.value = value; Drupal.behaviors.autoCalculateFormulaBehaviour.setValue(element.getAttribute('name'), value === undefined ? 0 : parseFloat(value)); } else { element.value = value === undefined ? '' : value; const event = new Event('change'); element.dispatchEvent(event); } } Drupal.behaviors.copyItemValues = { attach: (context) => { once('copy-item-values', `.${DATA_SOURCE_CLASS}`, context).forEach((element) => { element.addEventListener('change', (event) => { handleCopy(context, event.target.value, event.target.getAttribute(DATA_NAME_STARTS_WITH)); }); }); } } })(Drupal, once);
<?php namespace Drupal\pos_field_address; use Drupal\Core\Cache\Cache; use Drupal\Component\Serialization\Yaml; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Messenger\MessengerInterface; /** * Class PosAddressConfigBuilder. */ class PosAddressConfigBuilder { const COUNTRIES = 'countries.yml'; /** * Cache backend. * * @var \Drupal\Core\Cache\CacheBackendInterface */ protected $cache; /** * Messenger. * * @var \Drupal\Core\Messenger\MessengerInterface */ protected $messenger; /** * PosAddressConfigBuilder constructor. * * @param \Drupal\Core\Cache\CacheBackendInterface $cache * Cache. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * Messenger. */ public function __construct(CacheBackendInterface $cache, MessengerInterface $messenger) { $this->cache = $cache; $this->messenger = $messenger; } /** * Parse file. * * @param string $file * Filename. * * @return bool|mixed * File content. */ private function parseFile($file) { $cache_name = 'address__' . str_replace('.yml', '', $file); if ($cached = $this->cache->get($cache_name)) { return $cached->data; } $path = realpath(__DIR__) . '/../values/' . $file; if (!is_file($path)) { return FALSE; } $content = file_get_contents($path); if ($content === FALSE) { return $content; } $content = Yaml::decode($content); $this->cache->set($cache_name, $content, Cache::PERMANENT); return $content; } /** * Get country codes. * * @return array * Country codes. */ public function getCountryCodes() { return array_keys($this->getCountriesDetailed()); } /** * Get country list. * * @param array $allowed_countries * Allowed countries. * * @return array|bool|mixed * Countries. */ public function getCountries(array $allowed_countries = []) { $countries = $this->getCountriesDetailed(); foreach ($countries as $country_code => $country) { if (empty($allowed_countries) || in_array($country_code, $allowed_countries)) { $countries[$country_code] = $country['country']; } else { unset($countries[$country_code]); } } return $countries; } /** * Detailed country data. * * @return array|bool|mixed * Data. */ public function getCountriesDetailed() { $countries_detailed = &drupal_static('address_countries_detailed'); if (!isset($countries_detailed)) { $countries_detailed = $this->parseFile(self::COUNTRIES); } return $countries_detailed; } /** * Country schema. * * @param string $country_code * Country code. * * @return bool|mixed * Schema. */ public function getCountrySchema($country_code, $force_input_schema = FALSE) { $countries = $this->getCountriesDetailed(); if ($countries === FALSE || !array_key_exists($country_code, $countries)) { return FALSE; } if ($force_input_schema) { return ['input' => t('Input')]; } return $countries[$country_code]['schema']; } public function isOriginallyInputCountrySchema($country_code) { $schema = $this->getCountrySchema($country_code); if ($schema === FALSE) { return TRUE; } return array_key_exists('input', $schema); } /** * Check if country schema exists. * * @param string $country_code * Country code. * * @return bool * Does schema exist? */ public function countrySchemaExists($country_code) { $countries = $this->getCountriesDetailed(); if ($countries === FALSE || !array_key_exists($country_code, $countries)) { return FALSE; } return TRUE; } /** * Returns tree for single country. */ public function getTree($country_code) { $tree = &drupal_static('address_countries_schema_' . $country_code); if (!isset($tree)) { $tree = $this->parseFile($country_code . '.yml'); } if ($tree === FALSE) { return []; } return $tree === FALSE ? [] : $tree; } /** * Returns data at depth. */ public function getCurrentDepthData($country_code, $data = [], $filter = FALSE, $filter_cache_context = FALSE, $force_input_schema = FALSE) { $microtime = microtime(TRUE); $tree = $this->cache->get($filter_cache_context); if ($filter !== FALSE && $filter_cache_context !== FALSE && $tree) { $tree = $tree->data; } else { $tree = $this->getTree($country_code); if ($filter !== FALSE) { $this->filterTree($tree, $filter, $country_code); if ($filter_cache_context !== FALSE) { $this->cache->set($filter_cache_context, $tree); } } } $schema = $this->getCountrySchema($country_code, $force_input_schema); if ($schema === FALSE) { return FALSE; } $return_data = []; $current_depth_data = $tree; $return_data['country'] = $tree; if (empty($schema)) { return []; } elseif (key($schema) == 'input') { return $return_data['country']; } do { if (current($data) !== FALSE) { $current_code = current($data); } else { $current_code = key($current_depth_data[key($schema)]); } $current_depth_data = $current_depth_data[key($schema)]; if (!array_key_exists($current_code, $current_depth_data)) { $current_code = key($current_depth_data); } $return_data[key($schema)] = $current_depth_data[$current_code]; $return_data[key($schema)]['code'] = $current_code; $current_depth_data = $current_depth_data[$current_code]; if ((microtime(TRUE) - $microtime) > 2) { $this->messenger->addMessage('Report this problem to administrator'); break; } next($data); } while (next($schema) !== FALSE); return $return_data; } /** * Filters tree. */ private function filterTree(&$tree, $filter, $country_code) { if (!is_array($filter)) { return $tree; } $schema = $this->getCountrySchema($country_code); foreach ($filter as $key => $value) { if ($value[0] !== $country_code) { unset($filter[$key]); } } foreach ($schema as $schema_key => $label) { $this->unsetUnexisting($tree, $filter, $schema, $schema_key); } } /** * Deletes locations not in filter. */ private function unsetUnexisting(&$tree, $filter, $schema, $schema_key) { $tree_copy = $tree; $filter_key = 1; reset($schema); $this->goToCurrentDepth($tree[key($schema)], $filter, $schema, $filter_key, $schema_key); return $tree_copy; } /** * Go through the depth. * * @param array $tree * Tree. * @param mixed $filter * Filter. * @param array $schema * Schema. * @param mixed $filter_key * Filter key. * @param mixed $schema_key * Schema key. */ private function goToCurrentDepth(array &$tree, &$filter, array &$schema, &$filter_key, $schema_key) { if (key($schema) === $schema_key) { foreach ($tree as $key => $value) { $found = FALSE; foreach ($filter as $filter_code) { if ($filter_code[$filter_key] == $key) { $found = TRUE; break; } } if (!$found) { unset($tree[$key]); } } } else { next($schema); $current_key = key($schema); $filter_key++; $current_filter = $filter_key; foreach ($tree as $code_key => $code) { $this->goToCurrentDepth($tree[$code_key][$current_key], $filter, $schema, $filter_key, $schema_key); $filter_key = $current_filter; reset($schema); while (key($schema) !== $current_key) { next($schema); } } } } /** * Get select schema. * * @param string $country_code * Country code. * * @return array * Schema. */ public function getSelectSchema($country_code) { $tree = $this->getTree($country_code); $schema = $this->getCountrySchema($country_code); $values = []; $codes = []; end($schema); $this->getSubnames($tree, key($schema), $values, $codes, TRUE, $country_code); return array_combine($codes, $values); } /** * Get subnames. * * @param array $current_tree * Current tree. * @param mixed $last_schema_key * Last schema key. * @param array $values * Values. * @param array $codes * Codes. * @param mixed $first * First. * @param string $country_code * Country code. * * @return array * Subnames. */ private function getSubnames(array $current_tree, $last_schema_key, array &$values, array &$codes, $first, $country_code = '') { $keys = array_keys($current_tree); if (!array_key_exists($country_code, $this->getCountriesDetailed())) { $country_name = ''; } else { $country_name = $this->getCountriesDetailed()[$country_code]['country']; } $schema_key = FALSE; foreach ($keys as $key) { if ($key != 'name') { $schema_key = $key; } } $subnames = []; if (empty($current_tree)) { return []; } foreach ($current_tree[$schema_key] as $code => $tree) { if ($first) { $subnames = $this->getSubnames($tree, $last_schema_key, $values, $codes, FALSE); foreach ($subnames as $subname) { $values[] = $country_name . '->' . $tree['name'] . '->' . $subname['name']; $codes[] = $country_code . '{||}' . $code . '{||}' . $subname['code']; } } elseif ($last_schema_key === $schema_key) { $subnames[] = ['name' => $tree['name'], 'code' => $code]; } else { $return_value = $this->getSubnames($tree, $last_schema_key, $values, $codes, FALSE); foreach ($return_value as $subname) { $subnames[] = [ 'name' => $tree['name'] . '->' . $subname['name'], 'code' => $code . '{||}' . $subname['code'], ]; } } } if (!$first) { return $subnames; } } /** * Get all options for country schema element. * * @param string $country_code * Country code. * @param mixed $schema_key * Schema key. * * @return array * Options. */ public function getAllOptionsForCountrySchemaElement($country_code, $schema_key) { $tree = $this->getTree($country_code); $country_schema = $this->getCountrySchema($country_code); $values = []; if (!empty($country_schema)) { $this->getAllValuesToGivenDepth($tree[key($country_schema)], $country_schema, $schema_key, $values); } return $values; } /** * Get all values to given depth. * * @param array $tree * Tree. * @param array $country_schema * Schema. * @param mixed $schema_key * Schema key. * @param array $values * Values. * @param array $current_depth_value * Current value. */ public function getAllValuesToGivenDepth(array $tree, array &$country_schema, $schema_key, array &$values, array $current_depth_value = []) { $current_key_schema = key($country_schema); next($country_schema); foreach ($tree as $value => $sub_tree) { $current_depth_value[$current_key_schema] = (string) $value; if ($schema_key === $current_key_schema) { $values[] = [ 'name' => $sub_tree['name'], 'value' => $current_depth_value, ]; } else { $this->getAllValuesToGivenDepth($sub_tree[key($country_schema)], $country_schema, $schema_key, $values, $current_depth_value); } } prev($country_schema); } /** * Validates if data is valid. */ public function validateValue($country_code, $data) { $tree = $this->getTree($country_code); $schema = $this->getCountrySchema($country_code); if (key($schema) === 'input' && is_string($data)) { return TRUE; } if (count($data) == 0 && !empty($tree)) { return TRUE; } elseif (count($data) == 0 && empty($tree)) { return FALSE; } foreach ($schema as $schema_key => $label) { if (array_key_exists(current($data), $tree[$schema_key])) { $tree = $tree[$schema_key][current($data)]; } else { return FALSE; } if (next($data) === FALSE) { break; } } return TRUE; } /** * Returns all schema keys that exists. */ public function getAllSchemaKeys() { $detailed_countries = $this->getCountriesDetailed(); $all_schema_keys = []; foreach ($detailed_countries as $detailed_country) { foreach ($detailed_country['schema'] as $key => $label) { if (!in_array($key, $all_schema_keys)) { $all_schema_keys[] = $key; } } } return $all_schema_keys; } }
/** * @file * Remove button for the Address field. */ (function ($, Drupal) { 'use strict'; Drupal.behaviors.addressFilterBehaviour = { attach: function (context) { $('.address-filer-country').once('address-filter-behaviour').on('change', function () { let countryElement = $(this); $.get('/pos_field_address/country-schema?country=' + $(this).val(), function (data) { let element = $(countryElement.data('schema-selector')); element.empty(); $.each(data, function (key,value) { element.append($('<option></option>') .attr('value', key).text(value)); }); element.trigger('change'); }, 'json'); $.get('/pos_field_address/schema-options?country=' + $(this).val() + '&schema=' + 'settlement', function (data) { let newElement = $(countryElement.data('value-selector')); newElement.empty(); $.each(data, function (key, value) { newElement.append($('<option></option>') .attr('value', key).text(value)); }); newElement.trigger('change'); }) }); $('.address-filter-schema').once('address-filter-behaviour').on('change', function () { let schemaElement = $(this); let countryCode = $(schemaElement.data('country-selector')).val(); $.get('/pos_field_address/schema-options?country=' + countryCode + '&schema=' + schemaElement.val(), function (data) { let element = $(schemaElement.data('value-selector')); element.empty(); $.each(data, function (key,value) { element.append($('<option></option>') .attr('value', key).text(value)); }); }, 'json'); }); } }; })(jQuery, Drupal);
<?php namespace Drupal\pos_field_address\Plugin\views\filter; use Drupal\Core\Database\Connection; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\filter\FilterPluginBase; use Drupal\pos_field_address\PosAddressConfigBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a custom filter for filtering by addresses. * * @ingroup views_filter_handlers * @ViewsFilter("pos_address_advance_filter") */ class PosAddressAdvanceFilter extends FilterPluginBase { /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected $connection; /** * Config builder. * * @var \Drupal\pos_field_address\PosAddressConfigBuilder */ protected $configBuilder; /** * {@inheritdoc} */ public $operator = 'LIKE'; /** * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition, Connection $connection, PosAddressConfigBuilder $config_builder) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->connection = $connection; $this->configBuilder = $config_builder; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('database'), $container->get('pos_field_address.config_builder') ); } /** * {@inheritdoc} */ protected function defineOptions() { $options = parent::defineOptions(); $options['operator'] = ['default' => 'LIKE']; return $options; } /** * {@inheritdoc} */ public function buildExposedForm(&$form, FormStateInterface $form_state) { $identifier = $this->options['expose']['identifier']; $exposed_input = $this->view->getExposedInput(); $form[$identifier] = [ '#type' => 'fieldset', '#title' => $this->options['expose']['label'], '#attached' => [ 'library' => [ 'pos_field_address/view-exposed-filter', ], ], ]; $element = &$form[$identifier]; // Define classes. $country_class = str_replace('_', '-', $identifier) . '-country'; $schema_class = str_replace('_', '-', $identifier) . '-schema'; $value_class = str_replace('_', '-', $identifier) . '-value'; // Country element. $countries = $this->configBuilder->getCountries(); $country_code = isset($exposed_input[$identifier . '_country']) ? $exposed_input[$identifier . '_country'] : key($countries); $element[$identifier . '_country'] = [ '#type' => 'select', '#title' => 'Entitet', '#options' => $this->configBuilder->getCountries(), '#attributes' => [ 'class' => ['address-filer-country', $country_class], 'data-schema-selector' => '.' . $schema_class, 'data-value-selector' => '.' . $value_class, ], '#default_value' => $country_code, ]; // Country schema element. $country_schema = $this->configBuilder->getCountrySchema($country_code); $country_schema_key = isset($exposed_input[$identifier . '_country_schema']) ? $exposed_input[$identifier . '_country_schema'] : key($country_schema); // $element[$identifier . '_country_schema'] = [ // '#type' => 'select', // '#title' => $this->t('Search by'), // '#options' => $country_schema, // '#attributes' => [ // 'class' => ['address-filter-schema', $schema_class], // 'data-country-selector' => '.' . $country_class, // 'data-value-selector' => '.' . $value_class, // ], // '#default_value' => $country_schema_key, // ]; // Value element. $values = $this->configBuilder->getAllOptionsForCountrySchemaElement($country_code, $country_schema_key); $options = ['' => $this->t('- None -')]; foreach ($values as $value) { $serialized = serialize($value['value']); $options[str_replace('}', '', substr($serialized, strpos($serialized, '{') + 1))] = $value['name']; } $default_value = isset($exposed_input[$identifier]) ? $exposed_input[$identifier] : NULL; $element[$identifier] = [ '#title' => $this->options['expose']['label'], '#type' => 'select', '#attributes' => [ 'class' => [$value_class, 'address-filter-city'], 'data-schema-selector' => '.' . $schema_class, ], '#options' => $options, '#default_value' => $default_value, ]; } /** * {@inheritdoc} */ public function query() { if (!empty($this->value) && !empty(reset($this->value))) { $this->ensureMyTable(); $this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", '%' . $this->connection->escapeLike(reset($this->value)) . '%', $this->operator); } else if (!empty($this->view->getExposedInput()) && $this->view->getExposedInput()['main_company_address_country'] === 'BD') { $no_settlement = 's:0:""'; $this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", '%' . $this->connection->escapeLike($no_settlement) . '%', $this->operator); } } }
<?php /** * @file * Contains cfp_payment_request.module. */ use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Render\Element; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\cfp_payment_request\Entity\PaymentRequestType; use Drupal\pos_entity_cfp\Entity\CfpType; use Drupal\Core\Entity\EntityTypeInterface; module_load_include('inc', 'cfp_payment_request', 'cfp_payment_request.extra_fields'); module_load_include('inc', 'cfp_payment_request', 'cfp_payment_request.tokens'); \Drupal::moduleHandler()->loadInclude('cfp_payment_request', 'inc', 'cfp_payment_request.validation'); require_once realpath(__DIR__) . '/cfp_payment_request.currency_conv.inc'; /** * Implements hook_help(). */ function cfp_payment_request_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the cfp_payment_request module. case 'help.page.cfp_payment_request': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; $output .= '<p>' . t('Payment Request for CFP') . '</p>'; return $output; default: } } /** * Implements hook_mail(). */ function cfp_payment_request_mail($key, &$message, $params) { switch ($key) { case 'pos_payment_request_mail': $mail_sender = \Drupal::config('system.site')->get('mail'); $message['headers']['From'] = $mail_sender; $message['headers']['Sender'] = $mail_sender; $message['headers']['Return-Path'] = $mail_sender; $message['headers']['Content-Type'] = 'text/html'; $message['from'] = $mail_sender; /** @var \Drupal\Core\Utility\Token $token */ $token = \Drupal::service('token'); $token_data = [ 'cfp_payment_request' => $params['entity'], ]; $message['subject'] = $token->replace($params['title'], $token_data); $message['body'][] = $token->replace($params['message'], $token_data); $email_log = \Drupal::entityTypeManager() ->getStorage('pos_entity_email_logs') ->create([ 'title' => $message['subject'], 'body' => isset($message['body'][0]) ? $message['body'][0] : '', 'cfp' => $params['entity']->get('parent')->target_id, ]); $email_log->save(); break; } } /** * Implements hook_theme(). */ function cfp_payment_request_theme() { $theme = []; $theme['cfp_payment_request'] = [ 'render element' => 'elements', 'file' => 'cfp_payment_request.page.inc', 'template' => 'cfp_payment_request', ]; $theme['cfp_payment_request_content_add_list'] = [ 'render element' => 'content', 'variables' => ['content' => NULL], 'file' => 'cfp_payment_request.page.inc', ]; $theme['cfp_payment_request_item'] = [ 'render element' => 'elements', 'file' => 'cfp_payment_request_item.page.inc', 'template' => 'cfp_payment_request_item', ]; $theme['cfp_payment_request_item_content_add_list'] = [ 'render element' => 'content', 'variables' => ['content' => NULL], 'file' => 'cfp_payment_request_item.page.inc', ]; $theme['cfp_payment_request_checklist'] = [ 'render element' => 'elements', 'file' => 'cfp_payment_request_checklist.page.inc', ]; $theme['pr_invoice'] = [ 'render element' => 'elements', ]; return $theme; } /** * Prepares variables for invoice templates. * * Default template: pr-invoice.html.twig. * * @param array $variables * An associative array containing: * - elements: An associative array containing the invoice information and any * fields attached to the entity. * - attributes: HTML attributes for the containing element. */ function template_preprocess_pr_invoice(array &$variables) { foreach (Element::children($variables['elements']) as $key) { $variables['content'][$key] = $variables['elements'][$key]; } } /** * Implements hook_entity_bundle_field_info_alter(). */ function cfp_payment_request_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { if ($entity_type->id() === 'cfp_payment_request') { $pr_type = \Drupal::entityTypeManager()->getStorage('cfp_payment_request_type')->load($bundle); if ($pr_type) { if (isset($fields['items'])) { $settings = $fields['items']->getSettings(); $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_item_type') => $pr_type->get('payment_request_item_type')]; $fields['items']->setSettings($settings); } if (isset($fields['invoices'])) { $settings = $fields['invoices']->getSettings(); $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_invoice_type') => $pr_type->get('payment_request_invoice_type')]; $fields['invoices']->setSettings($settings); } } } } /** * Implements hook_theme_suggestions_HOOK(). */ function cfp_payment_request_theme_suggestions_cfp_payment_request(array $variables) { $entity = $variables['elements']['#cfp_payment_request']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); return build_template_suggestions($entity, $sanitized_view_mode); } /** * Implements hook_theme_suggestions_HOOK(). */ function cfp_payment_request_theme_suggestions_cfp_payment_request_item(array $variables) { $entity = $variables['elements']['#cfp_payment_request_item']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); return build_template_suggestions($entity, $sanitized_view_mode); } /** * Implements hook_theme_suggestions_HOOK(). */ function cfp_payment_request_theme_suggestions_cfp_payment_request_checklist(array $variables) { $entity = $variables['elements']['#cfp_payment_request_checklist']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); return build_template_suggestions($entity, $sanitized_view_mode); } /** * Implements hook_theme_suggestions_HOOK(). */ function cfp_payment_request_theme_suggestions_pr_invoice(array $variables) { $entity = $variables['elements']['#pr_invoice']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); return build_template_suggestions($entity, $sanitized_view_mode); } /** * Adds template suggestions. */ function build_template_suggestions($entity, $sanitized_view_mode) { $suggestions = []; $suggestions[] = $entity->getEntityTypeId() . '__' . $sanitized_view_mode; $suggestions[] = $entity->getEntityTypeId() . '__' . $entity->bundle(); $suggestions[] = $entity->getEntityTypeId() . '__' . $entity->bundle() . '__' . $sanitized_view_mode; $suggestions[] = $entity->getEntityTypeId() . '__' . $entity->id(); $suggestions[] = $entity->getEntityTypeId() . '__' . $entity->id() . '__' . $sanitized_view_mode; return $suggestions; } /** * Implements hook_file_download(). */ function cfp_payment_request_file_download($uri) { if (str_starts_with($uri, 'temporary://temporary_excel_exports/')) { return [ 'Content-disposition' => 'attachment; filename="' . basename($uri) . '"', ]; } } /** * Implements hook_add_more_entities_to_field_access_alter(). */ function cfp_payment_request_add_more_entities_to_field_access_alter(&$access, FieldItemListInterface $items, FieldDefinitionInterface $field_definition) { // @todo review this logic? $target_type = $field_definition->getSetting('target_type'); if ($target_type === 'cfp_payment_request') { // TODO: Delete comment. /** @var \Drupal\pos_entity_cfp\Entity\Cfp $parent_entity */ // $parent_entity = $items->getEntity(); // if ($parent_entity->getState()->getId() != 'project_implementation') { // return FALSE; // } // $current_user = \Drupal::currentUser(); // $access = $access ?: $current_user->id() == $parent_entity->getOwnerId(); // if ($access) { // /** @var \Drupal\pos_entity_cfp\Entity\CfpType $cfp_type */ // $cfp_type = CfpType::load($parent_entity->bundle()); // /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $payment_request_type */ // $payment_request_type = PaymentRequestType::load($cfp_type->getPaymentRequestBundle()); // if (!$payment_request_type) { // $access = FALSE; // return; // } // if ($current_user->hasPermission('administer payment request')) { // $entity_limit = $payment_request_type->get('entity_limit_for_admin'); // } else { // $entity_limit = $payment_request_type->get('entity_limit_for_applicant'); // } // if ($entity_limit !== -1 && $items->count() >= $entity_limit) { // $access = FALSE; // } // } } } /** * Implements hook_add_more_entity_alter(). */ function cfp_payment_request_add_more_entity_alter(FieldableEntityInterface $entity, FieldableEntityInterface $parent, FieldDefinitionInterface $field_definition) { if ($entity->getEntityTypeId() === 'cfp_payment_request') { // @todo Probably move this logic to presave. $entity->set('parent', $parent); $entity->setOwnerId($parent->getOwnerId()); } } /** * Implements hook_options_list_alter(). */ function cfp_payment_request_options_list_alter(array &$options, array $context) { if ($context['fieldDefinition']->getName() === 'pr_type' && $context['fieldDefinition']->getTargetEntityTypeId() === 'cfp_payment_request') { /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $pr_type */ $pr_type = $context['entity']->get('type')->entity; $allowed_options = $pr_type->get('allowed_pr_types') + ['_none' => '_none']; if (!empty($allowed_options)) { foreach ($options as $option_key => $option) { if (!in_array($option_key, $allowed_options)) { unset($options[$option_key]); } } } } } /** * Implements hook_preprocess_HOOK(). */ function cfp_payment_request_preprocess_field__entity_reference(&$variables) { if ($variables['field_name'] === 'payment_request' && $variables['entity_type'] === 'cfp') { foreach ($variables['items'] as $item) { $pr = $item['content']['#cfp_payment_request']; if ($pr->getState() === 'reopened') { $item['attributes']->setAttribute('style', 'border: 3px solid #ff0000'); } } } } /** * Implements hook_form_FORM_ID_alter(). */ function cfp_payment_request_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { if ($form['#id'] === 'views-exposed-form-payment-requests-page-1') { $workflow_manager = \Drupal::service('plugin.manager.workflow'); $workflow = $workflow_manager->createInstance('payment_request'); $states = $workflow->getStates(); $states = array_map(function ($state) { return $state->getLabel(); }, $states); $form['state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states, ]; } } /** * Implements hook_form_FORM_ID_alter(). */ function cfp_payment_request_form_cfp_payment_request_pr_2022_01_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { $form['cf_customs_documents']['#states'] = [ 'visible' => [ ':input[name="pr_type"]' => ['value' => 'closing'] ] ]; $form['cf_eur1_form']['#states'] = [ 'visible' => [ ':input[name="pr_type"]' => ['value' => 'closing'] ] ]; // @TODO: Ovo treba ispraviti. Ne verujem da ovo može tu da bude. // Payment request item conditional fields. $conditional_fields = [ 'cf_final_account', 'cf_confirm_final_payment', 'cf_purchase_contract', 'cf_protocol_record', 'cf_driving_license', 'cf_pictures', ]; foreach ($conditional_fields as $conditional_field) { if (isset($form[$conditional_field])) { $form[$conditional_field]['#states'] = [ 'visible' => [ ':input[name="pr_type"]' => ['value' => 'closing'] ] ]; } } }
<?php /** * Implements hook_entity_validation_ENTITY_TYPE_alter(). */ function cfp_payment_request_entity_validation_cfp_payment_request_alter($entity_typed_data, $validation_context) { $entity_typed_data->getDataDefinition()->addConstraint('GlobalPaymentRequestConstraint', []); if ($validation_context === 'cfp_payment_request.pr_2022_01') { $required_fields = [ 'cf_promissory_notes', 'cf_no_debts_confirmation', 'cf_technical_report_start', 'cf_technical_report_end', 'cf_project_description', 'items', ]; /** @var Drupal\Core\Entity\EntityInterface $entity */ $entity = $entity_typed_data->getEntity(); if ($entity->get('pr_type')->value === 'closing') { array_push($required_fields, 'cf_eur1_form', 'cf_customs_documents'); } /** @var \Drupal\Core\Field\FieldDefinition[] $field_definitions */ $field_definitions = $entity->getFieldDefinitions(); foreach ($required_fields as $required_field) { $field_definitions[$required_field]->setRequired(TRUE); } } } /** * Implements hook_entity_validation_ENTITY_TYPE_rollback_alter(). */ function cfp_payment_request_entity_validation_cfp_payment_request_item_rollback_alter($entity_typed_data, $validation_context, $rollback_info) { if ($validation_context === 'cfp_payment_request.pr_2022_01') { $required_fields = [ 'cost_item_name', 'cf_manufacturer', 'cf_distributor', 'cf_unique_item_id', 'cf_distributor_bank_account_num', 'cf_distributor_vat_number', 'item_quantity', ]; $decimal_fields = [ 'item_net_unit', 'item_unit_vat', 'item_pay_off', 'item_support', ]; /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestItem $entity */ $entity = $entity_typed_data->getEntity(); $payment_request = $entity->getParent(); if ($payment_request->get('pr_type')->value === 'closing') { array_push($required_fields, 'cf_final_account', 'cf_confirm_final_payment', 'cf_purchase_contract', 'cf_protocol_record', 'cf_driving_license', 'cf_pictures', ); } /** @var \Drupal\Core\Field\FieldDefinition[] $field_definitions */ $field_definitions = $entity->getFieldDefinitions(); foreach ($required_fields as $required_field) { $field_definitions[$required_field]->setRequired(TRUE); } foreach ($decimal_fields as $decimal_field) { if ($entity->get($decimal_field)->value === "0.00") { $entity->set($decimal_field, NULL); } $field_definitions[$decimal_field]->setRequired(TRUE); } } }
<?php namespace Drupal\cfp_payment_request\Entity; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityPublishedTrait; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\pos_core\PosFieldVariables; use Drupal\pos_entity_autocalculate\AutoCalculateFormula; use Drupal\pos_entity_autocalculate\Entity\AutocalculateEntityTrait; use Drupal\pos_entity_cost_item\AdditionalCostItem; use Drupal\pos_entity_cost_item\Entity\CostItemAcceptableInterface; use Drupal\pos_parent_entity\Entity\ChildEntityTrait; use Drupal\user\UserInterface; /** * Defines the Payment request item entity. * * @ingroup cfp_payment_request * * @ContentEntityType( * id = "cfp_payment_request_item", * label = @Translation("Payment request item"), * bundle_label = @Translation("Payment request item type"), * handlers = { * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", * "list_builder" = "Drupal\cfp_payment_request\PaymentRequestItemListBuilder", * "views_data" = "Drupal\cfp_payment_request\Entity\PaymentRequestItemViewsData", * * "form" = { * "default" = "Drupal\cfp_payment_request\Form\PaymentRequestItemForm", * "add" = "Drupal\cfp_payment_request\Form\PaymentRequestItemForm", * "edit" = "Drupal\cfp_payment_request\Form\PaymentRequestItemForm", * "delete" = "Drupal\cfp_payment_request\Form\PaymentRequestItemDeleteForm", * }, * "route_provider" = { * "html" = "Drupal\cfp_payment_request\PaymentRequestItemHtmlRouteProvider", * }, * "access" = "Drupal\cfp_payment_request\PaymentRequestItemAccessControlHandler", * "inline_form" = "\Drupal\cfp_payment_request\Form\PaymentRequestItemInlineForm", * }, * base_table = "cfp_payment_request_item", * translatable = FALSE, * admin_permission = "administer payment request item entities", * entity_keys = { * "id" = "id", * "bundle" = "type", * "uuid" = "uuid", * "uid" = "user_id", * "langcode" = "langcode", * "published" = "status", * }, * links = { * "canonical" = "/admin/structure/cfp_payment_request_item/{cfp_payment_request_item}", * "add-page" = "/admin/structure/cfp_payment_request_item/add", * "add-form" = "/admin/structure/cfp_payment_request_item/add/{cfp_payment_request_item_type}", * "edit-form" = "/admin/structure/cfp_payment_request_item/{cfp_payment_request_item}/edit", * "delete-form" = "/admin/structure/cfp_payment_request_item/{cfp_payment_request_item}/delete", * "collection" = "/admin/structure/cfp_payment_request_item", * }, * bundle_entity_type = "cfp_payment_request_item_type", * field_ui_base_route = "entity.cfp_payment_request_item_type.edit_form" * ) */ class PaymentRequestItem extends ContentEntityBase implements PaymentRequestItemInterface { use EntityChangedTrait; use EntityPublishedTrait; use ChildEntityTrait; use AutocalculateEntityTrait { preSave as autoCalculatePreSave; addFormulas as autoCalculateAddFormulas; } /** * {@inheritdoc} */ public static function preCreate(EntityStorageInterface $storage_controller, array &$values) { parent::preCreate($storage_controller, $values); $values += [ 'user_id' => \Drupal::currentUser()->id(), ]; } /** * {@inheritdoc} */ public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); if ($this->getPRIType()->arePricesInCurrencies()) { if (($currency = $this->getCurrency()) && ($currency_date = $this->getCurrencyDate())) { if ($exchange_rate = self::getExchangeRate($currency, $currency_date)) { $this->populateValuesWithExchange($exchange_rate); } } $this->autoCalculatePreSave($storage); } else { $this->autoCalculatePreSave($storage); } if ($this->get('accepted')->value !== 'accepted_with_new_value') { $this->set('new_item_pay_off', NULL) ->set('new_item_support', NULL); } } /** * {@inheritDoc} * Some computed field directly depend on another field, and we need to access * it right after. */ public function onChange($name) { parent::onChange($name); $field_influence_connection = [ 'accepted' => ['item_pay_off_computed', 'item_support_computed'], 'item_pay_off' => ['item_pay_off_computed'], 'new_item_pay_off' => ['item_pay_off_computed'], 'new_item_support' => ['item_support_computed'], 'item_support' => ['item_support_computed'], ]; foreach ($field_influence_connection[$name] ?? [] as $field_influence) { $this->get($field_influence)->forceRecomputeValue(); } } /** * @param $exchange_value */ public function populateValuesWithExchange($exchange_value) { $exchange_value = (float) $exchange_value; foreach ($this->getFieldDefinitions() as $field_definition) { if (strpos($field_definition->getName(), '_currency_value') !== FALSE) { $value = $this->get($field_definition->getName())->value; if ($value) { $forint_field_name = str_replace('_currency_value', '', $field_definition->getName()); $this->set($forint_field_name, bcmul($value, $exchange_value)); } elseif(is_numeric($value)) { $forint_field_name = str_replace('_currency_value', '', $field_definition->getName()); $this->set($forint_field_name, 0); } else { $this->set($forint_field_name, NULL); } } } } public static function getExchangeRate($currency, $currency_date) { if ($currency === 'HUF') { return 1; } $exchange_rate = str_replace(',', '.', _get_mnb_currency_value($currency, $currency_date)); return is_numeric($exchange_rate) ? $exchange_rate : NULL; } /** * {@inheritdoc} */ public function getName() { return $this->get('name')->value; } /** * {@inheritdoc} */ public function setName($name) { $this->set('name', $name); return $this; } /** * {@inheritdoc} */ public function getCreatedTime() { return $this->get('created')->value; } /** * {@inheritdoc} */ public function setCreatedTime($timestamp) { $this->set('created', $timestamp); return $this; } /** * {@inheritdoc} */ public function getOwner() { return $this->get('user_id')->entity; } /** * {@inheritdoc} */ public function getOwnerId() { return $this->get('user_id')->target_id; } /** * {@inheritdoc} */ public function setOwnerId($uid) { $this->set('user_id', $uid); return $this; } /** * {@inheritdoc} */ public function setOwner(UserInterface $account) { $this->set('user_id', $account->id()); return $this; } /** * {@inheritdoc} */ public function label() { return $this->getName(); } /** * Payment request item type. * * @return \Drupal\cfp_payment_request\Entity\PaymentRequestItemType */ public function getPRIType() { return PaymentRequestItemType::load($this->bundle()); } /** * @return mixed */ public function getCurrency() { $currency = $this->get('currency')->value; return $currency; } /** * */ public function getCurrencyDate() { if (!$this->get('currency_date')->isEmpty()) { return $this->get('currency_date')->date->format(CURRENCY_DATE_FORMAT); } } /** * Cost item identifier. * * @return string * Identifier of item. */ public function getCostItemIdentifier() { return $this->get('cost_item_name')->value; } /** * Returns accepted state. * * @return string * Accepted state. */ public function getAcceptedState() { return $this->get('accepted')->value; } /** * {@inheritdoc} */ public function addFormulas() { $this->autoCalculateAddFormulas(); if ($this->getPRIType()->arePricesInCurrencies()) { // Currency values. $this->addAutoCalculateFormula('item_net_amount_currency_value', AutoCalculateFormula::create() ->addFieldWithOperation('item_net_unit_currency_value') ->multiplyField('item_quantity')); $this->addAutoCalculateFormula('item_vat_currency_value', AutoCalculateFormula::create() ->addFieldWithOperation('item_unit_vat_currency_value') ->multiplyField('item_quantity') ); $this->addAutoCalculateFormula('item_bruto_currency_value', AutoCalculateFormula::create() ->addFieldWithOperation('item_net_amount_currency_value') ->addField('item_vat_currency_value') ); } // Forint values. $this->addAutoCalculateFormula('item_net_amount', AutoCalculateFormula::create() ->addFieldWithOperation('item_net_unit') ->multiplyField('item_quantity')); $this->addAutoCalculateFormula('item_vat', AutoCalculateFormula::create() ->addFieldWithOperation('item_unit_vat') ->multiplyField('item_quantity') ); $this->addAutoCalculateFormula('item_bruto', AutoCalculateFormula::create() ->addFieldWithOperation('item_net_amount') ->addField('item_vat') ); $this->addAutoCalculateFormula('item_support_percentage', AutoCalculateFormula::create() ->addField('item_support') ->divideField('item_pay_off') ->addNumberWithOperation(100, AutoCalculateFormula::MULTIPLY) ); $this->addAutoCalculateFormula('item_own_source', AutoCalculateFormula::create() ->addFieldWithOperation('item_pay_off') ->subtractField('item_support')); $this->addAutoCalculateFormula('item_bruto_unit', AutoCalculateFormula::create() ->addFieldWithOperation('item_bruto') ->divideField('item_quantity') ); } /** * {@inheritDoc} */ public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { $fields = []; if ($bundle) { /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestItemType $pri_type */ $pri_type = \Drupal::entityTypeManager() ->getStorage('cfp_payment_request_item_type') ->load($bundle); if ($pri_type) { $prices_in_currencies = $pri_type->arePricesInCurrencies(); foreach ($base_field_definitions as $field_name => $base_field_definition) { if (strpos($field_name, '_currency_value') !== FALSE) { if (!$prices_in_currencies) { $fields[$field_name] = clone $base_field_definition; $fields[$field_name]->setDisplayConfigurable('form', FALSE) ->setDisplayConfigurable('view', FALSE); } else { $basic_field_name = str_replace('_currency_value', '', $field_name); $fields[$basic_field_name] = clone $base_field_definitions[$basic_field_name]; $fields[$basic_field_name]->setDisplayConfigurable('form', FALSE); } } } } } return $fields; } /** * {@inheritdoc} */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); // Add the published field. $fields += static::publishedBaseFieldDefinitions($entity_type); $fields['user_id'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Authored by')) ->setDescription(t('The user ID of author of the Payment request item entity.')) ->setRevisionable(TRUE) ->setSetting('target_type', 'user') ->setSetting('handler', 'default') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['name'] = BaseFieldDefinition::create('string') ->setLabel(t('Tétel sorszáma')) ->setDescription(t('The name of the Payment request item entity.')) ->setSettings([ 'max_length' => 50, 'text_processing' => 0, ]) ->setDefaultValue('') ->setDisplayConfigurable('view', TRUE); $fields['cost_item_name'] = BaseFieldDefinition::create('list_string') ->setLabel('Stavka na koju se isplata odnosi') ->setSetting('allowed_values_function', '\Drupal\cfp_payment_request\Entity\PaymentRequestItem::itemNames') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); // NUMERIC FIELDS. $numeric_fields = [ 'item_net_unit' => 'Neto jedinična cijena', 'item_unit_vat' => 'PDV po neto jediničnoj cijeni', 'item_bruto_unit' => 'Jedinična bruto cijena', 'item_quantity' => 'Količina', 'item_pay_off' => 'Prihvatljivi trošak nabavke artikla', 'item_support' => 'Iznos bespovratnih sredstava koji tražite za artikal (EUR)', 'item_net_amount' => 'Neto ukupni trošak nabavke artikla (EUR)', 'item_vat' => 'Ukupan PDV', 'item_bruto' => 'Bruto ukupni trošak nabavke artikla (EUR)', 'item_own_source' => 'Iznos sopstvenog učešća (EUR)', ]; $exception_numeric_field_names = [ 'item_quantity', 'item_pay_off', 'item_support', 'item_own_source', ]; foreach ($numeric_fields as $numeric_field_machine_name => $numeric_field) { $fields[$numeric_field_machine_name] = BaseFieldDefinition::create($numeric_field_machine_name === 'item_quantity' ? 'integer' : 'decimal') ->setLabel($numeric_field) ->setSettings([ 'precision' => 12, 'scale' => 2, 'suffix' => '€', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); if (!in_array($numeric_field_machine_name, $exception_numeric_field_names)) { $fields[$numeric_field_machine_name .'_currency_value'] = BaseFieldDefinition::create('decimal') ->setLabel(str_replace(' (Ft)', '', $numeric_field)) ->setSettings([ 'precision' => 12, 'scale' => 2, ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); } } $fields['new_item_pay_off'] = BaseFieldDefinition::create('decimal') ->setLabel('New payoff') ->setSettings([ 'precision' => 12, 'scale' => 2, 'suffix' => '€', ]); $fields['new_item_support'] = BaseFieldDefinition::create('decimal') ->setLabel('New Support') ->setSettings([ 'precision' => 12, 'scale' => 2, 'suffix' => '€', ]); $fields['currency'] = BaseFieldDefinition::create('list_string') ->setLabel(t('Currency')) ->setSetting('allowed_values_function', '_get_mnb_currencies') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['currency_date'] = BaseFieldDefinition::create('datetime') ->setLabel(t('Currency date')) ->setSettings([ 'datetime_type' => 'date', ]) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['item_support_percentage'] = BaseFieldDefinition::create('decimal') ->setLabel('Postotak bespovratnih sredstava koji tražite (%)') ->setSettings([ 'prefix' => '', 'suffix' => '%', ]) ->setSettings(PosFieldVariables::PERCENTAGE_DEFAULT_FIELD_SETTINGS) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['item_pay_off_computed'] = BaseFieldDefinition::create('decimal') ->setLabel('Ügyintéző által jóváhagyott elszámolható költség') ->setComputed(TRUE) ->setClass('\Drupal\cfp_payment_request\Plugin\Field\ItemPayOffComputedFieldItemList') ->setDisplayConfigurable('view', TRUE); $fields['item_support_computed'] = BaseFieldDefinition::create('decimal') ->setLabel('Ügyintéző által jóváhagyott támogatási összeg') ->setComputed(TRUE) ->setClass('\Drupal\cfp_payment_request\Plugin\Field\ItemSupportComputedFieldItemList') ->setDisplayConfigurable('view', TRUE); $fields['supplier'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Supplier')) ->setSetting('target_type', 'supplier') ->setSetting('handler', 'default:supplier') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['accepted'] = BaseFieldDefinition::create('list_string') ->setLabel(t('Status')) ->setDefaultValue('accepted') ->setInitialValue('accepted') ->setSetting('allowed_values', PaymentRequestItem::getAllowedAcceptedValues()) ->setDisplayConfigurable('view', TRUE); $fields['status']->setDescription(t('A boolean indicating whether the Payment request item is published.')); $fields['created'] = BaseFieldDefinition::create('created') ->setLabel(t('Created')) ->setDescription(t('The time that the entity was created.')); $fields['changed'] = BaseFieldDefinition::create('changed') ->setLabel(t('Changed')) ->setDescription(t('The time that the entity was last edited.')); return $fields; } public static function getAllowedAcceptedValues() { return [ 'rejected' => t('Rejected'), 'accepted' => t('Accepted'), 'accepted_with_new_value' => t('Accepted with new value'), ]; } /** * Get item names. * * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition * Field definition. * @param \Drupal\Core\Entity\ContentEntityInterface|null $entity * Content entity. * * @return array * Item names. */ public static function itemNames(FieldStorageDefinitionInterface $definition = NULL, ContentEntityInterface $entity = NULL) { if ($parent = $entity->getParent()) { /** @var \Drupal\pos_payment_request\Entity\PaymentRequest $parent */ if ($parent_cfp = $parent->get('parent')->entity) { /** @var \Drupal\pos_entity_cost_item\Entity\CostItemsParentEntityInterface $parent_cfp */ $additional_options= array_filter(array_map(function (CostItemAcceptableInterface $cost_item) { if ($cost_item->isNewTotalSupportDefined() || $cost_item->isAccepted()) { return $cost_item->getName(); } }, $parent_cfp->getCostItemEntities())); foreach ($parent_cfp->getAdditionalCostItems() as $key => $cost_item) { $additional_options["additional_cost_item_$key"] = $cost_item['name']; } return $additional_options; } } return []; } /** * @return array */ public function getItemsCriteria() { if ($parent = $this->getParent()) { /** @var \Drupal\pos_payment_request\Entity\PaymentRequest $parent */ if ($parent_cfp = $parent->get('parent')->entity) { /** @var \Drupal\pos_entity_cost_item\Entity\CostItemsParentEntityInterface $parent_cfp */ $additional_options= array_filter(array_map(function (CostItemAcceptableInterface $cost_item) { if ($cost_item->isNewTotalSupportDefined() || $cost_item->isAccepted()) { return new AdditionalCostItem([ 'name' => $cost_item->getName(), 'value' => $cost_item->getAcceptedTotalSupport(), 'own_contribution_value' => $cost_item->getAcceptedOwnContribution(), ]); } }, $parent_cfp->getCostItemEntities())); foreach ($parent_cfp->getAdditionalCostItems() as $key => $cost_item) { $additional_options["additional_cost_item_$key"] = $cost_item; } return $additional_options; } } } }
{# /** * @file review.html.twig * Default theme implementation to present Review data. * * This template is used when viewing Review pages. * * * Available variables: * - content: A list of content items. Use 'content' to print all content, or * - attributes: HTML attributes for the container element. * * @see template_preprocess_review() * * @ingroup themeable */ #} <link rel="stylesheet" type="text/css" href="/themes/custom/pos/css/print.css"> <script type="text/javascript"> window.onload = () => {window.print();} </script> <div{{ attributes.addClass('review') }}> {% if content %} {{- content -}} {% endif %} </div> <div class="signatures"> <div class="signature-date"> <p>Mjesto i datum: ____________________________ 2022.</p> </div> <div class="signature"><p>____________________________________________________________</p> <p>Potpis</p> </div> </div>
{# /** * @file review.html.twig * Default theme implementation to present Review data. * * This template is used when viewing Review pages. * * * Available variables: * - content: A list of content items. Use 'content' to print all content, or * - attributes: HTML attributes for the container element. * * @see template_preprocess_review() * * @ingroup themeable */ #} <link rel="stylesheet" type="text/css" href="/themes/custom/pos/css/print.css"> <script type="text/javascript"> window.onload = () => {window.print();} </script> <div{{ attributes.addClass('review') }}> {% if content %} {{- content -}} {% endif %} </div> <div class="signatures"> <div class="signature-date"> <p>Mjesto i datum: ____________________________ 2022.</p> </div> <div class="signature"><p>____________________________________________________________</p> <p>Potpis</p> </div> </div>
<?php /** * @file * Contains pos_entity_review.module. */ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormState; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; use Drupal\pos_entity_cfp\Entity\Cfp; use Drupal\pos_entity_form_part\Form\EntityPartForm; use Drupal\pos_entity_review\Entity\ReviewType; use Drupal\pos_entity_review\Entity\ReviewTypeInterface; /** * Implements hook_help(). */ function pos_entity_review_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the pos_entity_review module. case 'help.page.pos_entity_review': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; $output .= '<p>' . t('Pos Review Base Entity Used by CFP in some states') . '</p>'; return $output; default: } } /** * Returns all execution as options. * * @return array * Array of all review types with labels. * * @throws \ReflectionException */ function _get_review_types_as_options() { $reflection_class = new ReflectionClass(ReviewTypeInterface::class); $states = []; foreach ($reflection_class->getConstants() as $constant_name => $constant) { if (strpos($constant_name, 'REVIEW_TYPE') !== FALSE) { $states[$constant] = ucfirst(strtolower(str_replace([ 'REVIEW_TYPE_', '_', ], [ '', ' ', ], $constant_name))); } } return $states; } /** * Implements hook_theme(). */ function pos_entity_review_theme() { $theme = []; $theme['review'] = [ 'render element' => 'elements', 'file' => 'review.page.inc', 'template' => 'review', ]; $theme['review_content_add_list'] = [ 'render element' => 'content', 'variables' => ['content' => NULL], 'file' => 'review.page.inc', ]; return $theme; } /** * Implements hook_theme_suggestions_HOOK(). */ function pos_entity_review_theme_suggestions_review(array $variables) { $suggestions = []; $entity = $variables['elements']['#review']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); $suggestions[] = 'review__' . $sanitized_view_mode; $suggestions[] = 'review__' . $entity->bundle(); $suggestions[] = 'review__' . $entity->bundle() . '__' . $sanitized_view_mode; $suggestions[] = 'review__' . $entity->id(); $suggestions[] = 'review__' . $entity->id() . '__' . $sanitized_view_mode; return $suggestions; } /** * Implements hook_entity_extra_field_info(). */ function pos_entity_review_entity_extra_field_info() { $extra = []; foreach (ReviewType::loadMultiple() as $review_type) { $extra['review'][$review_type->id()]['display']['view_link'] = [ 'label' => t('View link'), 'description' => 'Entity view link', 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['edit_link'] = [ 'label' => t('Edit link'), 'weight' => 0, 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['entity_label'] = [ 'label' => t('Entity label'), 'weight' => 0, 'visible' => FALSE, ]; if ($review_type->questionCanBeClarified()) { $extra['review'][$review_type->id()]['display']['clarify_question'] = [ 'label' => t('Clarify question button'), 'weight' => 0, 'visible' => FALSE, ]; } $extra['review'][$review_type->id()]['display']['correction_data'] = [ 'label' => t('Correction data(correction data for given)'), 'description' => t('If review is for correction state, corrections will be shown'), 'weight' => 0, 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['reviewer_additional_files'] = [ 'label' => t('Shows file upload for additional files'), 'description' => t('Reviewer need to attach document during work in some cases'), 'weight' => 0, 'visible' => FALSE, ]; } return $extra; } /** * Implements hook_ENTITY_TYPE_view(). */ function pos_entity_review_review_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { /** @var \Drupal\pos_entity_review\Entity\Review $entity */ if ($display->getComponent('view_link') && $entity->access('view') && !$entity->access('update')) { $view_link = $entity->toUrl(); $build['view_link'] = [ '#type' => 'link', '#title' => t('View'), '#url' => $view_link, '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('edit_link') && $entity->access('update')) { $edit_link = $entity->toUrl('edit-form'); $edit_link->setRouteParameter('destination', Url::fromRoute('<current>')->toString()); $build['edit_link'] = [ '#type' => 'link', '#title' => t('Edit'), '#url' => $edit_link, '#attributes' => [ 'class' => ['button', 'button--primary'], ], ]; } if ($display->getComponent('entity_label')) { $build['entity_label'] = [ '#type' => 'markup', '#markup' => '<h3>' . $entity->label() . '</h3>', ]; } if ($display->getComponent('clarify_question') && $entity->access('update')) { $build['clarify_question'] = [ '#title' => t('Clarify question'), '#type' => 'link', '#url' => $entity->toUrl('question-form')->setRouteParameter('destination', Url::fromRoute('<current>')->toString()), '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('correction_data')) { /** @var \Drupal\pos_entity_cfp\Entity\Cfp $cfp */ $cfp = $entity->getCfpEntity(); if ($cfp && $state_for_review = $entity->get('state_for_review')->value) { $correction_plugin = $cfp->getStateCorrectionPlugin($state_for_review); if ($correction_plugin) { $build['correction_data']['#type'] = 'container'; $build['correction_data']['questions'] = $correction_plugin->getCorrectionQuestionElement(); $build['correction_data']['answers'] = $correction_plugin->getCorrectionAnswersElement(); } } } if ($display->getComponent('reviewer_additional_files')) { if ((\Drupal::currentUser()->id() == $entity->getAssigneeId()) || (in_array('administrator', \Drupal::currentUser()->getRoles()))) { $field = 'reviewer_files'; /** @var \Drupal\pos_entity_form_part\Form\EntityPartForm $form_part */ $form_part = \Drupal::classResolver() ->getInstanceFromDefinition(EntityPartForm::class); $form_state = new FormState(); $form_part->setFields([$field]); $form_part->setEntity($entity); $form_part->setRedirectionRoute('<current>'); $form_part->setCurrentTabRedirect(TRUE); $form = \Drupal::formBuilder()->buildForm($form_part, $form_state); $form['reviewer_files']['widget']['#disable_dragging'] = TRUE; $build['reviewer_additional_files'] = $form; } } } /** * Implements hook_cron(). */ function pos_entity_review_cron() { $query = \Drupal::database()->query('SELECT id FROM `review` WHERE cfp NOT IN (SELECT id FROM cfp)'); $review_storage = \Drupal::entityTypeManager()->getStorage('review'); while ($row = $query->fetch()) { $review = $review_storage->load($row->id); if ($review) { $review->delete(); } } } /** * Implements hook_views_data_alter(). */ function pos_entity_review_views_data_alter(array &$data) { $data['review']['review_project_implementation_filter'] = [ 'title' => t('Járás" - Okres - Project Implementation Place (Filter)'), 'filter' => [ 'title' => t('Járás - Okres - Project Implementation Place (Filter)'), 'field' => 'cfp', 'id' => 'pos_review_address_filter', ], ]; } /** * Implements hook_review_passed_alter(). */ function pos_entity_review_review_passed_alter(&$passed, $entity) { /** @var \Drupal\pos_entity_review\Entity\ReviewType $review_type */ $review_type = ReviewType::load($entity->bundle()); if (($key_field = $review_type->getKeyField()) && !empty($accept_values = $review_type->getAcceptValues())) { if (in_array($entity->get($key_field)->value, $accept_values)) { if (pos_printer_is_printable_entity($entity->getEntityType(), $entity->bundle())) { if ($entity->isPrintConfirmed()) { $passed = TRUE; } } else { $passed = TRUE; } } } } /** * Implements hook_review_rejected_alter(). */ function pos_entity_review_review_rejected_alter(&$rejected, $entity) { /** @var \Drupal\pos_entity_review\Entity\ReviewType $review_type */ $review_type = ReviewType::load($entity->bundle()); if (($key_field = $review_type->getKeyField()) && !empty($reject_values = $review_type->getRejectValues())) { if (in_array($entity->get($key_field)->value, $reject_values)) { if (pos_printer_is_printable_entity($entity->getEntityType(), $entity->bundle())) { if ($entity->isPrintConfirmed()) { $rejected = TRUE; } } else { $rejected = TRUE; } } } } /** * Implements hook_entity_bundle_field_info_alter(). */ function pos_entity_review_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { if ($entity_type->id() === 'review' && !empty($bundle)) { $review_type = ReviewType::load($bundle); if ($key_field = $review_type->getKeyField()) { if (isset($fields[$key_field])) { $fields[$key_field]->addConstraint('reviewKeyFieldCondition'); } } } if ($entity_type->id() === 'review' && $bundle === 'acceptance_2022_01') { if ($fields['cf_comment']) { $fields['cf_comment']->setRequired(TRUE); $fields['cf_comment']->addPropertyConstraints('value', ['NamedLength' => ['min' => 20, 'max' => 500]]); } } } /** * Implements hook_mail(). */ function pos_entity_review_mail($key, &$message, $params) { switch ($key) { case 'reviewer_clarify_question': $message['headers']['From'] = $params['from']; $message['headers']['Sender'] = $params['from']; $message['subject'] = $params['subject']; $message['body'][] = $params['message']; $message['headers']['Content-Type'] = 'text/html'; break; } }
{# /** * @file review.html.twig * Default theme implementation to present Review data. * * This template is used when viewing Review pages. * * * Available variables: * - content: A list of content items. Use 'content' to print all content, or * - attributes: HTML attributes for the container element. * * @see template_preprocess_review() * * @ingroup themeable */ #} <link rel="stylesheet" type="text/css" href="/themes/custom/pos/css/print.css"> <script type="text/javascript"> window.onload = () => {window.print();} </script> <div{{ attributes.addClass('review') }}> {% if content %} {{- content -}} {% endif %} </div> <div class="signatures"> <div class="signature-date"> <p>Mjesto i datum: ____________________________ 2022.</p> </div> <div class="signature"><p>____________________________________________________________</p> <p>Potpis</p> </div> </div>
<?php /** * @file * Contains pos_entity_review.module. */ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormState; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; use Drupal\pos_entity_cfp\Entity\Cfp; use Drupal\pos_entity_form_part\Form\EntityPartForm; use Drupal\pos_entity_review\Entity\ReviewType; use Drupal\pos_entity_review\Entity\ReviewTypeInterface; /** * Implements hook_help(). */ function pos_entity_review_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the pos_entity_review module. case 'help.page.pos_entity_review': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; $output .= '<p>' . t('Pos Review Base Entity Used by CFP in some states') . '</p>'; return $output; default: } } /** * Returns all execution as options. * * @return array * Array of all review types with labels. * * @throws \ReflectionException */ function _get_review_types_as_options() { $reflection_class = new ReflectionClass(ReviewTypeInterface::class); $states = []; foreach ($reflection_class->getConstants() as $constant_name => $constant) { if (strpos($constant_name, 'REVIEW_TYPE') !== FALSE) { $states[$constant] = ucfirst(strtolower(str_replace([ 'REVIEW_TYPE_', '_', ], [ '', ' ', ], $constant_name))); } } return $states; } /** * Implements hook_theme(). */ function pos_entity_review_theme() { $theme = []; $theme['review'] = [ 'render element' => 'elements', 'file' => 'review.page.inc', 'template' => 'review', ]; $theme['review_content_add_list'] = [ 'render element' => 'content', 'variables' => ['content' => NULL], 'file' => 'review.page.inc', ]; return $theme; } /** * Implements hook_theme_suggestions_HOOK(). */ function pos_entity_review_theme_suggestions_review(array $variables) { $suggestions = []; $entity = $variables['elements']['#review']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); $suggestions[] = 'review__' . $sanitized_view_mode; $suggestions[] = 'review__' . $entity->bundle(); $suggestions[] = 'review__' . $entity->bundle() . '__' . $sanitized_view_mode; $suggestions[] = 'review__' . $entity->id(); $suggestions[] = 'review__' . $entity->id() . '__' . $sanitized_view_mode; return $suggestions; } /** * Implements hook_entity_extra_field_info(). */ function pos_entity_review_entity_extra_field_info() { $extra = []; foreach (ReviewType::loadMultiple() as $review_type) { $extra['review'][$review_type->id()]['display']['view_link'] = [ 'label' => t('View link'), 'description' => 'Entity view link', 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['edit_link'] = [ 'label' => t('Edit link'), 'weight' => 0, 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['entity_label'] = [ 'label' => t('Entity label'), 'weight' => 0, 'visible' => FALSE, ]; if ($review_type->questionCanBeClarified()) { $extra['review'][$review_type->id()]['display']['clarify_question'] = [ 'label' => t('Clarify question button'), 'weight' => 0, 'visible' => FALSE, ]; } $extra['review'][$review_type->id()]['display']['correction_data'] = [ 'label' => t('Correction data(correction data for given)'), 'description' => t('If review is for correction state, corrections will be shown'), 'weight' => 0, 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['reviewer_additional_files'] = [ 'label' => t('Shows file upload for additional files'), 'description' => t('Reviewer need to attach document during work in some cases'), 'weight' => 0, 'visible' => FALSE, ]; $extra['review'][$review_type->id()]['display']['raw_signature'] = [ 'label' => t('Signature'), 'visible' => FALSE, ]; } return $extra; } /** * Implements hook_ENTITY_TYPE_view(). */ function pos_entity_review_review_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { /** @var \Drupal\pos_entity_review\Entity\Review $entity */ if ($display->getComponent('view_link') && $entity->access('view') && !$entity->access('update')) { $view_link = $entity->toUrl(); $build['view_link'] = [ '#type' => 'link', '#title' => t('View'), '#url' => $view_link, '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('edit_link') && $entity->access('update')) { $edit_link = $entity->toUrl('edit-form'); $edit_link->setRouteParameter('destination', Url::fromRoute('<current>')->toString()); $build['edit_link'] = [ '#type' => 'link', '#title' => t('Edit'), '#url' => $edit_link, '#attributes' => [ 'class' => ['button', 'button--primary'], ], ]; } if ($display->getComponent('entity_label')) { $build['entity_label'] = [ '#type' => 'markup', '#markup' => '<h3>' . $entity->label() . '</h3>', ]; } if ($display->getComponent('clarify_question') && $entity->access('update')) { $build['clarify_question'] = [ '#title' => t('Clarify question'), '#type' => 'link', '#url' => $entity->toUrl('question-form')->setRouteParameter('destination', Url::fromRoute('<current>')->toString()), '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('correction_data')) { /** @var \Drupal\pos_entity_cfp\Entity\Cfp $cfp */ $cfp = $entity->getCfpEntity(); if ($cfp && $state_for_review = $entity->get('state_for_review')->value) { $correction_plugin = $cfp->getStateCorrectionPlugin($state_for_review); if ($correction_plugin) { $build['correction_data']['#type'] = 'container'; $build['correction_data']['questions'] = $correction_plugin->getCorrectionQuestionElement(); $build['correction_data']['answers'] = $correction_plugin->getCorrectionAnswersElement(); } } } if ($display->getComponent('reviewer_additional_files')) { if ((\Drupal::currentUser()->id() == $entity->getAssigneeId()) || (in_array('administrator', \Drupal::currentUser()->getRoles()))) { $field = 'reviewer_files'; /** @var \Drupal\pos_entity_form_part\Form\EntityPartForm $form_part */ $form_part = \Drupal::classResolver() ->getInstanceFromDefinition(EntityPartForm::class); $form_state = new FormState(); $form_part->setFields([$field]); $form_part->setEntity($entity); $form_part->setRedirectionRoute('<current>'); $form_part->setCurrentTabRedirect(TRUE); $form = \Drupal::formBuilder()->buildForm($form_part, $form_state); $form['reviewer_files']['widget']['#disable_dragging'] = TRUE; $build['reviewer_additional_files'] = $form; } } if ($display->getComponent('raw_signature')) { /** @var \Drupal\pos_entity_cfp\Entity\Cfp $cfp */ $cfp = $entity->getCfpEntity(); $build['raw_signature'] = [ '#type' => 'inline_template', '#template' => pos_entity_review_get_signature_part($cfp), ]; } } /** * Get signature part. */ function pos_entity_review_get_signature_part(Cfp $cfp) { $representative = $cfp->getApplicantEntity()->getCompanyRepresentative(); return '<div class="signatures"> <div class="signature-date"><p>Mjesto i datum: ____________________________ 2022.</p></div> <div class="signature"> <p>____________________________</p> <p>' . $cfp->getApplicantEntity()->get('applicant_name')->value . '</p> <p>' . $representative?->label() .'</p> </div>'; } /** * Implements hook_cron(). */ function pos_entity_review_cron() { $query = \Drupal::database()->query('SELECT id FROM `review` WHERE cfp NOT IN (SELECT id FROM cfp)'); $review_storage = \Drupal::entityTypeManager()->getStorage('review'); while ($row = $query->fetch()) { $review = $review_storage->load($row->id); if ($review) { $review->delete(); } } } /** * Implements hook_views_data_alter(). */ function pos_entity_review_views_data_alter(array &$data) { $data['review']['review_project_implementation_filter'] = [ 'title' => t('Járás" - Okres - Project Implementation Place (Filter)'), 'filter' => [ 'title' => t('Járás - Okres - Project Implementation Place (Filter)'), 'field' => 'cfp', 'id' => 'pos_review_address_filter', ], ]; } /** * Implements hook_review_passed_alter(). */ function pos_entity_review_review_passed_alter(&$passed, $entity) { /** @var \Drupal\pos_entity_review\Entity\ReviewType $review_type */ $review_type = ReviewType::load($entity->bundle()); if (($key_field = $review_type->getKeyField()) && !empty($accept_values = $review_type->getAcceptValues())) { if (in_array($entity->get($key_field)->value, $accept_values)) { if (pos_printer_is_printable_entity($entity->getEntityType(), $entity->bundle())) { if ($entity->isPrintConfirmed()) { $passed = TRUE; } } else { $passed = TRUE; } } } } /** * Implements hook_review_rejected_alter(). */ function pos_entity_review_review_rejected_alter(&$rejected, $entity) { /** @var \Drupal\pos_entity_review\Entity\ReviewType $review_type */ $review_type = ReviewType::load($entity->bundle()); if (($key_field = $review_type->getKeyField()) && !empty($reject_values = $review_type->getRejectValues())) { if (in_array($entity->get($key_field)->value, $reject_values)) { if (pos_printer_is_printable_entity($entity->getEntityType(), $entity->bundle())) { if ($entity->isPrintConfirmed()) { $rejected = TRUE; } } else { $rejected = TRUE; } } } } /** * Implements hook_entity_bundle_field_info_alter(). */ function pos_entity_review_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { if ($entity_type->id() === 'review' && !empty($bundle)) { $review_type = ReviewType::load($bundle); if ($key_field = $review_type->getKeyField()) { if (isset($fields[$key_field])) { $fields[$key_field]->addConstraint('reviewKeyFieldCondition'); } } } if ($entity_type->id() === 'review' && $bundle === 'acceptance_2022_01') { if ($fields['cf_comment']) { $fields['cf_comment']->setRequired(TRUE); $fields['cf_comment']->addPropertyConstraints('value', ['NamedLength' => ['min' => 20, 'max' => 500]]); } } } /** * Implements hook_mail(). */ function pos_entity_review_mail($key, &$message, $params) { switch ($key) { case 'reviewer_clarify_question': $message['headers']['From'] = $params['from']; $message['headers']['Sender'] = $params['from']; $message['subject'] = $params['subject']; $message['body'][] = $params['message']; $message['headers']['Content-Type'] = 'text/html'; break; } }
<?php namespace Drupal\pos_entity_review\Form; use Drupal\Component\Datetime\TimeInterface; use Drupal\Core\Entity\ContentEntityForm; use Drupal\Core\Entity\Display\EntityFormDisplayInterface; use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Mail\MailManagerInterface; use Drupal\pos_entity_cfp\Entity\CfpType; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class ReviewQuestionClaficationForm * * @package Drupal\pos_entity_review\Form */ class ReviewQuestionClarificationForm extends ContentEntityForm { /** * Mail Manager. * * @var \Drupal\Core\Mail\MailManagerInterface */ protected $mailManager; /** * Constructs a new ReviewQuestionClarificationForm. * * @param EntityRepositoryInterface $entity_repository * @param EntityTypeBundleInfoInterface $entity_type_bundle_info * @param TimeInterface $time * @param MailManagerInterface $mailManager */ public function __construct(EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time, MailManagerInterface $mailManager) { parent::__construct($entity_repository, $entity_type_bundle_info, $time); $this->mailManager = $mailManager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { // Instantiates this form class. return new static( $container->get('entity.repository'), $container->get('entity_type.bundle.info'), $container->get('datetime.time'), $container->get('plugin.manager.mail'), ); } /** * {@inheritDoc} */ public function getFormDisplay(FormStateInterface $form_state) { $entity_form_display = EntityFormDisplay::create([ 'targetEntityType' => 'review', 'third_party_settings' => [], 'bundle' => $this->entity->bundle(), 'content' => [ 'question' => [ 'type' => 'string_textarea', 'region' => 'content', 'weight' => 0, 'settings' => [ 'rows' => 10, 'placeholder' => '', ], 'third_party_settings' => [], ] ], ]); return $entity_form_display; } /** * {@inheritDoc} */ public function setFormDisplay(EntityFormDisplayInterface $form_display, FormStateInterface $form_state) { return parent::setFormDisplay($this->getFormDisplay($form_state), $form_state); } /** * {@inheritDoc} */ protected function actions(array $form, FormStateInterface $form_state) { $actions = parent::actions($form, $form_state); unset($actions['delete']); return $actions; } /** * Route title callback. * * @return \Drupal\Core\StringTranslation\TranslatableMarkup */ public function titleCallback() { return $this->t('Clarify question'); } /** * {@inheritDoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); /** @var \Drupal\pos_entity_review\Entity\Review $review */ $review = $this->entity; $cfp = $review->getCfpEntity(); $cfp_type = CfpType::load($cfp->bundle()); $reviewer = $review->getAssignee(); // If admin is the one who is sending the mail, then it needs to be sent to reviewers email address. if ($this->currentUser()->hasPermission('admin view all call for proposal entities')) { $to = $reviewer->getEmail(); $from = $cfp_type->get('mail_sender')->value ?? 'noreply@forsrpska.org'; } else { $to = $cfp_type->get('notification_email')->value ?? 'info@forsrpska.org'; $from = $reviewer->getEmail(); } $this->mailManager->mail( 'pos_entity_review', 'reviewer_clarify_question', $to, \Drupal::languageManager()->getCurrentLanguage()->getId(), [ 'from' => $from, 'subject' => t('Clarify question'), 'message' => reset($form_state->getValue('question'))['value'], ], NULL, TRUE ); } }
<?php namespace Drupal\cfp_payment_request\Entity; use Drupal\cfp_payment_request\Event\PRTransitionEvent; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityPublishedTrait; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface; use Drupal\halo_closable_entity\Entity\ClosableEntityTrait; use Drupal\halo_entity_cfp\Entity\Cfp; use Drupal\halo_entity_validator\Entity\HaloEntityValidationTrait; use Drupal\halo_parent_entity\Entity\ChildEntityTrait; use Drupal\halo_printer\Entity\HaloPrintableEntityTrait; use Drupal\halo_printer\Entity\PrintTokenEntityInterface; use Drupal\halo_transition_history_field\Plugin\Field\TransitionDateSearchItemList; use Drupal\user\UserInterface; use Drupal\halo_entity_cfp\Entity\CfpPaymentInterface; /** * Defines the Payment request entity. * * @ingroup cfp_payment_request * * @ContentEntityType( * id = "cfp_payment_request", * label = @Translation("Payment request"), * bundle_label = @Translation("Payment request type"), * handlers = { * "view_builder" = "Drupal\cfp_payment_request\PaymentRequestEntityViewBuilder", * "list_builder" = "Drupal\cfp_payment_request\PaymentRequestListBuilder", * "views_data" = "Drupal\cfp_payment_request\Entity\PaymentRequestViewsData", * * "form" = { * "default" = "Drupal\cfp_payment_request\Form\PaymentRequestForm", * "add" = "Drupal\cfp_payment_request\Form\PaymentRequestForm", * "edit" = "Drupal\cfp_payment_request\Form\PaymentRequestForm", * "delete" = "Drupal\cfp_payment_request\Form\PaymentRequestDeleteForm", * "suspended_documents" = "\Drupal\cfp_payment_request\Form\PaymentRequestSuspendedDocumentsForm", * }, * "route_provider" = { * "html" = "Drupal\cfp_payment_request\PaymentRequestHtmlRouteProvider", * }, * "access" = "Drupal\cfp_payment_request\PaymentRequestAccessControlHandler", * }, * base_table = "cfp_payment_request", * translatable = FALSE, * admin_permission = "administer payment request entities", * entity_keys = { * "id" = "id", * "bundle" = "type", * "label" = "name", * "uuid" = "uuid", * "uid" = "user_id", * "langcode" = "langcode", * "published" = "status", * }, * links = { * "canonical" = "/admin/structure/cfp_payment_request/{cfp_payment_request}", * "add-page" = "/admin/structure/cfp_payment_request/add", * "add-form" = "/admin/structure/cfp_payment_request/add/{cfp_payment_request_type}", * "edit-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/edit", * "current-correction-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/correction", * "correction-submit-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/correction_submit", * "delete-form" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/delete", * "collection" = "/admin/structure/cfp_payment_request", * "admin-view" = "/admin/structure/cfp_payment_request/{cfp_payment_request}/admin_view", * "suspended-documents" = "/cfp_payment_request/{cfp_payment_request}/suspended_documents", * "suspended-documents-submit" = "/cfp_payment_request/{cfp_payment_request}/suspended_documents_submit" * }, * bundle_entity_type = "cfp_payment_request_type", * field_ui_base_route = "entity.cfp_payment_request_type.edit_form" * ) */ class PaymentRequest extends ContentEntityBase implements PaymentRequestInterface, CfpPaymentInterface, PrintTokenEntityInterface { use EntityChangedTrait; use EntityPublishedTrait; use HaloEntityValidationTrait; use ClosableEntityTrait; use HaloPrintableEntityTrait; use ChildEntityTrait; const ADD_UP_FIELDS = [ 'item_pay_off', 'item_support', 'item_pay_off_computed', 'item_support_computed', 'item_net_amount', 'item_vat', 'item_bruto', 'item_own_source', ]; /** * {@inheritdoc} */ public static function preCreate(EntityStorageInterface $storage_controller, array &$values) { parent::preCreate($storage_controller, $values); $values += [ 'user_id' => \Drupal::currentUser()->id(), ]; } /** * {@inheritdoc} */ public function getName() { return $this->get('label')->value; } /** * {@inheritdoc} * @todo Refactor this in more functions. */ public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $payment_request_type */ $payment_request_type = $this->get('type')->entity; $clear_reopen_instructions = FALSE; if (!$this->isNew()) { // On opening payment request. if ($this->getState() === 'open_state' && $this->getState() !== $this->original->getState()) { $this->set('validation_passed', FALSE); $this->set('closed', FALSE); $this->set('print', NULL); $this->set('print_confirmed', FALSE); } // On reopening payment request. if ($this->getState() === 'reopened' && $this->getState() !== $this->original->getState()) { /** @var \Drupal\file\Entity\File $old_print_file */ $old_print_file = $this->get('print')->entity; if ($old_print_file) { $this->get('old_prints')->appendItem([ 'target_id' => $old_print_file->id(), 'description' => DrupalDateTime::createFromTimestamp($old_print_file->getCreatedTime())->format('Y.m.d.') . ' - print', ]); } $reopen_instructions = $this->get('reopen_instructions')->value ?? '-'; $this->get('previous_reopen_instructions')->appendItem(['value' => $reopen_instructions]); $clear_reopen_instructions = TRUE; $this->invalidate()->open()->clearPrintFile()->unconfirmPrint(); } if ($this->isPrintConfirmed() === TRUE && $this->original->isPrintConfirmed() === FALSE) { $this->appendChecklist($this->getState() === 'reopened'); $this->setState('sent'); if ($this->get('first_submission_date')->isEmpty()) { $this->set('first_submission_date', \Drupal::time()->getCurrentTime()); } } if (!$this->original->isClosed() && $this->isClosed()) { $datetime = new DrupalDateTime(); $datetime->setTimezone(new \DateTimeZone('UTC')); $this->set('closed_date', $datetime->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT)); } if ($this->getState() === 'correction_submitted' && $this->original->getState() === 'correction' ) { $current_correction = (int) $this->get('current_correction')->value; $this->appendChecklist(TRUE); $this->set('current_correction', ($current_correction + 1)); } if ($this->getState() === 'deadline_expired' && $this->original->getState() === 'reopened') { // This function needs to accept one more optional argument (after_deadline). $this->appendChecklist(FALSE, TRUE); } if (($this->getState() === 'approved' || $this->getState() === 'accepted_with_reduction') && $this->stateHasChangedFromOriginal()) { $this->set('date_of_completion', \Drupal::time()->getCurrentTime()); } // Flag that cfp has closing payment request. if ($this->stateHasChangedFromOriginal() && $this->hasField('pr_type') && $this->get('pr_type')->value === 'closing') { if (in_array($this->getState(), Cfp::getPaidStates())) { if ($this->hasParent() && !$this->getParent()->isFlagged('has_closing_payment_request')) { $this->getParent()->flag('has_closing_payment_request')->save(); } } if (in_array($this->getState(), Cfp::getCompletionStates())) { if ($this->hasParent() && !$this->getParent()->isFlagged('has_approved_closing_pr')) { $this->getParent()->flag('has_approved_closing_pr')->save(); } } } if ($this->getState() !== $this->original->getState()) { $event = new PRTransitionEvent( $this, $this->original->getState(), $this->getState() ); \Drupal::service('event_dispatcher')->dispatch(PRTransitionEvent::TRANSITION_EVENT, $event); $this->appendTransition($this->getState()); $this->set('correction_deadline', NULL); } if ($this->stateHasChangedFromOriginal() && in_array($this->getState(), Cfp::getCompletionInvalidationStates())) { $this->setAmountDedicatedToAp(NULL); $this->set('date_of_completion', NULL); } } if ($this->get('label')->isEmpty() && $this->hasParent()) { $parent = $this->getParent(); $order = $parent->get('payment_request')->count() + 1; $this->set('label', $parent->label() . '/' . $payment_request_type->get('order_prefix') . $order); } if ($this->hasParent()) { $this->setOwnerId($this->getParent()->getOwnerId()); } if ($clear_reopen_instructions) { $this->set('reopen_instructions', NULL); } $items = $this->getItems(TRUE); $this->calculateTotals($items); $this->constructItemLabels($items); $this->setInvoiceOrdering(); } /** * Calculates totals. */ public function calculateTotals($items = NULL) { if (!isset($items)) { $items = $this->getItems(TRUE); } foreach (self::ADD_UP_FIELDS as $add_up_field) { $total = 0; foreach ($items as $item) { $total += $item->get($add_up_field)->value ?? 0; } $this->set("{$add_up_field}_total", $total); } if (($this->getState() === 'approved' || $this->getState() === 'accepted_with_reduction') && isset($this->original) && $this->original->getState() !== $this->getState()) { /** @var \Drupal\halo_entity_cfp\Entity\Cfp $cfp */ $cfp = $this->getParent(); $not_covered_ap = $cfp->getNotCoveredApAmount(); if ($not_covered_ap > $this->getTotalSupport()) { $this->setAmountDedicatedToAp($this->getTotalSupport()); } else { $this->setAmountDedicatedToAp($not_covered_ap); } } } /** * Has state changed since original. * * @return bool * Has state changed. */ protected function stateHasChangedFromOriginal() { if (!isset($this->original)) { return FALSE; } return $this->original->getState() !== $this->getState(); } /** * Constructs labels based on order from parent payment request(this entity). * * @param \Drupal\cfp_payment_request\Entity\PaymentRequestItem[] $items * Payment request items. */ public function constructItemLabels($items) { foreach ($items as $delta => $item) { $label = $this->label() . '-' . str_pad(($delta + 1), 3, '0', STR_PAD_LEFT); if ($item->getName() != $label) { $item->setName($label); $item->save(); } } } public function setInvoiceOrdering() { foreach ($this->getInvoices() as $order => $invoice) { if (((int) ($order + 1)) !== ((int) $invoice->get('invoice_order')->value)) { $invoice->set('invoice_order', $order + 1); $invoice->save(); } } } /** * {@inheritdoc} */ public function setName($name) { $this->set('label', $name); return $this; } /** * {@inheritdoc} */ public function getCreatedTime() { return $this->get('created')->value; } /** * {@inheritdoc} */ public function setCreatedTime($timestamp) { $this->set('created', $timestamp); return $this; } /** * {@inheritdoc} */ public function getOwner() { return $this->get('user_id')->entity; } /** * {@inheritdoc} */ public function getOwnerId() { return $this->get('user_id')->target_id; } /** * {@inheritdoc} */ public function setOwnerId($uid) { $this->set('user_id', $uid); return $this; } /** * {@inheritdoc} */ public function setOwner(UserInterface $account) { $this->set('user_id', $account->id()); return $this; } /** * Item type for this payment request. * * @return string * Item type for this payment request. */ public function getPaymentRequestItemType() { return \Drupal::entityTypeManager() ->getStorage('cfp_payment_request_type') ->load($this->bundle()) ->get('payment_request_item_type'); } /** * @return \Drupal\cfp_payment_request\Entity\PaymentRequestItem[] */ public function getItems($with_invoice = FALSE) { $items = []; foreach ($this->get('items') as $field_item) { if ($item = $field_item->entity) { $items[] = $item; } } if ($with_invoice) { foreach ($this->getInvoices() as $invoice) { foreach ($invoice->getItems() as $item) { $items[] = $item; } } } return $items; } /** * @return \Drupal\cfp_payment_request\Entity\PrInvoice[] */ public function getInvoices() { $invoices = []; foreach ($this->get('invoices') as $field_item) { if ($invoice = $field_item->entity) { $invoices[] = $invoice; } } return $invoices; } /** * Returns active state. * * @return string * Active state. */ public function getState() { return $this->get('state')->value ?: 'open_state'; } /** * Returns active state. * * @return string * Active state. */ public function getStateId(): string { return $this->getState(); } /** * {@inheritDoc} */ public function getCompletionTimestamp(): int|string|null { return $this->get('date_of_completion')->value; } /** * Payment request state. * * @param string $state * Payment request state. * * @return static * Returns */ public function setState($state) { $this->set('state', $state); return $this; } /** * Returns user friendly state value. * * @return string * User friendly value. */ public function getStateLabel() { return $this->get('state')->first()->getLabel(); } /** * {@inheritdoc} */ public function inheritsParentAccess() { return FALSE; } /** * {@inheritdoc} */ public function label() { return $this->get('label')->value; } /** * Is item approvement closed. * * @return bool * */ public function isItemApprovementClosed() { return (bool) $this->get('items_approvement_closed')->value; } /** * {@inheritDoc} */ public function appendChecklist($during_correction = FALSE, $after_deadline = FALSE) { /** @var \Drupal\cfp_payment_request\Entity\PaymentRequestType $payment_request_type */ $payment_request_type = $this->get('type')->entity; if (!$during_correction) { if ($after_deadline) { $payment_request_checklist = $this->generateDuplicateChecklist($during_correction, $after_deadline); } else { $payment_request_checklist = \Drupal::entityTypeManager() ->getStorage('cfp_payment_request_checklist') ->create([ 'bundle' => $payment_request_type->get('payment_request_checklist_type'), 'created_during_correction' => $during_correction, 'created_after_deadline' => $after_deadline, ]); } } else { $payment_request_checklist = $this->generateDuplicateChecklist($during_correction, $after_deadline); } $payment_request_checklist->save(); $this->get('checklist')->appendItem($payment_request_checklist->id()); } /** * Generates new checklist. * * @param $correction * @param $deadline * * @return \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist */ private function generateDuplicateChecklist($correction, $deadline): CfpPaymentRequestChecklist { $last_checklist = $this->getLastChecklist(); $payment_request_checklist = $last_checklist->createDuplicate(); $payment_request_checklist->set('closed', FALSE); $payment_request_checklist->set('validation_passed', FALSE); $payment_request_checklist->set('created_during_correction', $correction); $payment_request_checklist->set('created_after_deadline', $deadline); return $payment_request_checklist; } /** * Returns last checklist. * * @return \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist */ public function getLastChecklist() { if ($this->get('checklist')->isEmpty()) { return FALSE; } /** @var \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist $checklist */ $checklist = $this->get('checklist')->get(($this->get('checklist')->count() - 1))->entity; return $checklist; } /** * @return \Drupal\cfp_payment_request\Entity\PrCorrectionData */ public function getCurrentCorrectionData() { $current_correction = $this->get('current_correction')->value; if ($item = $this->get('correction_data')->get($current_correction)) { if ($correction_data = $item->entity) { return $correction_data; } } return FALSE; } /** * @param $to_state */ public function appendTransition($to_state) { $this->get('transition_history')->appendItem([ 'to' => $to_state, 'timestamp' => \Drupal::time()->getCurrentTime(), 'user_id' => \Drupal::currentUser()->id(), 'user_email' => \Drupal::currentUser()->getEmail(), 'user_display_name' => \Drupal::currentUser()->getDisplayName(), 'deadline' => $this->get('correction_deadline')->value, ]); } /** * Total support. * * @return int * Total support. */ public function getTotalSupport() { // TODO: Check every call. return (int) $this->get('item_support_computed_total')->value; } /** * Amount to pay. * * @return int * Amount to pay. */ public function getAmountToPay() { return (int) $this->get('amount_to_pay')->value; } /** * Amount dedicated to advance payment. * * @return int * Amount dedicated to advance payment. */ public function getAmountDedicatedToAp() { return (int) $this->get('computed_amount_dedicated_to_ap')->value; } /** * Returns pr type. * * @return string * Returns value of config field pr type. */ public function getPaymentRequestType() { return $this->hasField('pr_type') ? $this->get('pr_type')->value : NULL; } /** * @return string */ public function getPaymentRequestTypeLabel() { if ($type = $this->getPaymentRequestType()) { $allowed_values = $this->get('pr_type')->getFieldDefinition()->getSetting('allowed_values'); return $allowed_values[$type]; } } /** * Set amount dedicated to advance payment coverage. * * @param $amount * Amount dedicated to advance payment. */ public function setAmountDedicatedToAp($amount) { $this->set('amount_dedicated_to_ap', $amount); return $this; } /** * @return string * Last reopening instructions. */ public function getLastReopeningInstructions() { if (!$this->get('previous_reopen_instructions')->isEmpty()) { return $this->get('previous_reopen_instructions')->get($this->get('previous_reopen_instructions')->count() - 1)->value; } } public function getSignatureToken() { /** @var \Drupal\halo_entity_cfp\Entity\Cfp $cfp */ $cfp = $this->getParent(); return $cfp->getApplicantEntity()->label(); } public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) { $fields = []; $pr_type = \Drupal::entityTypeManager()->getStorage('cfp_payment_request_type')->load($bundle); if ($pr_type) { $settings = $base_field_definitions['items']->getSettings(); $fields['items'] = clone $base_field_definitions['items']; $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_item_type') => $pr_type->get('payment_request_item_type')]; $fields['items']->setSettings($settings); $settings = $base_field_definitions['invoices']->getSettings(); $fields['invoices'] = clone $base_field_definitions['invoices']; $settings['handler_settings']['target_bundles'] = [$pr_type->get('payment_request_invoice_type') => $pr_type->get('payment_request_invoice_type')]; $fields['invoices']->setSettings($settings); } return $fields; } /** * Returns checklist that was before given checklist. * * @param \Drupal\cfp_payment_request\Entity\CfpPaymentRequestChecklist $payment_request_checklist */ public function getPreviousChecklist(CfpPaymentRequestChecklist $payment_request_checklist) { $current_entity = NULL; foreach ($this->get('checklist') as $item) { if ($looping_payment_request_checklist = $item->entity) { if ($looping_payment_request_checklist->id() == $payment_request_checklist->id()) { return $current_entity; } $current_entity = $looping_payment_request_checklist; } } } /** * {@inheritdoc} */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); // Add the published field. $fields += static::publishedBaseFieldDefinitions($entity_type); $fields['user_id'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Authored by')) ->setDescription(t('The user ID of author of the Payment request entity.')) ->setSetting('target_type', 'user') ->setSetting('handler', 'default') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['label'] = BaseFieldDefinition::create('string') ->setLabel(t('Kifizetési Igénylés sorszáma')) ->setDescription(t('The name of the Payment request entity.')) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['item_pay_off_total'] = BaseFieldDefinition::create('integer') ->setLabel('Igényelt elszámolási összeg (Ft)') ->setSetting('size', 'big') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['item_support_total'] = BaseFieldDefinition::create('integer') ->setLabel('Igényelt támogatási összeg (Ft)') ->setSetting('size', 'big') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields_definitions = isolate_numeric_field_types('cfp_payment_request_item'); foreach (static::ADD_UP_FIELDS as $add_up_field) { $field_name = $add_up_field . '_total'; if (!isset($fields[$field_name])) { $fields[$field_name] = self::createAddUpFieldFromFieldDefinition($fields_definitions[$add_up_field]); } } $fields['item_pay_off_computed_total']->setInitialValueFromField('item_pay_off_total'); $fields['item_support_computed_total']->setInitialValueFromField('item_support_total'); $fields['computed_amount_dedicated_to_ap'] = BaseFieldDefinition::create('integer') ->setLabel(t('Amount dedicated to advance payment')) ->setClass('\Drupal\cfp_payment_request\Plugin\Field\AmountDedicatedToAP') ->setComputed(TRUE) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['amount_dedicated_to_ap'] = BaseFieldDefinition::create('integer') ->setLabel(t('Amount dedicated to advance payment')) ->setSetting('size', 'big') ->setReadOnly(TRUE); $fields['amount_to_pay'] = BaseFieldDefinition::create('integer') ->setLabel(t('Amount to pay')) ->setComputed(TRUE) ->setClass('\Drupal\cfp_payment_request\Plugin\Field\PrAmountToPayItemList') ->setSetting('size', 'big') ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['items'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Items')) ->setSetting('target_type', 'cfp_payment_request_item') ->setSetting('handler', 'default') ->setSetting('handler_settings', [ 'target_bundles' => [], ]) ->setClass('\Drupal\cfp_payment_request\Plugin\Field\FieldType\PRFieldItemList') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['items_approvement_closed'] = BaseFieldDefinition::create('boolean') ->setLabel(t('Items approvement closed')) ->setReadOnly(TRUE); $fields['invoices'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Invoices')) ->setSetting('target_type', 'pr_invoice') ->setSetting('handler', 'default') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['checklist'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Checklist')) ->setSetting('target_type', 'cfp_payment_request_checklist') ->setSetting('handler', 'default') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); $fields['state'] = BaseFieldDefinition::create('state') ->setLabel(t('State')) ->setSetting('max_length', 255) ->setDefaultValue('open_state') ->setSetting('workflow', 'payment_request') ->setDisplayConfigurable('view', TRUE); $fields['comment'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Comment')) ->setDisplayConfigurable('view', TRUE); $fields['justification'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Justification')) ->setDisplayConfigurable('view', TRUE); $fields['reopen_instructions'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Reopen instructions')) ->setDisplayConfigurable('view', TRUE); $fields['previous_reopen_instructions'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Previous reopening instructions')) ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('view', TRUE); $fields['closed_date'] = BaseFieldDefinition::create('datetime') ->setLabel(t('Closed date')) ->setDisplayConfigurable('view', TRUE); $fields['submission_date'] = BaseFieldDefinition::create('datetime') ->setLabel(t('Last submission date')) ->setComputed(TRUE) ->setSettings([ 'state' => 'sent', 'search_for' => TransitionDateSearchItemList::SEARCH_LAST, 'field_name' => 'transition_history', ]) ->setClass('\Drupal\halo_transition_history_field\Plugin\Field\TransitionDateSearchItemList') ->setDisplayConfigurable('view', TRUE); $fields['first_submission_date'] = BaseFieldDefinition::create('timestamp') ->setLabel(t('First submission date')) ->setReadOnly(TRUE) ->setDisplayConfigurable('view', TRUE); $fields['current_correction'] = BaseFieldDefinition::create('integer') ->setLabel(t('Current correction')) ->setDefaultValue(0) ->setReadOnly(TRUE); $fields['correction_data'] = BaseFieldDefinition::create('entity_reference') ->setLabel('Correction data') ->setSetting('target_type', 'correction_data') ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('view', TRUE); $fields['old_prints'] = BaseFieldDefinition::create('file') ->setLabel(t('Older prints')) ->setSettings([ 'file_directory' => 'payment_request/new/print_files', 'max_filesize' => '100 MB', 'file_extensions' => 'pdf', 'description_field' => TRUE, 'uri_scheme' => 'public', ]) ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setDisplayConfigurable('view', TRUE); $fields['date_of_completion'] = BaseFieldDefinition::create('timestamp') ->setLabel(t('Date of completion')) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE); $fields['statements_accepted'] = BaseFieldDefinition::create('boolean') ->setLabel(t('Statements')) ->setReadOnly(TRUE) ->setDefaultValue(FALSE); $fields['attached_documents'] = BaseFieldDefinition::create('file') ->setLabel(t('Documents attached by an administrator')) ->setSettings([ 'file_directory' => 'pr_attached_files', 'max_filesize' => '100 MB', 'file_extensions' => 'pdf png jpg doc docx xls xlsx', 'description_field' => TRUE, 'uri_scheme' => 'public', ]) ->setDisplayConfigurable('view', TRUE); $fields['suspended_documents'] = BaseFieldDefinition::create('file') ->setLabel(t('Suspended documents')) ->setSettings([ 'file_directory' => 'payment_request/suspended_documents', 'max_filesize' => '100 MB', 'file_extensions' => 'doc docx jpeg jpg png pdf', 'description_field' => TRUE, 'uri_scheme' => 'public', ]) ->setDescription(t('Documents attached during suspension')) ->setDisplayConfigurable('view', TRUE) ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED); $fields['transition_history'] = BaseFieldDefinition::create('transition_history') ->setLabel(t('Transition History')) ->setSetting('state_field', 'state') ->setReadOnly(TRUE) ->setDisplayConfigurable('view', TRUE) ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED); $fields['status']->setDescription(t('A boolean indicating whether the Payment request is published.')); $fields['created'] = BaseFieldDefinition::create('created') ->setLabel(t('Created')) ->setDescription(t('The time that the entity was created.')); $fields['changed'] = BaseFieldDefinition::create('changed') ->setLabel(t('Changed')) ->setDescription(t('The time that the entity was last edited.')); $fields['correction_deadline'] = BaseFieldDefinition::create('timestamp') ->setLabel(t('Correction deadline')) ->setDescription(t('Deadline for submitting PR correction')) ->setDisplayConfigurable('view', TRUE); return $fields; } /** * Create add up field form definition. */ protected static function createAddUpFieldFromFieldDefinition(FieldDefinitionInterface $field_definition) { return BaseFieldDefinition::create($field_definition->getType()) ->setLabel($field_definition->getLabel() . ' ' . t('total')) ->setSettings($field_definition->getSettings()) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); } }
<?php /** * @file * Contains halo_views_2.module. */ use Drupal\cfp_modification_request\Entity\CfpModificationRequest; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Drupal\user\Entity\User; module_load_include('inc', 'halo_front_page', 'halo_front_page.views'); /** * Implements hook_toolbar(). */ function halo_front_page_toolbar() { return [ 'admin_front_page_link' => [ '#type' => 'toolbar_item', 'tab' => [ '#type' => 'link', '#title' => t('Admin front page'), '#url' => Url::fromRoute('halo_front_page.admin_front_page'), ], '#weight' => -5, ], ]; } /** * Implements hook_form_FORM_ID_alter(). */ function halo_front_page_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Cfp state. if (in_array($form['#id'], [ 'views-exposed-form-cfp-page-1', 'views-exposed-form-cfp-page-2', 'views-exposed-form-cfp-page-3', 'views-exposed-form-ced-main-data-page-1', 'views-exposed-form-cfp-modification-requests-page-1', ])) { $workflow_manager = \Drupal::service('plugin.manager.workflow'); $workflow = $workflow_manager->createInstance('cfp'); $states = $workflow->getStates(); $states = array_map(function ($state) { return $state->getLabel(); }, $states); $form['state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states, '#default_value' => reset($states), ]; $entity_field_manager = \Drupal::service('entity_field.manager'); $fields = $entity_field_manager->getFieldStorageDefinitions('cfp'); $sub_state_options = options_allowed_values($fields['sub_state']); unset($sub_state_options['void_sub_state']); $form['sub_state'] = [ '#title' => t('Sub state'), '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $sub_state_options, ]; } if ($form['#id'] === 'views-exposed-form-payment-requests-page-1') { $workflow_manager = \Drupal::service('plugin.manager.workflow'); $workflow = $workflow_manager->createInstance('payment_request'); $states = $workflow->getStates(); $states = array_map(function ($state) { return $state->getLabel(); }, $states); $form['state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states, ]; $form['state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states, ]; $entity_field_manager = \Drupal::service('entity_field.manager'); $fields = $entity_field_manager->getFieldStorageDefinitions('cfp'); $form['location_check_state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $fields['location_check_state']->getSetting('allowed_values'), ]; $form['location_check_type'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $fields['location_check_type']->getSetting('allowed_values'), ]; } if ($form['#id'] === 'views-exposed-form-locations-halo-page-1') { if (!isset($entity_field_manager)) { $entity_field_manager = \Drupal::service('entity_field.manager'); } $fields = $entity_field_manager->getFieldStorageDefinitions('cfp'); $form['location_check_state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $fields['location_check_state']->getSetting('allowed_values'), ]; $form['location_check_type'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $fields['location_check_type']->getSetting('allowed_values'), ]; } if ($form['#id'] === 'views-exposed-form-advance-payment-page-1') { $workflow_manager = \Drupal::service('plugin.manager.workflow'); $workflow = $workflow_manager->createInstance('advance_payment'); $states = $workflow->getStates(); $states = array_map(function ($state) { return $state->getLabel(); }, $states); $form['state'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states, ]; } if ($form['#id'] === 'views-exposed-form-cfp-modification-requests-page-1') { $form['request_type'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + _request_type_callback() ]; $form['state_1'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + CfpModificationRequest::getStates(), ]; } if ($form['#id'] === 'views-exposed-form-technical-report-page-1') { $workflow_manager = \Drupal::service('plugin.manager.workflow'); $workflow = $workflow_manager->createInstance('technical_report'); $states = $workflow->getStates(); $states = array_map(function ($state) { return $state->getLabel(); }, $states); $form['state'] = $form['transition_history_to'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + $states ]; } // First submission date. if (in_array($form['#id'], ['views-exposed-form-payment-requests-page-1', 'views-exposed-form-technical-report-page-1', 'views-exposed-form-advance-payment-page-1'])) { $form['first_submission_date_wrapper']['first_submission_date']['min']['#type'] = 'date'; $form['first_submission_date_wrapper']['first_submission_date']['min']['#title'] = '-tól'; $form['first_submission_date_wrapper']['first_submission_date']['max']['#type'] = 'date'; $form['first_submission_date_wrapper']['first_submission_date']['max']['#title'] = '-ig'; // if (isset($form['correction_deadline_wrapper'])) { // $form['correction_deadline_wrapper']['correction_deadline']['min']['#type'] = 'date'; // $form['correction_deadline_wrapper']['correction_deadline']['min']['#title'] = '-tól'; // $form['correction_deadline_wrapper']['correction_deadline']['max']['#type'] = 'date'; // $form['correction_deadline_wrapper']['correction_deadline']['max']['#title'] = '-ig'; // } if (isset($form['deadline_expired_wrapper'])) { $form['deadline_expired_wrapper']['deadline_expired']['min']['#type'] = 'date'; $form['deadline_expired_wrapper']['deadline_expired']['min']['#title'] = '-tól'; $form['deadline_expired_wrapper']['deadline_expired']['max']['#type'] = 'date'; $form['deadline_expired_wrapper']['deadline_expired']['max']['#title'] = '-ig'; } } if ($form['#id'] === 'views-exposed-form-applicants-page-1') { $form['cfp_type_group_owner_value'] = [ '#type' => 'select', '#options' => [ '' => t('- Any -'), ] + _cfp_group_types(), ]; } if ($form['#id'] === 'views-exposed-form-locations-page-1') { $form['closed']['#options'][1] = t('Closed'); $form['closed']['#options'][0] = t('Open'); $form['date']['#type'] = 'date'; $form['date_1']['#type'] = 'date'; } } /** * Implements hook_link_alter(). */ function halo_front_page_link_alter(&$variables) { $url = $variables['url']; if ($url->isExternal() || !$url->isRouted()) { return; } $route = $url->getRouteName(); if ($route === 'user.page') { $variables['text'] = \Drupal::currentUser()->getDisplayName(); } } /** * Implements hook_user_format_name_alter(). */ function halo_front_page_user_format_name_alter(&$name, AccountInterface $account) { $user = User::load($account->id()); $name = $user->field_lastname->value . ' ' . $user->field_firstname->value; } /** * Implements hook_views_data_alter(). */ function halo_front_page_views_data_alter(array &$data) { $data['review']['assignable_filter'] = [ 'title' => t('Assignable filter'), 'filter' => [ 'title' => t('Assignable filter'), 'help' => t('Filters by assignable entities.'), 'field' => 'id', 'id' => 'assignable_filter', ], ]; }
<?php namespace Drupal\cfp_payment_request\Plugin\views\filter; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\views\Plugin\views\filter\FilterPluginBase; /** * Filter PR view by correction deadline date. * * @ingroup views_filter_handlers * * @ViewsFilter("pr_correction_deadline") */ class PaymentRequestCorrectionDeadlineFilter extends FilterPluginBase { use StringTranslationTrait; /** * {@inheritDoc} */ public function acceptExposedInput($input) { return TRUE; } /** * {@inheritDoc} */ public function buildExposedForm(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed'])) { return; } $identifier = $this->options['expose']['identifier']; $exposed_input = $this->view->getExposedInput(); $form[$identifier] = [ '#type' => 'fieldset', '#title' => $this->t('Correction deadline'), ]; $form[$identifier]['start_date'] = [ '#type' => 'date', '#title' => $this->t('Start date'), '#default_value' => $exposed_input['start_date'] ?? NULL, ]; $form[$identifier]['end_date'] = [ '#type' => 'date', '#title' => $this->t('End date'), '#default_value' => $exposed_input['end_date'] ?? NULL, ]; return $form; } /** * {@inheritDoc} */ public function query() { $this->ensureMyTable(); /** @var \Drupal\views\Plugin\views\query\Sql $query */ $query = $this->query; $query->addTable("cfp_payment_request__transition_history"); $input = $this->view->getExposedInput(); $start = isset($input['start_date']) ? strtotime($input['start_date']) : NULL; if ($start) { $query->addWhere($this->options['group'], "cfp_payment_request__transition_history.transition_history_deadline", $start, ">="); } $end = isset($input['end_date']) ? strtotime($input['end_date']) : NULL; if ($end) { $query->addWhere($this->options['group'], "cfp_payment_request__transition_history.transition_history_deadline", $end, "<="); } } }
<?php namespace Drupal\cfp_payment_request\Entity; use Drupal\views\EntityViewsData; /** * Provides Views data for Payment request entities. */ class PaymentRequestViewsData extends EntityViewsData { /** * {@inheritdoc} */ public function getViewsData() { $data = parent::getViewsData(); $data['cfp_payment_request']['correction_deadline']['filter']['id'] = 'pr_correction_deadline'; return $data; } }
<?php namespace Drupal\pos_entity_cfp\Plugin; use Drupal\Component\Plugin\PluginBase; use Drupal\Core\Access\AccessResult; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountProxyInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; use Drupal\file\Entity\File; use Drupal\pos_entity_cfp\Form\CorrectionTextForm; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Base class for Cfp correction type plugins. */ abstract class CfpCorrectionTypeBase extends PluginBase implements CfpCorrectionTypeInterface, ContainerFactoryPluginInterface { use StringTranslationTrait; /** * Form builder. * * @var \Drupal\Core\Form\FormBuilderInterface */ protected $formBuilder; /** * State to handle. * * @var string */ protected $correctionState; /** * Correction order. * * @var int */ protected $correctionOrder; /** * Cfp to handle. * * @var \Drupal\pos_entity_cfp\Entity\Cfp */ protected $cfp; /** * @var \Drupal\Core\Session\AccountProxyInterface */ protected $currentUser; /** * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $form_builder, AccountProxyInterface $account_proxy, EntityTypeManagerInterface $entity_type_manager) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->correctionState = $configuration['correctionState']; $this->cfp = $configuration['cfp']; $this->formBuilder = $form_builder; $this->currentUser = $account_proxy; $this->entityTypeManager = $entity_type_manager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('form_builder'), $container->get('current_user'), $container->get('entity_type.manager') ); } /** * {@inheritdoc} */ public function getCorrectionState() { return $this->correctionState; } /** * {@inheritdoc} */ public function getCorrectionOrder() { return $this->correctionOrder; } /** * {@inheritdoc} */ public function getCfp() { return $this->cfp; } /** * {@inheritdoc} */ public function startCorrection() { return TRUE; } /** * {@inheritdoc} */ public function endCorrection() { return TRUE; } /** * Get correction config form. * * @return array * Config form. */ public function getCorrectionConfigForm() { return []; } /** * {@inheritdoc} */ public function isCorrectionActive() { return $this->getCfp()->getState()->getId() === $this->getCorrectionState(); } /** * Check if multiple. * * @return bool * Is multiple. */ public function isMultiple() { $definition = $this->getPluginDefinition(); return isset($definition['multiple']) ? $definition['multiple'] : FALSE; } /** * Get correction text. */ abstract public function getCorrectionText(); /** * Get correction question element. */ public function getCorrectionQuestionElement() { return $this->formBuilder->getForm(CorrectionTextForm::class, $this->getCfp(), $this->getCorrectionState(), $this->getPluginId()); } /** * Returns if user has access to start correction. * * @return bool * Returns if user has access to start correction. */ public function userHasAccessToStartCorrection() { if ($this->cfp->getState()->getId() !== $this->correctionState) { return FALSE; } if ($this->cfp->isInCorrection()) { return FALSE; } return $this->currentUser->hasPermission('start cfp correction'); } /** * Get correction operations form. */ public function getCorrectionOperationsForm() { $state_item = $this->getCfp()->getState(); $current_url = Url::fromRoute('<current>'); if ($this->getCfp()->getSubState() != 'correction_started') { if ($this->userHasAccessToStartCorrection()) { $correction_data = $this->getCfp()->getCorrectionData($state_item->getId()); $element['start_correction'] = [ '#type' => 'link', '#title' => $this->t('Start correction @order', ['@order' => number_to_roman_representation($correction_data['number_of_corrections'] + 1)]), '#url' => Url::fromRoute('pos_entity_cfp.confirm_start_correction_user_cfp_form', [ 'cfp' => $this->getCfp()->id(), 'destination' => $current_url->toString(), ]), '#attributes' => [ 'class' => ['button'], ], ]; } } else { $element['start_correction'] = [ '#type' => 'markup', '#markup' => '<div class="correction-info-text">' . $this->t('Correction is in progress') . '</div>', ]; if ($this->currentUser->hasPermission('access correction form')) { $plugin_definition = $this->getCfp()->getCurrentStateCorrectionPlugin()->getPluginDefinition(); $element['help_correction'] = [ '#type' => 'link', '#title' => $this->t('Help applicant with correction'), '#url' => Url::fromRoute($plugin_definition['correction_form_route'], [ 'cfp' => $this->getCfp()->id(), 'destination' => $current_url->toString(), ]), '#attributes' => [ 'class' => ['button'], ], ]; $element['close_correction'] = [ '#type' => 'link', '#title' => $this->t('Close correction'), '#url' => Url::fromRoute('pos_entity_cfp.confirm_correction_user_cfp_form', [ 'cfp' => $this->getCfp()->id(), 'destination' => $current_url->toString(), ]), '#attributes' => [ 'class' => ['button'], ], ]; } } return $element ?? []; } /** * Correction answers. */ public function getCorrectionAnswersElement() { $correction_data = $this->getCfp()->getCorrectionData($this->getCorrectionState()); $element = []; foreach ($correction_data['info'] as $correction_order => $correction_datum) { if (!is_numeric($correction_order)) { continue; } if (isset($correction_datum['started'])) { $started_date = DrupalDateTime::createFromTimestamp($correction_datum['started']); $started_date->setTimezone(new \DateTimeZone('Europe/Budapest')); $element[$correction_order]['started'] = [ '#type' => 'item', '#title' => $this->t('Correction started'), '#markup' => $started_date->format('d/m/Y - H:i'), ]; } if (isset($correction_datum['ended'])) { $ended_date = DrupalDateTime::createFromTimestamp($correction_datum['ended']); $ended_date->setTimezone(new \DateTimeZone('Europe/Budapest')); $element[$correction_order]['ended'] = [ '#type' => 'item', '#title' => $this->t('Correction ended'), '#markup' => $ended_date->format('d/m/Y - H:i'), ]; } if (isset($correction_data['info'][$correction_order]['correction_text'])) { $element[$correction_order][] = [ '#type' => 'item', // @codingStandardsIgnoreStart '#title' => $this->t(ucfirst('correction') . ' text @order', [ '@order' => number_to_roman_representation($correction_order + 1), ]), // @codingStandardsIgnoreEnd 'markup' => ['#markup' => check_markup($correction_data['info'][$correction_order]['correction_text'])], ]; } elseif (isset($correction_data['info'][$correction_order]['correction_text'])) { $element[$correction_order][] = [ '#type' => 'item', // @codingStandardsIgnoreStart '#title' => $this->t(ucfirst('correction') . ' text @order', [ '@order' => number_to_roman_representation($correction_order + 1), ]), // @codingStandardsIgnoreEnd 'markup' => ['#markup' => check_markup($correction_data['info'][$correction_order]['correction_text'])], ]; } if (isset($correction_datum['correction_answer_text']) && !empty($correction_datum['correction_answer_text'])) { $element[$correction_order]['correction_text'] = [ '#type' => 'item', '#title' => t('Correction answer @order', ['@order' => number_to_roman_representation($correction_order + 1)]), '#markup' => check_markup($correction_datum['correction_answer_text']), ]; } if (isset($correction_datum['correction_files']) && !empty($correction_datum['correction_files'])) { foreach ($correction_datum['correction_files'] as $delta => $fid) { $file = File::load($fid); $element[$correction_order]['correction_files'][$delta] = [ '#theme' => 'file_link', '#file' => $file, '#cache' => [ 'tags' => $file->getCacheTags(), ], ]; } } if (isset($element[$correction_order])) { $element[$correction_order]['#type'] = 'fieldset'; $element[$correction_order]['#title'] = $this->t('Correction @order', ['@order' => number_to_roman_representation($correction_order + 1)]); } if (isset($correction_datum['started']) && !isset($correction_datum['ended'])) { $started_date = DrupalDateTime::createFromTimestamp($correction_datum['started']); $started_date->setTimezone(new \DateTimeZone('Europe/Budapest')); $now = DrupalDateTime::createFromTimestamp(time()); $now->setTimezone(new \DateTimeZone('Europe/Budapest')); $days_limit = $this->pluginDefinition['correction_limit_in_days']; if ($started_date->diff($now)->d > $days_limit) { $element[$correction_order]['warning'] = [ '#type' => 'markup', '#markup' => '<p class="correction-warning">' . $this->t('@number_of_days days limit expired!', [ '@number_of_days' => $days_limit, ]) . '</p>', ]; } } } if (!empty($element)) { $element['#type'] = 'container'; } return $element; } }
<?php use Drupal\Core\Entity\EntityTypeInterface; /** * Implements hook_entity_bundle_field_info_alter(). */ function pos_cfp_bundle_2022_01_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { if ($entity_type->id() === 'review' && $bundle === 'acceptance_2022_01') { $fields['cf_acceptable_application']->addConstraint('ConditionalValues', [ 'conditions' => [ [ 'required_choice' => 'no', 'on_values' => [ 'cf_submit_ontime' => ['no'], 'cf_submit_original_ontime' => ['no'], 'cf_scanned_application' => ['no'], 'cf_application_submitt' => ['no'], 'cf_liquidation_applicant' => ['no'], 'cf_rpg_registration' => ['no'], 'cf_anti_labour_protection' => ['no'], 'cf_disqualification_conditions' => ['no'], ], 'conjunction' => 'OR', 'error_message' => 'Ukoliko su polja iz prve dve sekcije "Ne", ovo polje mora biti Ne.', ], [ 'required_choice' => 'yes', 'on_values' => [ 'cf_submit_ontime' => ['yes'], 'cf_submit_original_ontime' => ['yes'], 'cf_scanned_application' => ['yes'], 'cf_application_submitt' => ['yes'], 'cf_liquidation_applicant' => ['yes'], 'cf_rpg_registration' => ['yes'], 'cf_anti_labour_protection' => ['yes'], 'cf_disqualification_conditions' => ['yes'], ], 'conjunction' => 'AND', 'error_message' => 'Ukoliko su sva polja iz prve dve sekcije "Da", ovo polje mora biti Da.', ] ], ]); } } /** * Implements hook_review_passed_alter(). */ function pos_cfp_bundle_2022_01_review_passed_alter(&$passed, $entity) { if ($entity->bundle() === 'technical_review_2022_01') { $passed = $entity->isPrintConfirmed(); } } /** * Implements hook_form_FORM_ID_alter(). */ function pos_entity_review_form_review_acceptance_2022_01_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { if (isset($form['cf_application_identifier'])) { $form['cf_application_identifier']['#states'] = [ 'visible' => [ ':input[name="cf_only_one_request"]' => ['value' => 'no'] ], 'required' => [ ':input[name="cf_only_one_request"]' => ['value' => 'no'] ] ]; } $form['#validate'][] = 'custom_field_validation'; } function custom_field_validation($form, \Drupal\Core\Form\FormStateInterface $form_state) { $only_request_field = !empty($form_state->getValue('cf_only_one_request')) ? $form_state->getValue('cf_only_one_request')[0]['value'] : ''; $cf_application_identifier = $form_state->getValue('cf_application_identifier'); if ($only_request_field === 'no' && empty($cf_application_identifier[0]['value'])) { $form_state->setErrorByName('cf_application_identifier', t('Identifikator aplikacije je obavezan ako je podnosioc zahtjeva podnio više od jednog zahtjeva')); } } /** * Implements hook_form_FORM_ID_alter(). */ function pos_cfp_bundle_2022_01_form_review_legal_check_2022_01_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { $form_object = $form_state->getFormObject(); $review = $form_object->getEntity(); foreach ($review->getFields() as $machine_name => $field) { if ($field->getFieldDefinition()->getType() === 'options_correction') { if ($review->get($machine_name)->value === 'replacement') { $form[$machine_name]['#attributes'] = [ 'class' => ['red_field'], ]; } } } }
<?php namespace Drupal\pos_entity_email_template\Plugin\Action; use Drupal\Component\Utility\Crypt; use Drupal\Core\Access\AccessResult; use Drupal\Core\Action\ConfigurableActionBase; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\RemoveCommand; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Site\Settings; use Drupal\file\Entity\File; /** * Provides a a Send Applicant email action. * * @Action( * id = "send_applicant_email", * label = @Translation("Send Applicant email"), * type = "user", * category = @Translation("Custom"), * confirm = TRUE * ) * * @DCG * For a simple updating entity fields consider extending FieldUpdateActionBase. */ class SendApplicantEmailAction extends ConfigurableActionBase { /** * {@inheritdoc} */ public function defaultConfiguration() { return [ 'title' => '', 'body' => '', 'attachment_files' => [], ]; } /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { //@todo: Check which templates will be available for this kind of e-mails. Maybe create a new type of templates. $templates = \Drupal::entityTypeManager() ->getStorage('pos_entity_email_template')->loadMultiple(); $options = ['_none' => $this->t('None')]; foreach ($templates as $template) { $options[$template->id()] = $template->id() . ') ' . $template->label(); } ksort($options, SORT_NUMERIC); $form['template'] = [ '#type' => 'select', '#title' => $this->t('Template'), '#options' => $options, '#ajax' => [ 'callback' => '\Drupal\pos_entity_email_template\Plugin\Action\SendApplicantEmailAction::replaceElements' ] ]; $form['title'] = [ '#title' => $this->t('Title'), '#type' => 'textfield', '#wrapper_attributes' => [ 'class' => 'mrmot-title', ], ]; $form['body'] = [ '#type' => 'text_format', '#title' => $this->t('Body'), '#format' => 'ckeditor_5', '#wrapper_attributes' => [ 'class' => 'mrmot-body', ], ]; $form['attachment_files'] = [ '#type' => 'managed_file', '#title' => $this->t('Attachments'), '#description' => t('Allowed types: pdf xls xlsx odt doc docx.'), '#upload_validators' => [ 'file_validate_extensions' => ['pdf xls xlsx odt doc docx'], ], '#upload_location' => 'public://email_attachments/', '#progress_indicator' => 'bar', '#multiple' => TRUE, '#wrapper_attributes' => [ 'class' => 'mrmot', ], ]; return $form; } /** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['title'] = $form_state->getValue('title'); $this->configuration['body'] = $form_state->getValue('body')['value']; $this->configuration['file_ids'] = $form_state->getValue('attachment_files'); foreach ($form_state->getValue('attachment_files') as $fid) { $file = File::load($fid); $this->configuration['attachments'][] = [ 'filepath' => $file->getFileUri(), 'filename' => $file->getFilename(), 'filemime' => $file->getMimeType(), ]; } } /** * {@inheritdoc} */ public function access($node, AccountInterface $account = NULL, $return_as_object = FALSE) { return $return_as_object ? AccessResult::allowedIfHasPermission($account, 'send emails from administration') : $account->hasPermission('send emails from administration'); } /** * {@inheritdoc} */ public function execute($user = NULL) { $params['headers'] = [ 'Content-Type' => 'text/html; charset=UTF-8;', 'Content-Transfer-Encoding' => '8Bit', ]; /** @var \Drupal\Core\Mail\MailManagerInterface $mail_manager */ $mail_manager = \Drupal::service('plugin.manager.mail'); $user_mail = $user->getEmail(); $emails = [$user_mail]; $params['title'] = $this->configuration['title']; $params['message'] = $this->configuration['body']; $params['file_ids'] = $this->configuration['file_ids']; $params['attachments'] = $this->configuration['attachments']; $params['entity'] = $user; $result = $mail_manager->mail('pos_entity_applicant', 'pos_entity_applicant_mail_send', implode(',', $emails), 'hu', $params, NULL, TRUE); } public static function replaceElements(array &$form, FormStateInterface $form_state) { // @todo: Check what kind of templates will be used. $triggering_element = $form_state->getTriggeringElement(); $response = new AjaxResponse(); /** @var \Drupal\pos_entity_email_template\Entity\EmailTemplateEntity $email_template */ if (is_numeric($triggering_element['#value'])) { $email_template = \Drupal::entityTypeManager() ->getStorage('pos_entity_email_template') ->load($triggering_element['#value']); $form['title']['#value'] = $email_template->getTitle(); $form['body']['value']['#value'] = $email_template->getBody(); $form['attachment_files']['#value']['fids'] = array_unique(array_merge($form['attachment_files']['#value']['fids'], $email_template->getAttachmentsInElementFormat())); $form['attachment_files']['fids']['#value'] = array_unique(array_merge($form['attachment_files']['fids']['#value'], $email_template->getAttachmentsInElementFormat())); foreach ($form['attachment_files']['#value']['fids'] as $fid) { $form['attachment_files']['#files'][$fid] = File::load($fid); } $element = &$form['attachment_files']; foreach ($element['#files'] as $delta => $file) { $file_link = [ '#theme' => 'file_link', '#file' => $file, ]; if ($element['#multiple']) { $element['file_' . $delta]['selected'] = [ '#type' => 'checkbox', '#title' => \Drupal::service('renderer')->renderPlain($file_link), ]; } else { $element['file_' . $delta]['filename'] = $file_link + ['#weight' => -10]; } // Anonymous users who have uploaded a temporary file need a // non-session-based token added so $this->valueCallback() can check // that they have permission to use this file on subsequent submissions // of the same form (for example, after an Ajax upload or form // validation error). if ($file->isTemporary() && \Drupal::currentUser()->isAnonymous()) { $element['file_' . $delta]['fid_token'] = [ '#type' => 'hidden', '#value' => Crypt::hmacBase64('file-' . $delta, \Drupal::service('private_key')->get() . Settings::getHashSalt()), ]; } } $form_state->setRebuild(TRUE); } else { $form['title']['#value'] = ''; $form['body']['value']['#value'] = ''; } $response->addCommand(new RemoveCommand('[id^=edit-body-format]')); $response->addCommand(new ReplaceCommand('.mrmot-body', $form['body'])); $response->addCommand(new ReplaceCommand('.mrmot-title', $form['title'])); $response->addCommand(new ReplaceCommand('.mrmot', $form['attachment_files'])); return $response; } }
<?php /** * @file * Contains pos_entity_applicant.module. */ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; use Drupal\pos_entity_applicant\Entity\ApplicantType; use Drupal\pos_entity_applicant\Event\UserCancelEvent; module_load_include('inc', 'pos_entity_applicant', 'pos_entity_applicant.tokens'); module_load_include('inc','pos_entity_applicant', 'pos_entity_applicant.views'); module_load_include('inc', 'pos_entity_applicant', 'pos_entity_applicant.validation'); /** * Implements hook_help(). */ function pos_entity_applicant_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the pos_entity_applicant module. case 'help.page.pos_entity_applicant': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; $output .= '<p>' . t('General Applicant Entity') . '</p>'; return $output; default: } } /** * Implements hook_theme(). */ function pos_entity_applicant_theme() { $theme = []; $theme['applicant'] = [ 'render element' => 'elements', 'file' => 'applicant.page.inc', 'template' => 'applicant', ]; $theme['applicant_content_add_list'] = [ 'render element' => 'content', 'variables' => ['content' => NULL], 'file' => 'applicant.page.inc', ]; return $theme; } /** * Implements hook_theme_suggestions_HOOK(). */ function pos_entity_applicant_theme_suggestions_applicant(array $variables) { $suggestions = []; $entity = $variables['elements']['#applicant']; $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_'); $suggestions[] = 'applicant__' . $sanitized_view_mode; $suggestions[] = 'applicant__' . $entity->bundle(); $suggestions[] = 'applicant__' . $entity->bundle() . '__' . $sanitized_view_mode; $suggestions[] = 'applicant__' . $entity->id(); $suggestions[] = 'applicant__' . $entity->id() . '__' . $sanitized_view_mode; return $suggestions; } /** * Implements hook_entity_extra_field_info(). */ function pos_entity_applicant_entity_extra_field_info() { $extra = []; foreach (ApplicantType::loadMultiple() as $bundle) { $extra['applicant'][$bundle->id()]['display']['edit_link'] = [ 'label' => t('Edit link'), 'description' => 'Entity edit link', 'weight' => 20, 'visible' => TRUE, ]; $extra['applicant'][$bundle->id()]['display']['view_link'] = [ 'label' => t('View link'), 'description' => 'Entity view link', 'weight' => 20, 'visible' => TRUE, ]; $extra['applicant'][$bundle->id()]['display']['state_description'] = [ 'label' => t('State description'), 'description' => 'Shows state description defined in applicant bundle', 'weight' => 20, 'visible' => TRUE, ]; $extra['applicant'][$bundle->id()]['display']['locked_button'] = [ 'label' => t('Locked button'), 'description' => 'Locked', 'weight' => 20, 'visible' => TRUE, ]; $extra['applicant'][$bundle->id()]['display']['representative'] = [ 'label' => t('Ovlašteno lice za zastupanje'), 'description' => t('Ime i prezime predstavnika'), 'weight' => 20, 'visible' => FALSE, ]; } return $extra; } /** * Implements hook_ENTITY_TYPE_view(). */ function pos_entity_applicant_applicant_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { if ($display->getComponent('edit_link') && $entity->access('update')) { $build['edit_link'] = [ '#type' => 'link', '#title' => t('Edit'), '#url' => Url::fromRoute('entity.' . $entity->getEntityTypeId() . '.edit_form', [ $entity->getEntityTypeId() => $entity->id(), ]), '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('view_link') && $entity->access('view')) { $build['view_link'] = [ '#type' => 'link', '#title' => t('View'), '#url' => Url::fromRoute('entity.' . $entity->getEntityTypeId() . '.canonical', [ $entity->getEntityTypeId() => $entity->id(), ]), '#attributes' => [ 'class' => ['button'], ], ]; } if ($display->getComponent('state_description')) { $applicant_type = ApplicantType::load($entity->bundle()); if ($description = $applicant_type->getStateDescription($entity->getState())) { $build['state_description'] = [ '#type' => 'inline_template', '#template' => '<div class="applicant__state-description">' . $description . '</div>', ]; } } if ($display->getComponent('locked_button')) { if (!$entity->isLocked() && (bool) $entity->get('validation_passed')->value) { $build['locked_button'] = [ '#type' => 'link', '#url' => new Url('pos_entity_applicant.applicant_lock_data_confirm', [ 'applicant' => $entity->id(), ]), '#title' => t('Lock'), '#attributes' => [ 'class' => [ 'button', ], ], ]; } } if ($display->getComponent('representative') && $entity->get('company_representative')->target_id) { $representative = $entity->get('company_representative')->entity; $rep_name = $representative->get('field_firstname')->value ?? ''; $rep_lastname = $representative->get('field_lastname')->value ?? ''; if ($rep_name === '' && $rep_lastname === '') { } else { $build['representative'] = [ '#type' => 'container', 'zastupnik' => [ '#type' => 'container', 'label' => [ '#type' => 'markup', '#markup' => t('Ovlašteno lice za zastupanje'), ], '#attributes' => [ 'class' => ['current_applicant_representative-label'], ] ], 'representative' => [ '#type' => 'markup', '#markup' => '<div class="current_applicant_representative-item">' . $rep_lastname . ' ' . $rep_name . '</div>', ] ]; } } } /** * Implements hook_cron(). */ function pos_entity_applicant_cron() { $query = \Drupal::database()->query('SELECT applicant.id FROM applicant WHERE applicant.id NOT IN (SELECT applicant FROM users_field_data) '); $storage = \Drupal::entityTypeManager()->getStorage('applicant'); while ($row = $query->fetch()) { $company = $storage->load($row->id); $company->delete(); } } /** * Get applicant bundles. * * @return array * Applicant bundles. */ function get_applicant_bundles() { $applicant_types = ApplicantType::loadMultiple(); $applicant_list = []; foreach ($applicant_types as $applicant_type) { $applicant_list[$applicant_type->id()] = $applicant_type->label(); } return $applicant_list; } /** * Implements hook_form_FORM_ID_alter(). */ function pos_entity_applicant_form_applicant_company_edit_form_alter(&$form, FormStateInterface $form_state) { $form['vat_number_entitled_true']['#states'] = [ 'visible' => [ ':input[name="entitled_to_vat_refund"]' => ['value' => 'yes'] ], ]; $form['annual_income']['widget']['#description'] = 'Molimo vas da unesete najmanje podatke za 2021.godinu, ukoliko je vaše pravno lice osnovano prije 31. decembra 2021.'; } /** * Implements hook_form_FORM_ID_alter(). */ function pos_entity_applicant_form_applicant_individual_edit_form_alter(&$form, FormStateInterface $form_state) { $form['vat_number_entitled_true']['#states'] = [ 'visible' => [ ':input[name="entitled_to_vat_refund"]' => ['value' => 'yes'] ], ]; $form['annual_income']['widget']['#description'] = 'Molimo vas da unesete najmanje podatke za 2021.godinu, ukoliko je vaše gazdinstvo osnovano prije 31. decembra 2021.'; } /** * Implements hook_inline_entity_form_entity_form_alter(). */ function pos_entity_applicant_inline_entity_form_entity_form_alter(array &$entity_form, FormStateInterface &$form_state) { if ($entity_form['#entity']->getEntityTypeId() === 'basic' && $entity_form['#entity']->bundle() === 'owned_other_companies') { if (isset($entity_form['cf_vat_number_entitled_true'])) { $entity_form['cf_vat_number_entitled_true']['#states'] = [ 'visible' => [ [ ':input[name="cf_owners_companies[form][inline_entity_form][entities][0][form][cf_entitled_to_vat_refund]"]' => ['value' => 1], ], 'or', [ ':input[name="cf_owners_companies[form][0][cf_entitled_to_vat_refund]"]' => ['value' => 1], ], ], ]; } } } /** * Implements hook_views_data(). */ function pos_entity_applicant_views_data() { $data = []; $data['views']['applicant_has_cfp'] = [ 'title' => t('Did the applicant start cfp - Custom filter'), 'filter' => [ 'title' => t('Did the applicant start cfp - Custom filter'), 'field' => 'id', 'id' => 'applicant_has_cfp', ], ]; $data['views']['applicant_cfp'] = [ 'title' => t('Did the applicant start cfp - NEW Custom filter'), 'filter' => [ 'title' => t('Did the applicant start cfp - NEW Custom filter'), 'field' => 'id', 'id' => 'applicant_cfp' ], ]; return $data; } /** * Implements hook_ENTITY_TYPE_predelete(). */ function pos_entity_applicant_user_predelete(\Drupal\Core\Entity\EntityInterface $entity) { $event = new UserCancelEvent($entity); $event_dispatcher = \Drupal::service('event_dispatcher'); $event_dispatcher->dispatch($event, UserCancelEvent::EVENT_NAME); } /** * Implements hook_mail(). */ function pos_entity_applicant_mail($key, &$message, $params) { switch($key) { case 'pos_entity_applicant_mail_send': $mail_sender = \Drupal::config('system.site')->get('mail'); $message['headers']['From'] = $mail_sender; $message['headers']['Sender'] = $mail_sender; $message['headers']['Return-Path'] = $mail_sender; $message['headers']['Content-Type'] = 'text/html'; $message['from'] = $mail_sender; $message['subject'] = $params['title']; /** @var \Drupal\Core\Utility\Token $token */ $token = \Drupal::service('token'); /** @var \Drupal\pos_entity_applicant\Entity\Applicant $applicant */ $applicant = $params['entity']->get('applicant')->entity ?? NULL; // Not using this tokens currently, but maybe we will some day in the future. $token_data = [ 'applicant' => $applicant, 'user' => $params['entity'], ]; $message['subject'] = $token->replace($params['title'], $token_data, ['clear' => TRUE]); $message['body'][] = $token->replace($params['message'], $token_data, ['clear' => TRUE]); $files = []; if (isset($params['attachments'])) { $message['params']['files'] = $params['attachments']; foreach ($params['attachments'] as $file) { $files[] = $file['filename']; } } $email_log = \Drupal::entityTypeManager() ->getStorage('pos_entity_email_logs') ->create([ 'title' => $message['subject'], 'body' => isset($message['body'][0]) ? $message['body'][0] : '', ]); $email_log->save(); break; } }
<?php namespace Drupal\maintenance_2020_01\Plugin\Field\FieldFormatter; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; /** * Plugin implementation of the 'Maintenance Documents' formatter. * * @FieldFormatter( * id = "maintenance_documents", * label = @Translation("Maintenance Documents"), * field_types = { * "file" * } * ) */ class MaintenanceDocumentsFormatter extends FormatterBase { /** * {@inheritdoc} */ public static function defaultSettings() { return parent::defaultSettings(); } /** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { $element = []; foreach ($items as $delta => $item) { $description = $item->getValue()['description']; $file = $item->entity; $created_timestamp = $file->get('created')->value; $element[$delta] = [ '#theme' => 'file_link', '#file' => $file, '#description' => $description . ' (' . \Drupal::service('date.formatter')->format($created_timestamp, 'custom', 'Y.m.d') . ')', '#cache' => [ 'tags' => $file->getCacheTags(), ], ]; } return $element; } }
function pos_core_update_9014($sandbox) { $user_ids_to_delete = [32, 30, 29, 28, 27, 24, 22, 20, 16, 15, 14, 13]; // Delete all cfps where the users are going to be deleted. \Drupal::database()->delete('cfp') ->condition('user_id', $user_ids_to_delete, 'IN') ->execute(); // Delete all applicants associated to the user that is going to be deleted. foreach ($user_ids_to_delete as $user_id_to_delete) { $user = \Drupal::entityTypeManager() ->getStorage('user') ->load($user_id_to_delete); if ($applicant_id = $user->get('applicant')->target_id) { \Drupal::database() ->delete('applicant') ->condition('id', $applicant_id) ->execute(); } // Delete users. $user->delete(); } }
// Ovo ide ispod prethodnog filtera (koji ću verovatno i obrisati). $data['views']['applicant_cfp'] = [ 'title' => t('Did the applicant start cfp - NEW Custom filter'), 'filter' => [ 'title' => t('Did the applicant start cfp - NEW Custom filter'), 'field' => 'id', 'id' => 'applicant_cfp' ], ];
<?php namespace Drupal\pos_entity_applicant\Plugin\views\filter; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\filter\FilterPluginBase; use Symfony\Contracts\Translation\TranslatorTrait; /** * Class ProgramCoordinatorFilter * * @ingroup views_filter_handlers * * @ViewsFilter("applicant_cfp") */ class ApplicantCfpFilter extends FilterPluginBase { use TranslatorTrait; /** * {@inheritDoc} */ public function acceptExposedInput($input) { return TRUE; } public function buildExposedForm(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed'])) { return; } $identifier = $this->options['expose']['identifier']; $exposed_input = $this->view->getExposedInput(); $form[$identifier] = [ '#type' => 'select', '#title' => $this->t('Da li aplikant ima konkurs?'), '#options' => [ NULL => $this->t('- Any -'), 'yes' => $this->t('Da'), 'no' => $this->t('Ne'), ], '#default_value' => $exposed_input, '#validated' => TRUE, ]; return $form; } public function query() { $this->ensureMyTable(); /** @var \Drupal\views\Plugin\views\query\Sql $query */ $query = $this->query; $input = $this->view->getExposedInput(); if (isset($input['applicant_cfp']) && !empty($input['applicant_cfp'])) { $input['applicant_cfp'] === 'yes' ? $query->addWhereExpression(0,"users_field_data.uid IN (SELECT DISTINCT user_id FROM users_field_data JOIN cfp ON cfp.user_id)") : $query->addWhereExpression(0,"users_field_data.uid NOT IN (SELECT DISTINCT user_id FROM users_field_data JOIN cfp ON cfp.user_id)"); } } }
services: hederavita_core.event_subscriber: class: Drupal\hederavita_core\EventSubscriber\OderPlacedSubscriber arguments: ['@messenger', '@marketing_tools.google_event_storage', '@path.current'] tags: - { name: event_subscriber }
<?php namespace Drupal\hederavita_core\EventSubscriber; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\Path\CurrentPathStack; use Drupal\marketing_tools\GoogleEventStorage; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * Hederavita Core event subscriber. */ class OderPlacedSubscriber implements EventSubscriberInterface { /** * The messenger. * * @var \Drupal\Core\Messenger\MessengerInterface */ protected $messenger; /** * The marketing tool. * * @var \Drupal\marketing_tools\GoogleEventStorage */ protected $marketing_tool; /** * The current path. * * @var \Drupal\Core\Path\CurrentPathStack */ protected $current_path; /** * Constructs event subscriber. * * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger. * @param \Drupal\marketing_tools\GoogleEventStorage $marketing_tool * The marketing tool. * @param \Drupal\Core\Path\CurrentPathStack $current_path */ public function __construct(MessengerInterface $messenger, GoogleEventStorage $marketing_tool, CurrentPathStack $current_path) { $this->messenger = $messenger; $this->marketing_tool = $marketing_tool; $this->current_path = $current_path; } /** * Kernel request event handler. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * Response event. */ public function onKernelRequest(GetResponseEvent $event) { $this->messenger->addStatus(__FUNCTION__); } /** * Kernel response event handler. * * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event * Response event. */ public function onKernelResponse(FilterResponseEvent $event) { $this->messenger->addStatus(__FUNCTION__); } /** * {@inheritdoc} */ public static function getSubscribedEvents() { $events = [ 'commerce_order.place.pre_transition' => ['addEvent', 50], ]; return $events; } /** * Create google event * * @return void */ public function addEvent() { $path = $this->current_path->getPath(); $path_parts = explode('/', $path); foreach ($path_parts as $path_part) { if (is_numeric($path_part)) { $order = \Drupal::entityTypeManager() ->getStorage('commerce_order') ->load($path_part); } } /** @var \Drupal\commerce_order\Entity\Order $order */ $value = $order->getTotalPrice()->getNumber(); $order_id = $order->id(); $this->marketing_tool->addEvent([ 'event' => 'conversion', 'sendTo' => 'GTM-PZQ4TQZ', 'value' => $value, 'currency' => 'RSD', 'transaction_id' => $order_id, ]); } }
name: Baross core type: module description: Baross Core module package: Custom core: 8.x core_version_requirement: ^8 || ^9
<?php /** * Implements hook_install(). */ function baross_core_install() { if (!\Drupal::moduleHandler()->moduleExists('path_alias')) { \Drupal::database()->delete('key_value') ->condition('name', 'path_alias') ->execute(); } } /** * Implements hook_update_N(). */ function baross_core_update_8002(&$sandbox) { \Drupal::database()->schema()->dropTable('menu_link_content_revision'); }
<?php /** * @file * Contains belmil_product_rating.module. */ use Drupal\block\Entity\Block; use Drupal\commerce_product\Entity\ProductInterface; use Drupal\commerce_product\Entity\ProductType; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Markup; use Drupal\Core\Routing\RouteMatchInterface; use \Drupal\user\EntityOwnerInterface; /** * Implements hook_help(). */ function belmil_product_rating_help($route_name, RouteMatchInterface $route_match) { switch ($route_name) { // Main module help for the belmil_product_rating module. case 'help.page.belmil_product_rating': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; $output .= '<p>' . t('This module provides custom rating functionalities for products.') . '</p>'; return $output; default: } return ''; } /** * Implements hook_theme(). */ function belmil_product_rating_theme() { return [ 'belmil_product_rating' => [ 'render element' => 'children', ], 'belmil_product_rating_statistics_widget' => [ 'render element' => 'children', ] ]; } /** * Implements hook_ENTITY_TYPE_insert(). */ function belmil_product_rating_comment_insert(EntityInterface $entity) { $userRoles = \Drupal::currentUser()->getRoles(); if ($entity instanceof EntityOwnerInterface) { $ownerEmail = $entity->getOwner()->getEmail(); if (!in_array('administrator', $userRoles) && $ownerEmail != 'trustami@studiopresent.com') { $link = '/comment/' . $entity->id() . '/edit'; $body = t('There is new comment on your site') . '<br> <a target="_blank" href="' . $link . '">' . t('Show') . ' </a>'; // Send mail. /** @var \Drupal\Core\Mail\MailManagerInterface $mailManager */ $mailManager = \Drupal::service('plugin.manager.mail'); $module = $key = 'belmil_product_rating'; // Get email from config and remove whitespaces. $to = \Drupal::config('system.site')->get('mail'); $params['subject'] = t('New comment on website'); $params['body'] = $body; $params['format'] = 'text/html'; $langcode = \Drupal::currentUser()->getPreferredLangcode(); $result = $mailManager->mail($module, $key, $to, $langcode, $params, NULL, TRUE); // Log result. if ($result['result'] != TRUE) { $message = t('There was a problem sending your email notification to @email.', ['@email' => $to]); \Drupal::logger('mail')->error($message); } else { $message = t('An email notification for new comment has been sent to @email.', ['@email' => $to]); \Drupal::logger('mail')->notice($message); } } } } /** * Implements hook_mail(). */ function belmil_product_rating_mail($key, &$message, $params) { switch ($key) { case 'belmil_product_rating': $message['subject'] = $params['subject']; $message['body'][] = Markup::create($params['body']); $message['headers']['Content-Type'] = $params['format']; break; } } /** * Implements hook_form_alter(). */ function belmil_product_rating_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Open details for admin comment approval. if ($form_id == "comment_product_comment_form") { $form['#validate'][] = 'belmil_product_rating_settings_validate'; if (isset($form['author'])) { $form['author']['#open'] = TRUE; } } } /** * Implements hook_form_submit(). */ function belmil_product_rating_settings_validate(&$form, FormStateInterface $form_state) { $uid = \Drupal::currentUser()->id(); if (empty($form_state->getValue('uid'))) { $form['author']['uid']['#value'] = $uid; $form['author']['name']['#value'] = 'Anonymous'; } } /** * Implements hook_entity_extra_field_info(). */ function belmil_product_rating_entity_extra_field_info() { $stars_field = []; foreach (ProductType::loadMultiple() as $bundle) { $stars_field['commerce_product'][$bundle->id()]['display']['trustamiproductreview'] = [ 'label' => t('Trustami product review'), 'description' => t('A pseudo field to display the Trustami product review block'), 'weight' => 0, 'visible' => TRUE, ]; // Define stars field for displaying rating by stars and link to comment section. $stars_field['commerce_product'][$bundle->id()]['display']['stars_field'] = [ 'label' => t('Product stars'), 'description' => t('This is pseudo field for showing stars rating'), 'visible' => FALSE, ]; // Define statistic widget for rating. $stars_field['commerce_product'][$bundle->id()]['display']['stars_widget'] = [ 'label' => t('Stars widget'), 'description' => t('Stars widget with statistic by marks'), 'visible' => FALSE, ]; } return $stars_field; } /** * Implements hook_ENTITY_TYPE_view(). * * Add stars field & widget to product view. */ function belmil_product_rating_commerce_product_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { if ($display->getComponent('trustamiproductreview')) { $block = Block::load('trustamiproductreview'); if ($block) { $build['trustamiproductreview'] = $block->getPlugin()->build(); } } if ($display->getComponent('stars_field') || $display->getComponent('stars_widget') ) { /** @var \Drupal\belmil_product_rating\BelmilProductRatingManager $product_rating_manager */ $product_rating_manager = \Drupal::service('belmil_product_rating.belmil_product_rating_manager'); $productRating = 0; $numOfComments = 0; $productsWithSameTagWithComments = []; $ratings = []; // Get product with same tag which contain comments for default product type. if ($entity->bundle() === "default") { $tagId = (int) $entity->get('field_tag')->target_id; $productsWithSameTagWithComments = $product_rating_manager ->getProductsWithSameTagWithComments($tagId); } // Get comments of single product for universal product type. elseif ($entity->bundle() === "universal") { $productsWithSameTagWithComments = [$entity->id()]; } // Call get rating function. $product_rating_manager->getRating($productsWithSameTagWithComments, $productRating, $numOfComments, $ratings); // Prepare stars data - num of stars is fixed to 5. $starsData = $product_rating_manager->prepareStarsData(5, $productRating); } // Render product stars. if ($display->getComponent('stars_field')) { $build['stars_field'] = [ '#markup' => \Drupal::theme()->render('belmil_product_rating', [ 'rating' => $productRating, 'stars' => 5, 'vote_type' => "fivestar-widget-static-vote", 'num_of_comments' => $numOfComments, 'widget' => ['name' => 'fivestar-basic'], 'stars_data' => $starsData, 'product_id' => $entity->id(), ]), ]; } // Render stars statistics widget. if ($display->getComponent('stars_widget')) { // Render only if there is any comment. if (!empty($ratings)) { $totalRating = ($productRating / 20 ); $statistics = $product_rating_manager->getStatisticsRatingData($ratings); // Get percentage of each mark. foreach ($statistics as $key => $rating) { $statistics[$key] = $rating / count($ratings) * 100; } $build['stars_widget'] = [ '#markup' => \Drupal::theme()->render('belmil_product_rating_statistics_widget', [ 'ratings' => $statistics, 'total_rating' => $totalRating, 'rating' => $productRating, 'stars' => 5, 'vote_type' => "fivestar-widget-static-vote", 'num_of_comments' => $numOfComments, 'widget' => ['name' => 'fivestar-basic'], 'stars_data' => $starsData, 'product_id' => $entity->id(), ]), ]; } } } /** * Implements hook_page_attachments(). */ function belmil_product_rating_page_attachments(array &$page) { // Get request and entity. $request = \Drupal::request(); $path = $request->attributes->get('_route_object')->getPath(); /** @var \Drupal\commerce_product\Entity\ProductInterface $entity */ $entity = $request->attributes->get('_entity'); // Check if we are on product view page. if (!empty($entity) && $path == "/product/{commerce_product}") { // Attach google schema style script. /** @var \Drupal\belmil_product_rating\BelmilProductRatingManager $product_rating_manager */ $product_rating_manager = \Drupal::service('belmil_product_rating.belmil_product_rating_manager'); $product_rating_manager->attachGoogleSchemaStyleScript($entity, $page); // Attach Trustami Comment Widget. $referrerMeta = [ '#tag' => 'meta', '#attributes' => [ 'name' => 'referrer', 'content' => 'strict-origin-when-cross-origin', ], ]; $page['#attached']['html_head'][] = [$referrerMeta, 'referrerMeta']; // attachTrustamiCommentsWidgetScript($entity, $page); } } /** * Trustami product widget script. * * @param \Drupal\commerce_product\Entity\ProductInterface $entity * The product entity. * @param array $page * The page array. */ function attachTrustamiCommentsWidgetScript(ProductInterface $entity, array &$page) { $variations = $entity->getVariations(); $variation = reset($variations); if ($variation) { $trustamiProductWidgetScript = [ '#tag' => 'script', '#attributes' => [ 'type' => 'text/javascript', 'id' => 'trustami-product-widget', 'src' => 'https://cdn.trustami.com/widgetapi/productWidget/trustami-product-widget.js', 'data-uid' => '601e2fffcc96c5152b8b46de', 'data-gtin' => $variation->getSku(), 'data-asin' => $variation->get('field_asin')->value, 'data-modes' => "[4]", ], '#value' => '', ]; // Add script to head. $page['#attached']['html_head'][] = [ $trustamiProductWidgetScript, 'trustamiProductWidgetScript' ]; } }
<?php declare(strict_types = 1); namespace Drupal\enmon_core\Plugin\search_api\processor; use Drupal\search_api\Datasource\DatasourceInterface; use Drupal\search_api\IndexInterface; use Drupal\search_api\Item\ItemInterface; use Drupal\search_api\Processor\ProcessorPluginBase; use Drupal\search_api\Processor\ProcessorProperty; /** * @SearchApiProcessor( * id = "only_special_offer", * label = @Translation("Only special offer"), * description = @Translation("Calculates whether the only special offer is true on all variation"), * stages = { * "add_properties" = 0, * }, * ) */ class OnlySpecialOffer extends ProcessorPluginBase { /** * {@inheritdoc} */ public static function supportsIndex(IndexInterface $index) { $supported_entity_types = ['commerce_product']; foreach ($index->getDatasources() as $datasource) { if (in_array($datasource->getEntityTypeId(), $supported_entity_types)) { return TRUE; } } return FALSE; } /** * {@inheritdoc} */ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { $properties = []; if (!$datasource) { $definition = [ 'label' => $this->t('Only special offers'), 'description' => $this->t('Whether the product all variation marked with only special offer'), 'type' => 'boolean', 'is_list' => TRUE, 'processor_id' => $this->getPluginId(), ]; $properties['only_special_offers'] = new ProcessorProperty($definition); } return $properties; } /** * {@inheritdoc} */ public function addFieldValues(ItemInterface $item) { $fields = $item->getFields(); $only_special_offer_fields = $this->getFieldsHelper() ->filterForPropertyPath($fields, NULL, 'only_special_offers'); /** @var \Drupal\Core\Entity\Plugin\DataType\EntityAdapter $entity_adapter */ $entity_adapter = $item->getOriginalObject(); /** @var \Drupal\commerce_product\Entity\Product $product */ $product = $entity_adapter->getEntity(); /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ foreach ($product->getVariations() as $product_variation) { $is_only_special_offer = $product_variation->get('field_only_special_offer')->value; foreach ($only_special_offer_fields as $only_special_offer_field) { $only_special_offer_field->addValue($is_only_special_offer); } } } }
/** * Implements hook_views_pre_view(). */ function enmon_core_views_pre_view(ViewExecutable $view, $display_id, array &$args) { if ($view->id() === 'special_offers') { $format_values = \Drupal::entityTypeManager() ->getStorage('commerce_product_attribute_value') ->getQuery() ->condition('attribute', 'master_format') ->execute(); $color_values = \Drupal::entityTypeManager() ->getStorage('commerce_product_attribute_value') ->getQuery() ->condition('attribute', 'master_color') ->execute(); $filters = $view->display_handler->getOption('filters'); if (array_key_exists('attribute_master_format_target_id_1', $filters)) { foreach ($format_values as $format_key => $format_value) { $filters['attribute_master_format_target_id_1']['value'][$format_key] = $format_value; } } if (array_key_exists('attribute_master_color_target_id_1', $filters)) { foreach ($color_values as $color_key => $color_value) { $filters['attribute_master_color_target_id_1']['value'][$color_key] = $color_value; } } $view->display_handler->overrideOption('filters', $filters); } }
TRUNCATE cache_config; TRUNCATE cache_container; TRUNCATE cache_data; TRUNCATE cache_default; TRUNCATE cache_discovery; TRUNCATE cache_dynamic_page_cache; TRUNCATE cache_entity; TRUNCATE cache_menu; TRUNCATE cache_render; TRUNCATE cache_toolbar;
(function (Drupal) { const handleExpand = (element) => { const expandElement = element.target.parentElement.querySelector('.to-expand'); if (expandElement.style.display === "inline") { expandElement.style.display = "none"; element.target.innerHTML = Drupal.t('Read more'); } else { expandElement.style.display = "inline"; element.target.innerHTML = Drupal.t('Collapse'); } }; document.querySelectorAll('.expand-link').forEach((element) => { element.addEventListener('click', handleExpand); }); }) (Drupal);
read_more: version: 1.x js: js/read_more.js: {} dependencies: - core/drupal
<?php namespace Drupal\halo_widget_altering\Element; use Drupal\Core\Render\Element\RenderElement; /** * Provides a render element to display read more text. * * Properties: * - #text: Text to be printed. * - #limit_chars: Number of characters to limit. * * Usage Example: * @code * $build['read_more'] = [ * '#type' => 'correction_value_viewer', * '#entity' => EntityInterface, * ]; * @endcode * @RenderElement("read_more") */ class ReadMore extends RenderElement { /** * {@inheritDoc} */ public function getInfo() { return [ '#pre_render' => [ [get_class($this), 'printText'], ], '#text' => NULL, '#limit_chars' => 250, ]; } /** * @return */ public static function printText(array $element) { $text = $element['#text']; $limit_characters = $element['#limit_chars']; if (empty($text)) { return []; } if (strlen($text) <= $limit_characters) { return [ 'text' => [ '#type' => 'inline_template', '#template' => '{{ value|nl2br }}', '#context' => ['value' => $text], ], ]; } $first_half_text = substr($text, 0, $limit_characters); $second_half_text = substr($text, $limit_characters); $element['text'] = [ 'text' => [ '#type' => 'inline_template', '#template' => '{{ value1|nl2br }}<span class="to-expand" style="display: none">{{ value2|nl2br }}</span><a class="expand-link">{{ read_more_text }}</a>', '#context' => [ 'value1' => $first_half_text, 'value2' => $second_half_text, 'read_more_text' => t('Read more'), ], ], ]; $element['#attached']['library'][] = 'halo_widget_altering/read_more'; return $element; } }
$entity_row[] = [ '#type' => 'read_more', '#text' => $entity->get('description')->value, // '#limit_chars' => 10, ]; }
<?php /** * Implements hook_token_info(). */ function mycustomtokenmodule_token_info() { $type = [ 'name' => t('Custom Token'), 'description' => t('Tokens for custom things.'), ]; $node['title'] = [ 'name' => t("Node Title"), 'description' => t('The node\'s title'), ]; $node['dateformat'] = [ 'name' => t("Custom Date Format"), 'dynamic' => TRUE, 'description' => t('Show a custom format for the current date'), ]; return [ 'types' => ['customtoken' => $type], 'tokens' => ['customtoken' => $node], ]; } /** * Implements hook_tokens(). */ function mycustomtokenmodule_tokens($type, $tokens, array $data, array $options, \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata) { $replacements = []; if ($type == 'customtoken' && !empty($data['node'])) { foreach ($tokens as $name => $original) { switch ($name) { case 'title': $replacements[$original] = $data['node']->getTitle(); break; } } if ($dateTokens = \Drupal::token()->findWithPrefix($tokens, 'dateformat')) { // var_dump($dateTokens) // retult: array(1) { ["Y-m-d"]=> string(30) "[customtoken:dateformat:Y-m-d]" } foreach ($dateTokens as $format => $original) { $replacements[$original] = date($format); } } } return $replacements; }
function change_maintenance_date() { //Change the date so the Report date is 2024. 07. 15. $cfp = \Drupal::entityTypeManager()->getStorage('cfp')->load(190); $cfp->set('maintenance_period', '2021-07-15')->save(); // Ovaj datum je }
SELECT entity_id, COUNT(variations_target_id) FROM `commerce_product__variations` GROUP BY entity_id HAVING COUNT(variations_target_id) > 1;
<?php /** @var \Drupal\halo_entity_cfp\Entity\Cfp[] $cfps */ $cfps = \Drupal::entityTypeManager()->getStorage('cfp')->loadByProperties([ 'type' => 'cfp_2020_01', 'state' => 'project_implementation', ]); $first_key = key($cfps); $writer = Box\Spout\Writer\Common\Creator\WriterEntityFactory::createXLSXWriter(); $file_system = \Drupal::service('file_system'); $temp_path = 'public://ced_NOVI_report.xlsx'; $temp_path = $file_system->realpath($temp_path); $writer->openToFile($temp_path); foreach ($cfps as $key => $cfp) { $applicant = $cfp->getApplicantEntity(); $row = []; $row['operational_number'] = $cfp->label(); $row['company_name'] = $applicant->label(); // Partner countries. for ($i = 0;$i < 3;$i++) { $index = $i + 1; $partner = $cfp->get('partners')[$i] ?? FALSE; if ($partner) { $partner_entity = $partner->entity; $project_implementation_place = $partner_entity->get('project_implementation_place'); if ($project_implementation_place->first()) { $implementation_country = $project_implementation_place->first()->getCountryName(); } $row["partner_$index"] = $partner_entity->get('short_name')->value; $row["partner_country_$index"] = $implementation_country ?? ''; } else { $row["partner_$index"] = ''; $row["partner_country_$index"] = ''; } } $contact_person_items = $applicant->get('contact_person'); for ($i = 0;$i < 3;$i++) { $index = $i + 1; /** @var \Drupal\halo_entity_person\Entity\PersonEntity $ontact_person */ $contact_person = $contact_person_items->get($i)->entity ?? FALSE; if ($contact_person) { $row["contact_person_last_name_$index"] = $contact_person->getLastName(); $row["contact_person_first_name_$index"] = $contact_person->getFirstName(); $row["contact_person_phone_1_$index"] = $contact_person->getPhone1(); $row["contact_person_phone_2_$index"] = $contact_person->getPhone2(); $row["contact_person_email_$index"] = $contact_person->getEmail(); } else { $row["contact_person_last_name_$index"] = ''; $row["contact_person_first_name_$index"] = ''; $row["contact_person_phone_1_$index"] = ''; $row["contact_person_phone_2_$index"] = ''; $row["contact_person_email_$index"] = ''; } } if ($first_key === $key) { $writer->addRow(\Box\Spout\Writer\Common\Creator\WriterEntityFactory::createRowFromArray(array_keys($row))); } $writer->addRow(\Box\Spout\Writer\Common\Creator\WriterEntityFactory::createRowFromArray($row)); } $writer->close();
function ced_giga_report() { /** @var \Drupal\halo_entity_cfp\Entity\Cfp[] $cfps */ $cfps = \Drupal::entityTypeManager()->getStorage('cfp')->loadByProperties([ 'state' => ['under_contracting', 'reject', 'project_implementation'], ]); $first_key = key($cfps); $writer = Box\Spout\Writer\Common\Creator\WriterEntityFactory::createXLSXWriter(); $file_system = \Drupal::service('file_system'); $temp_path = 'public://ced_giga_report.xlsx'; $temp_path = $file_system->realpath($temp_path); $writer->openToFile($temp_path); foreach ($cfps as $key => $cfp) { $applicant = $cfp->getApplicantEntity(); $row = []; $row['operational_number'] = $cfp->label(); $row['company_name'] = $applicant->label(); $row['vat_number'] = $applicant->get('vat_number')->value; $row['company_registration_number'] = $applicant->get('company_registration_number')->value; $date = $applicant->get('company_establishment_date')->date; $row['company_establishment_date'] = $date ? $date->format('Y.m.d') : ''; $row['entitled_to_vat_refund'] = ((bool) $applicant->get('entitled_to_vat_refund')->value) ? 'Igen' : 'Nem'; $row['main_company_address'] = $applicant->get('main_company_address') ->isEmpty() ? '' : address_basic_view($applicant->get('main_company_address') ->first()); // Bank account. $bank_account_item = $applicant->get('bank_account_details'); for ($i = 0; $i < 2; $i++) { /** @var \Drupal\halo_entity_bank_account\Entity\BankAccountEntity $bank_account */ $bank_account = $bank_account_item->get($i)->entity ?? FALSE; $index = $i + 1; if ($bank_account) { $row["bank_account_name_$index"] = $bank_account->getName(); $row["bank_address_address_$index"] = $bank_account->getAddress(); $row["bank_account_number_$index"] = $bank_account->getAccountNumber(); } else { $row["bank_account_name_$index"] = ''; $row["bank_address_address_$index"] = ''; $row["bank_account_number_$index"] = ''; } } $company_representative_item = $applicant->get('company_representative'); for ($i = 0;$i < 4;$i++) { $index = $i + 1; /** @var \Drupal\halo_entity_person\Entity\PersonEntity $company_representative */ $company_representative = $company_representative_item->get($i)->entity ?? FALSE; if ($company_representative) { $row["company_representative_last_name_$index"] = $company_representative->getLastName(); $row["company_representative_first_name_$index"] = $company_representative->getFirstName(); $row["company_representative_assignment_$index"] = $company_representative->getAssignment(); $row["company_representative_representation_type_$index"] = $company_representative->getRepresentationTypeLabel(); $row["company_representative_phone_1_$index"] = $company_representative->getPhone1(); $row["company_representative_email_$index"] = $company_representative->getEmail(); } else { $row["company_representative_last_name_$index"] = ''; $row["company_representative_first_name_$index"] = ''; $row["company_representative_assignment_$index"] = ''; $row["company_representative_representation_type_$index"] = ''; $row["company_representative_phone_1_$index"] = ''; $row["company_representative_email_$index"] = ''; } } $contact_person_items = $applicant->get('contact_person'); for ($i = 0;$i < 3;$i++) { $index = $i + 1; /** @var \Drupal\halo_entity_person\Entity\PersonEntity $ontact_person */ $contact_person = $contact_person_items->get($i)->entity ?? FALSE; if ($contact_person) { $row["contact_person_last_name_$index"] = $contact_person->getLastName(); $row["contact_person_first_name_$index"] = $contact_person->getFirstName(); $row["contact_person_assignment_$index"] = $contact_person->getAssignment(); $row["contact_person_phone_1_$index"] = $contact_person->getPhone1(); $row["contact_person_email_$index"] = $contact_person->getEmail(); } else { $row["contact_person_last_name_$index"] = ''; $row["contact_person_first_name_$index"] = ''; $row["contact_person_assignment_$index"] = ''; $row["contact_person_phone_1_$index"] = ''; $row["contact_person_email_$index"] = ''; } } if ($first_key === $key) { $writer->addRow(\Box\Spout\Writer\Common\Creator\WriterEntityFactory::createRowFromArray(array_keys($row))); } $writer->addRow(\Box\Spout\Writer\Common\Creator\WriterEntityFactory::createRowFromArray($row)); } $writer->close(); }
{# /** * @file * Template for the commerce email. * * Available variables: * - order_entity: The order entity. * - body: The email body. * - totals: An array of order totals values with the following keys: * - subtotal: The order subtotal price. * - adjustments: An array of adjustment totals: * - type: The adjustment type. * - label: The adjustment label. * - total: The adjustment total price. * - weight: The adjustment weight, taken from the adjustment type. * * @ingroup themeable */ #} <table style="margin: 15px auto 0 auto; max-width: 768px; font-family: arial,sans-serif"> <tbody> <tr> <td> <table style="text-align: center; min-width: 450px; margin: 5px auto 0 auto; border: 1px solid #cccccc; border-radius: 5px; padding: 40px 30px 30px 30px;"> <tbody> <tr> <td style="font-size: 30px; padding-bottom: 30px"><img src="/themes/custom/zadi_theme/belmil_wave_logo_email.png" style="height: 60px;" /></td> </tr> <tr> <td> {{ body|raw }} </td> <tr> <td style="font-weight: bold; padding-top:15px; padding-bottom: 15px; text-align: left; border-top: 1px solid #cccccc; border-bottom: 1px solid #cccccc"> {{ 'Order #@number details:'|t({'@number': order_entity.getOrderNumber}) }} </td> </tr> <tr> <td> <table style="padding-top: 15px; padding-bottom:15px; width: 100%"> <tbody style="text-align: left;"> {% for order_item in order_entity.getItems %} <tr> <td> {{ order_item.getQuantity|number_format }} x </td> <td> <span>{{ order_item.label }}</span> <span style="float: right;">{{ order_item.getTotalPrice|commerce_price_format }}</span> </td> </tr> {% endfor %} </tbody> </table> </td> </tr> <tr> <td> <p style="margin-bottom: 0;"> {{ 'Subtotal: @subtotal'|t({'@subtotal': totals.subtotal|commerce_price_format}) }} </p> </td> </tr> {% for adjustment in totals.adjustments %} <tr> <td> <p style="margin-bottom: 0;"> {{ adjustment.label }}: {{ adjustment.total|commerce_price_format }} </p> </td> </tr> {% endfor %} <tr> <td> <p style="font-size: 24px; padding-top: 15px; padding-bottom: 5px;"> {{ 'Order Total: @total'|t({'@total': order_entity.getTotalPrice|commerce_price_format}) }} </p> </td> </tr> {% if store_info %} <tr> <td> {% block additional_information %} {{ store_info|raw }} {% endblock %} </td> </tr> {% endif %} </tr> </tbody> </table> </td> </tr> </tbody> </table>
<?php /** * @file * Provides a bb2b_order. */ use Drupal\block\Entity\Block; use Drupal\commerce_order\Entity\Order; use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\AppendCommand; use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\RedirectCommand; use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\bb2b_order\Plugin\Commerce\CheckoutPane\OrderTypePane; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Drupal\views\Form\ViewsForm; use Drupal\views\ViewExecutable; use Drupal\Core\Entity\EntityInterface; /** * Implements hook_cron(). */ function bb2b_order_cron() { $request_time = \Drupal::time()->getRequestTime(); $state_key = 'bb2b_order.last_queue_time'; $last_queue_time = \Drupal::state()->get($state_key, 0); // Once daily. if ($request_time - $last_queue_time >= (24 * 60 * 60)) { \Drupal::service('bb2b_order.order_reservation_cron')->run(); \Drupal::state()->set($state_key, $request_time); } } /** * Implements hook_form_alter(). */ function bb2b_order_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Add to cart on product page. This page will be deactivated. if (strpos($form_id, 'commerce_order_item_add_to_cart_form') !== FALSE) { array_unshift($form['#validate'], 'validate_available_quantity'); } // Cart page. if (strpos($form_id, 'views_form_commerce_cart_form_') !== FALSE) { array_unshift($form['#validate'], 'validate_min_quantity'); } // Quick order page. if ($form_state->getFormObject() instanceof ViewsForm) { /** @var \Drupal\views\ViewExecutable $view */ $view = reset($form_state->getBuildInfo()['args']); if ($view->storage->get('id') == 'quick_order' && !empty($view->result)) { $order_id = \Drupal::service('commerce_cart.cart_provider')->getCartIds(\Drupal::currentUser()); $order_id = reset($order_id); $order = \Drupal::entityTypeManager()->getStorage('commerce_order') ->load($order_id); $form['ddp_package_list'] = [ '#type' => 'details', '#title' => t('At DDP orders, every box must be filled with the MOQ / box quantity.'), '#weight' => -2, '#open' => FALSE, ]; $form['ddp_package_list']['block'] = [ '#type' => 'container', 'block' => [ '#markup' => bb2b_order_render_shipment_package_block(), ], ]; $name = 'field_order_type'; /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */ $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display') ->load('commerce_order.default.default'); $widget = $form_display->getRenderer($name); $roles = \Drupal::currentUser()->getRoles(); $is_admin = in_array('administrator', $roles) || in_array('site_administrator', $roles); if ($widget) { $items = $order->get($name); $items->filterEmptyItems(); $store = \Drupal::service('commerce_store.current_store')->getStore(); $cart_provider = \Drupal::service('commerce_cart.cart_provider'); $cart = $cart_provider->getCart('default', $store); if (!$cart) { $cart = $cart_provider->createCart('default', $store); } $order_type = $cart->get('field_order_type')->value; $form[$name] = $widget->form($items, $form, $form_state); $form[$name]['#access'] = $items->access('edit'); $form[$name]['#required'] = TRUE; $form[$name]['#weight'] = -1; $form[$name]['widget']['#default_value'] = $order_type ?? 'ddp'; $form[$name]['widget']['#ajax'] = [ 'callback' => 'bb2b_order_update_min_values', ]; if ($is_admin) { unset($form[$name]['widget']['#options']['ddp_reservation']); } else { $form[$name]['widget']['ddp_reservation'] = [ '#description' => t('You have 5 days to pay the order, otherwise it will be canceled.'), ]; } } $options = []; $companies = \Drupal::entityTypeManager() ->getStorage('company') ->loadMultiple(); foreach ($companies as $company) { if ($employee = $company->getEmployeeByRole('company_manager')) { $options[$employee->id()] = $employee->getDisplayName() . ' (' . $company->getName() . ')'; } } $form['client'] = [ '#type' => 'select2', '#id' => 'update-client', '#options' => $options, '#title' => t('Client'), '#required' => FALSE, '#weight' => -2, '#access' => $is_admin, '#ajax' => [ 'callback' => 'bb2b_order_update_client', ], ]; if ($client_id = $order->getData('client_id')) { $form['client']['#default_value'] = $client_id; } $form['actions']['checkout'] = [ '#type' => 'submit', '#value' => t('Delivery data'), '#weight' => 5, '#access' => \Drupal::currentUser()->hasPermission('access checkout'), '#submit' => array_merge($form['#submit'], ['bb2b_order_checkout_views_form_submit']), '#order_id' => $order_id, ]; } } if ($form_id == 'commerce_shipping_method_edit_form') { $form['plugin']['widget'][0]['target_plugin_configuration']['form']['rate_label']['#attributes'] = ['readonly' => 'readonly']; $form['plugin']['widget'][0]['target_plugin_configuration']['form']['rate_label']['#description'] = t('Shown to customers during checkout. This value cannot be changed because we need it to match the name in Linker.'); } } /** * Implements hook_views_pre_render(). */ function bb2b_order_views_pre_render(ViewExecutable $view) { if ($view->id() == 'commerce_cart_form') { $order_id = $view->args[0]; /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = Order::load($order_id); /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); if (!$order_service->packageMinQuantityIsValid($order)) { $view->build_info['substitutions']['{{ admin_shipment_packages_block }}'] = bb2b_order_render_shipment_package_block(); } } if ($view->id() === 'quick_order') { //@todo: This will go to history when we create stock base field on product. //@todo: Query will be in the StockStatus filter. $input = $view->getExposedInput(); if (isset($input['stock_status']) && $input['stock_status'] === 'only_available') { // Get products from the view. $products = []; foreach ($view->result as $key => $product) { $products[$key] = $product->_entity; } // Check if those products are available. $order_service = \Drupal::service('bb2b_order.order_service'); foreach ($products as $key => $product) { if (!$order_service->checkAccessForProduct($product)) unset($view->result[$key]); } } } } /** * Gets the cart order for the given store and user. * * @param \Drupal\Core\Session\AccountInterface $account * The user. If empty, the current user is assumed. * * @return \Drupal\commerce_order\Entity\OrderInterface|null * The cart order, or NULL if none found. */ function bb2b_order_get_cart(AccountInterface $account = NULL) { $store = \Drupal::service('commerce_store.current_store')->getStore(); $cart_provider = \Drupal::service('commerce_cart.cart_provider'); $cart = $cart_provider->getCart('default', $store, $account); if (!$cart) { $cart = $cart_provider->createCart('default', $store, $account); } return $cart; } /** * Ajax handler used to remove min values validation for drop shipping. */ function bb2b_order_update_client($form, FormStateInterface $form_state) { $response = new AjaxResponse(); $triggering_element = $form_state->getTriggeringElement(); $trigger_name = array_shift($triggering_element['#parents']); if ($trigger_name === 'client') { $client_id = $triggering_element['#value']; $cart = bb2b_order_get_cart(); $user = \Drupal::entityTypeManager() ->getStorage('user') ->load($client_id); $email = $user ? $user->getEmail() : NULL; $cart->setData('client_id', $client_id); $cart->setData('client_email', $email); $cart->save(); $content = '<div class="ajax-progress-throbber"></div>'; $response->addCommand(new AppendCommand('body', $content)); $response->addCommand(new RedirectCommand(Url::fromUri('internal:/orders/quick-order')->toString())); } return $response; } /** * Ajax handler used to remove min values validation for drop shipping. */ function bb2b_order_update_min_values($form, FormStateInterface $form_state) { $response = new AjaxResponse(); $triggering_element = $form_state->getTriggeringElement(); $trigger_name = array_shift($triggering_element['#parents']); if ($trigger_name === 'field_order_type') { $order_type = $triggering_element['#value']; $rows = $form['output'][0]['#rows']; /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); $cart = bb2b_order_get_cart(); /*if ($order_type !== 'drop_shipping') { $cart->setData('client_id', NULL); $cart->setData('client_email', NULL); }*/ $cart->set('field_order_type', $order_type); $cart->save(); foreach ($rows as $key => $row) { $field_stock = $form['warehouse_stock'][$key]; $field_quantity = $form['edit_quantity'][$key]; $field_chk = $form['chk_add_to_cart'][$key]; $field_price = $form['price_group_price'][$key]; $add_to_cart_button = $form['add_to_cart_button'][$key]; /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $row->_entity; $access = $order_service->checkAccessForProduct($product); $available = $order_service->getAvailableStock($product); if ($order_type === 'drop_shipping') { $class = $field_quantity['#attributes']['class'] ?? []; $key = array_search('visually-hidden', $class); if ($key !== FALSE && $available > 0) { unset($field_quantity['#attributes']['class'][$key]); } $class = $field_chk['#attributes']['class'] ?? []; $key = array_search('visually-hidden', $class); if ($key !== FALSE && $available > 0) { unset($field_chk['#attributes']['class'][$key]); } $class = $add_to_cart_button['#attributes']['class'] ?? []; $key = array_search('visually-hidden', $class); if ($key !== FALSE && $available > 0) { unset($add_to_cart_button['#attributes']['class'][$key]); } } else { if (!$access || $available == 0) { if (!isset($field_quantity['#attributes']['class']['visually-hidden'])) { $field_quantity['#attributes']['class'][] = 'visually-hidden'; } if (!isset($field_chk['#attributes']['class']['visually-hidden'])) { $field_chk['#attributes']['class'][] = 'visually-hidden'; } $field_chk['#value'] = 0; if (!isset($add_to_cart_button['#attributes']['class']['visually-hidden'])) { $add_to_cart_button['#attributes']['class'][] = 'visually-hidden'; } } } $method = $order_type === 'drop_shipping' ? 'addClass' : 'removeClass'; $response->addCommand(new InvokeCommand('.min-qty', $method, ['visually-hidden'])); $selector = $field_quantity['#attributes']['data-drupal-selector']; $quantity_selector = 'div[class*="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]'; $response->addCommand(new ReplaceCommand($quantity_selector, $field_quantity)); $selector = $field_chk['#attributes']['data-drupal-selector']; $chk_selector = 'div[class*="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]'; $response->addCommand(new ReplaceCommand($chk_selector, $field_chk)); $selector = $field_stock['#attributes']['data-drupal-selector']; $stock_selector = 'div[id="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]'; $response->addCommand(new ReplaceCommand($stock_selector, $field_stock)); $company = $order_service->getCompanyForClient($cart); $price = $order_service->getProductPriceForClient($product->getDefaultVariation(), $cart, $company); $field_price['list_price']['#value'] = $price['list_price']; $field_price['price']['#value'] = $price['price']; $selector = $field_price['#attributes']['data-drupal-selector']; $price_selector = 'div[id="' . preg_replace('/edit/', 'form-item', $selector, 1) . '"]'; $response->addCommand(new ReplaceCommand($price_selector, $field_price)); $button_selector = 'button[name="' . $add_to_cart_button['#name'] . '"]'; $response->addCommand(new ReplaceCommand($button_selector, $add_to_cart_button)); // Cart block. /** @var \Drupal\Core\Block\BlockPluginInterface $cart_block */ $cart_block = \Drupal::service('plugin.manager.block')->createInstance('commerce_cart', []); if ($cart_block) { $response->addCommand(new ReplaceCommand('.cart--cart-block', $cart_block->build())); } } } return $response; } /** * Submit handler used to redirect to the checkout page. */ function bb2b_order_checkout_views_form_submit($form, FormStateInterface $form_state) { $order_id = $form_state->getTriggeringElement()['#order_id']; $form_state->setRedirect('commerce_checkout.form', ['commerce_order' => $order_id]); } /** * Form validation handler for commerce_order_item_add_to_cart_form*(). * * @param array $form * A build form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. */ function validate_available_quantity(array $form, FormStateInterface $form_state) { $product = $form_state->get('product'); $quantity = (int) $form_state->getValue('quantity')[0]['value']; /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); $available = $order_service->getAvailableStock($product); if ($available < $quantity) { $form_state->setErrorByName('quantity][0][value', t('There are not enough quantity on the stock. Available: @available', [ '@available' => $available, ])); } } /** * Form validation handler for views_form_commerce_cart_form_*(). * * @param array $form * A build form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. */ function validate_min_quantity(array $form, FormStateInterface $form_state) { $quantity = $form_state->getValue('edit_quantity'); $rows = $form['output'][0]['#rows']; $triggering_element = $form_state->getTriggeringElement(); $trigger_name = array_shift($triggering_element['#parents']); if ($trigger_name !== 'remove_button') { foreach ($rows as $key => $row) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $product_variation */ $product_variation = $row->_relationship_entities['commerce_product_variation']; /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $product_variation->getProduct(); /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = $row->_entity; /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); $available = $order_service->getAvailableStock($product); foreach ($order->getItems() as $order_item) { if ($order_item->getPurchasedEntityId() == $product_variation->id()) { $order_quantity = (int) $order_item->getQuantity(); $diff_quantity = $quantity[$key] - $order_quantity; if ($available < $diff_quantity || ($diff_quantity == 0 && $available < $order_quantity)) { $form_state->setErrorByName('edit_quantity][' . $key, t('There are not enough quantity on the stock for product: @product_title. Available: @available', [ '@product_title' => $product->getTitle(), '@available' => $diff_quantity == 0 ? $available : $available + $order_quantity, ])); } } } } } } /** * Implements hook_commerce_inline_form_PLUGIN_ID_alter(). */ function bb2b_order_commerce_inline_form_customer_profile_alter(array &$inline_form, FormStateInterface $form_state, array &$complete_form) { if ($inline_form['#profile_scope'] === 'checkout' && !isset($inline_form['rendered'])) { $inline_form['address']['widget'][0]['address']['#after_build'] = [ 'change_country_code_ajax_callback', ['\Drupal\address\Element\Address', 'clearValues'], ]; } } /** * Form API callback: Change ajax callback on country select. * * @param array $element * The element array. * @param \Drupal\Core\Form\FormStateInterface $form_state * Form state object. * * @return array * The element array. */ function change_country_code_ajax_callback(array $element, FormStateInterface &$form_state) { $element['country_code']['country_code']['#ajax']['callback'] = [ OrderTypePane::class, 'ajaxRefresh', ]; if ($form_state->getTriggeringElement()) { if ($form_state->getTriggeringElement()['#name'] === $element['country_code']['country_code']['#name']) { $form_state->setTriggeringElement($element['country_code']['country_code']); } } return $element; } /** * Implements hook_mail_alter(). */ function bb2b_order_mail_alter(&$message) { if ($message['key'] == 'order_receipt' && !empty($message['params']['order'])) { /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = $message['params']['order']; $message['from'] = 'noreply@bescool.net'; $subject_order_number = $order->getOrderNumber(); if ($order->get('field_your_order_id')->isEmpty() === FALSE) { $client_order_number = $order->get('field_your_order_id')->value; $subject_order_number .= ' (' . $client_order_number . ')'; } $message['subject'] = t('Order confirmation ID: @number', [ '@number' => $subject_order_number, ]); } } /** * Implements hook_form_FORM_ID_alter(). */ function bb2b_order_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) { $view = $form_state->get('view'); if ($view && in_array($view->id(), ['ongoing_orders', 'orders'])) { $form['search']['#placeholder'] = t('By email, order IDs, recipient name'); } } /** * Implements hook_views_data_alter(). */ function bb2b_order_views_data_alter(array &$data) { $data['commerce_order']['own_company_orders'] = [ 'title' => t('Own company orders'), 'help' => t('Filter orders by own company for company managers.'), 'filter' => [ 'group' => 'Order', 'field' => 'uid', 'id' => 'own_company_orders_filter', 'entity_type' => 'commerce_order', ], ]; } /** * Implements hook_views_data(). */ function bb2b_order_views_data() { $data = []; //@todo: Maybe we could put ["products"] instead of ["views"]. $data['views']['stock_status'] = [ 'title' => t('Stock status - Custom Filter'), 'filter' => [ 'title' => t('Stock status - Custom Filter'), 'field' => 'id', 'id' => 'stock_status', ] ]; return $data; } /** * Implements hook_ENTITY_TYPE_presave(). */ function bb2b_order_commerce_order_presave(EntityInterface $entity) { if ($entity->get('field_created_invoice')->isEmpty()) { $entity->set('field_created_invoice', 'no'); } // In case the your_order_id is edited after the order has been created, // and before the order is being shipped. if (!empty($entity->get('placed')->value)) { $order_service = \Drupal::service('bb2b_order.order_service'); $order_service->resolveShipping($entity); } } /** * Implements hook_entity_access(). */ function bb2b_order_entity_access(EntityInterface $entity, $operation, AccountInterface $account) { $allowed_entities = [ 'commerce_order', 'commerce_order_item', 'commerce_shipment', ]; if (in_array($entity->getEntityTypeId(), $allowed_entities)) { if ($account->hasPermission('update default commerce_order')) { return AccessResult::allowed(); } } return AccessResult::neutral(); } /** * Implements hook_form_BASE_FORM_ID_alter(). */ function bb2b_order_form_commerce_shipment_default_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { if (!\Drupal::currentUser()->hasPermission('access commerce administration pages')) { $form['title']['#access'] = FALSE; $form['shipping_method']['#access'] = FALSE; $form['tracking_code']['#access'] = FALSE; $form['shipment_items']['#access'] = FALSE; $form['recalculate_shipping']['#access'] = FALSE; $form['actions']['delete']['#access'] = FALSE; $request = \Drupal::requestStack()->getCurrentRequest(); $shipment = $request->get('commerce_shipment'); $form_state->set('shipment', $shipment); $shipment->setData('shipping_force_resolve', TRUE); if (isset($form['shipping_profile']['widget'][0]['profile']['edit_button'])) { $form['shipping_profile']['widget'][0]['profile']['edit_button']['#attributes']['class'][] = 'button-secondary'; } // Redirect user to order view. $form['actions']['submit']['#submit'][] = 'bb2b_order_shipment_edit_form_submit'; } } /** * Custom submit handler for the shipment edit form. */ function bb2b_order_shipment_edit_form_submit($form, FormStateInterface $form_state) { $shipment = $form_state->get('shipment'); $account = \Drupal::currentUser(); if ($shipment) { $admin_permission = $account ->hasPermission($shipment->getEntityType()->getAdminPermission()); $order = $shipment->getOrder(); if ($order && !$admin_permission) { /*$form_state->setRedirect('entity.commerce_order.user_view', [ 'commerce_order' => $order->id(), 'user' => $order->getCustomerId(), ]);*/ $form_state->setRedirect('entity.commerce_order.edit_form', [ 'commerce_order' => $order->id(), ]); } } } /** * Implements hook_form_BASE_FORM_ID_alter(). */ function bb2b_order_form_commerce_order_default_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) { $user = \Drupal::currentUser(); if (!$user->hasPermission('access commerce administration pages')) { $form['field_credit_note']['#access'] = FALSE; $form['field_internal_note']['#access'] = FALSE; $form['field_order_notes']['#access'] = FALSE; $form['field_order_type']['#access'] = FALSE; $form['field_vat_verified']['#access'] = FALSE; $form['field_tracking_code_date']['#access'] = FALSE; $form['coupons']['#access'] = FALSE; $form['billing_profile']['widget'][0]['profile']['select_address']['#access'] = FALSE; $form['billing_profile']['widget'][0]['profile']['edit_button']['#access'] = FALSE; $form['billing_profile']['widget'][0]['profile']['copy_fields']['enable']['#access'] = FALSE; $form['shipments']['#access'] = FALSE; $form['order_items']['widget']['actions']['ief_add']['#attributes']['class'][] = 'button-secondary'; if (isset($form['order_items']['widget']['entities'])) { foreach ($form['order_items']['widget']['entities'] as $key => &$entity) { if (is_numeric($key)) { $entity['actions']['ief_entity_edit']['#attributes']['class'][] = 'button-secondary'; $entity['actions']['ief_entity_remove']['#attributes']['class'][] = 'delete-order-item'; } } } $form['ddp_package_list'] = [ '#type' => 'details', '#title' => t('At DDP orders, every box must be filled with the MOQ / box quantity.'), '#weight' => -2, '#open' => FALSE, ]; $form['ddp_package_list']['block'] = [ '#type' => 'container', 'block' => [ '#markup' => bb2b_order_render_shipment_package_block(), ], ]; $header = [t('Title'), t('Shipping method'), t('Price'), t('Actions')]; $rows = []; $request = \Drupal::requestStack()->getCurrentRequest(); /** @var \Drupal\commerce_order\Entity\OrderInterface $order */ $order = $request->get('commerce_order'); if ($order && $user->hasPermission('update default commerce_order')) { $form_state->set('order', $order); /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface[] $shipments */ $shipments = $order->get('shipments')->referencedEntities(); foreach ($shipments as $shipment) { $row = $links = []; $links['edit'] = [ 'title' => t('Edit'), 'url' => $shipment->toUrl('edit-form'), 'attributes' => [ 'role' => 'button', 'class' => ['button button-secondary'], // 'target' => '_blank', ], ]; $row[] = [ 'data' => [ '#type' => 'markup', '#markup' => $shipment->label(), ], ]; $row[] = [ 'data' => [ '#type' => 'markup', '#markup' => $shipment->getShippingMethod()->label(), ], ]; $row[] = [ 'data' => [ '#type' => 'markup', '#markup' => $shipment->getAmount(), ], ]; $row[] = [ 'data' => [ '#type' => 'operations', '#links' => $links, ], ]; $rows[] = $row; } } $form['shipments_list'] = [ '#type' => 'container', '#weight' => $form['shipments']['#weight'] ?? 0, 'shipments' => [ '#type' => 'fieldset', '#title' => t('Shipments'), 'entities' => [ '#theme' => 'table', '#rows' => $rows, '#header' => $header, ], ], ]; array_unshift($form['#validate'], 'validate_first_package_is_full'); // Redirect user to order view. $form['actions']['submit']['#submit'][] = 'bb2b_order_order_edit_form_submit'; } } /** * Custom submit handler for the order edit form. */ function bb2b_order_order_edit_form_submit($form, FormStateInterface $form_state) { $order = $form_state->get('order'); if ($order) { $form_state->setRedirect('entity.commerce_order.user_view', [ 'commerce_order' => $order->id(), 'user' => $order->getCustomerId(), ]); } } /** * Render shipment packages block content. * * @return mixed * The rendered content. */ function bb2b_order_render_shipment_package_block() { $shipment_package_view = views_embed_view('shipment_package_list', 'block_1'); return \Drupal::service('renderer') ->render($shipment_package_view); } /** * Form validation handler for commerce_order_default_edit_form(). * * @param array $form * A build form array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. */ function validate_first_package_is_full(array $form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $parents = $triggering_element['#array_parents']; $triggering_element_name = array_pop($parents); if ($triggering_element_name === 'submit') { $storage = $form_state->getStorage(); $order_items_array = $storage['inline_entity_form']['order_items-form']['entities'] ?? []; /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); $order_type = NULL; $order_items = []; foreach ($order_items_array as $order_item_array) { if (isset($order_item_array['entity'])) { $order_items[] = $order_item_array['entity']; if (!$order_type) { $order = $order_item_array['entity']->getOrder(); $order_type = $order ? $order->get('field_order_type')->value : NULL; } } } if ($order_items && $order_type !== 'drop_shipping') { $quantities = $order_service->getOrderedQuantitiesByTag($order_items); if ($order_service->minQuantityIsNotValid($quantities)) { $form_state->setErrorByName('full_package', t('Your order can not be completed because the conditions for minimum order quantity is not met.')); } } } } /** * Implements hook_inline_entity_form_entity_form_alter(). */ function bb2b_order_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) { $access_commerce_admin_pages = \Drupal::currentUser() ->hasPermission('access commerce administration pages'); if (!$access_commerce_admin_pages) { if ($entity_form['#entity_type'] === 'commerce_shipment') { $entity_form['title']['#access'] = FALSE; $entity_form['shipping_method']['#access'] = FALSE; $entity_form['tracking_code']['#access'] = FALSE; } elseif ($entity_form['#entity_type'] === 'commerce_order_item') { $entity_form['unit_price']['#access'] = FALSE; $default_quantity = (int) ($entity_form['quantity']['widget'][0]['value']['#default_value'] ?? 0); $entity_form['quantity']['widget'][0]['value']['#default_value'] = $default_quantity; $entity_form['purchased_entity']['widget'][0]['target_id']['#attributes']['class'][] = 'form-order-item-autocomplete'; } } } /** * Implements hook_entity_base_field_info_alter(). */ function bb2b_order_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) { if ($entity_type->id() === 'commerce_order_item' && isset($fields['quantity'])) { $fields['quantity']->addConstraint('CheckAvailable'); } } /** * Implements hook_ENTITY_TYPE_presave(). */ function bb2b_order_commerce_shipment_presave(ShipmentInterface $shipment) { $order = $shipment->getOrder(); $pending_order = $order && $order->getState()->getId() === 'pending'; $shipping_force_resolve = $shipment->getData('shipping_force_resolve', FALSE); if ($shipment->original && $pending_order && $shipping_force_resolve) { /** @var \Drupal\bb2b_order\OrderServiceInterface $order_service */ $order_service = \Drupal::service('bb2b_order.order_service'); $order = $shipment->getOrder(); $shipping_method = $order_service ->getShippingMethodForOrder($order, $shipment->getShippingProfile()); if ($shipping_method) { $adjustments = $order->getAdjustments(); $order_service->setShippingMethodForShipment($shipment, $shipping_method, 0, $adjustments); $order->set('adjustments', $adjustments); } $shipment->setData('shipping_force_resolve', FALSE); } } /** * Implements hook_theme(). */ function bb2b_order_theme($existing, $type, $theme, $path) { return [ 'commerce_checkout_form__with_sidebar' => [ 'base hook' => 'commerce_checkout_form', 'variables' => [ 'ordered_products' => NULL, ], ], ]; } /** * Implements hook_preprocess_HOOK(). */ function bb2b_order_preprocess_commerce_checkout_form__with_sidebar(&$variables) { $block = Block::load('views_block__ordered_products_block_2'); $step = $variables['form']['#step_id'] ?? NULL; if ($block && $step === 'complete') { $variables['ordered_products'] = $block->getPlugin()->build(); $variables['ordered_products']['#attributes']['class'][] = 'ordered-products-block'; } } /** * Implements hook_tokens_alter(). */ function bb2b_order_tokens_alter(array &$replacements, array $context, BubbleableMetadata $bubbleable_metadata) { // Clear empty token. if (isset($context['data']['entity_type']) && $context['data']['entity_type'] === 'commerce_order' ) { foreach ($context['tokens'] as $token) { if (!isset($replacements[$token])) { $replacements[$token] = ''; } } } } /** * Implements hook_entity_view_alter(). */ function bb2b_order_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) { if ($build['#view_mode'] === 'user' && $build['#entity_type'] === 'commerce_order' ) { /** @var \Drupal\commerce_order\Entity\OrderInterface $entity */ $entity_state = $entity->getState()->getId(); if ($entity_state === 'pending') { $order = $build['#commerce_order']; $vat_verified = $order->get('field_vat_verified')->value; if (($vat_verified === '1') || ($vat_verified === '0')) { $ship_uri = '/orders/' . $entity->id() . '/send'; $ship_url = Url::fromUri('internal:' . $ship_uri); $build['ship_the_order_link'] = [ '#type' => 'link', '#title' => t('Ship the order'), '#url' => $ship_url, '#weight' => -11, '#attributes' => [ 'class' => ['button button-secondary'], ], ]; } $user = $entity->getCustomer(); if ($user->hasPermission('update default commerce_order')) { $build['edit_link'] = [ '#type' => 'link', '#title' => t('Edit order'), '#url' => $entity->toUrl('edit-form'), '#weight' => -10, '#attributes' => [ 'class' => ['button button-secondary'], ], ]; } } } }
<?php namespace Drupal\bb2b_order; use Drupal\bb2b_company\CompanyInterface; use Drupal\commerce_order\Adjustment; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_price\Price; use Drupal\commerce_product\Entity\ProductInterface; use Drupal\commerce_product\Entity\ProductVariationInterface; use Drupal\commerce_shipping\Entity\ShipmentInterface; use Drupal\commerce_shipping\Entity\ShippingMethod; use Drupal\commerce_shipping\Entity\ShippingMethodInterface; use Drupal\commerce_shipping\ShippingOrderManagerInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\TempStore\PrivateTempStoreFactory; use Drupal\paragraphs\ParagraphInterface; use Drupal\profile\Entity\ProfileInterface; /** * Class Order Service. */ class OrderService implements OrderServiceInterface { use StringTranslationTrait; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The messenger. * * @var \Drupal\Core\Messenger\MessengerInterface */ protected $messenger; /** * The cache. * * @var \Drupal\Core\Cache\CacheBackendInterface */ protected $cache; /** * The shipping order manager. * * @var \Drupal\commerce_shipping\ShippingOrderManagerInterface */ protected $shippingOrderManager; /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected $database; /** * The private temp store. * * @var \Drupal\Core\TempStore\PrivateTempStore */ protected $tempStore; /** * The Base Linker config. * * @var \Drupal\Core\Config\Config */ protected $baseLinkerConfig; /** * Constructs a new OrderService object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\Messenger\MessengerInterface $messenger * The messenger. * @param \Drupal\Core\Cache\CacheBackendInterface $cache * The cache. * @param \Drupal\commerce_shipping\ShippingOrderManagerInterface $shipping_order_manager * The shipping order manager. * @param \Drupal\Core\Database\Connection $database * The database connection. * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $temp_store_factory * The tempstore factory. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. */ public function __construct( EntityTypeManagerInterface $entity_type_manager, MessengerInterface $messenger, CacheBackendInterface $cache, ShippingOrderManagerInterface $shipping_order_manager, Connection $database, PrivateTempStoreFactory $temp_store_factory, ConfigFactoryInterface $config_factory ) { $this->entityTypeManager = $entity_type_manager; $this->messenger = $messenger; $this->cache = $cache; $this->shippingOrderManager = $shipping_order_manager; $this->database = $database; $this->tempStore = $temp_store_factory->get('bb2b_order'); $this->baseLinkerConfig = $config_factory->get('bb2b_baselinker.settings'); } /** * {@inheritdoc} */ public function getApplicableWarehouse(ProductInterface $product) { $cid = 'get_applicable_warehouse_' . $product->id(); $cache_data = $this->cache->get($cid); if (isset($cache_data->data)) { return $cache_data->data; } else { // @todo Logic to check which warehouse will be used in reality. $warehouse = $this->entityTypeManager->getStorage('taxonomy_term')->loadByProperties([ 'vid' => 'warehouse', 'field_warehouse_code' => 'PL', ]); $warehouse = reset($warehouse); $product_warehouses = $product->get('field_warehouse')->referencedEntities(); $applicable_warehouse = NULL; foreach ($product_warehouses as $product_warehouse) { $warehouse_target_id = $product_warehouse->get('field_warehouse')->target_id; if ($warehouse_target_id == $warehouse->id()) { $applicable_warehouse = $product_warehouse; } } if (!empty($applicable_warehouse)) { $cache_tags = [ 'commerce_product:' . $product->id(), 'paragraph:' . $applicable_warehouse->id(), ]; $this->cache->set($cid, $applicable_warehouse, CacheBackendInterface::CACHE_PERMANENT, $cache_tags); } return $applicable_warehouse; } } /** * {@inheritdoc} */ public function setStockOnWarehouse(ParagraphInterface $warehouse, int $stock) { if ($stock <= 0) { $warehouse->setUnpublished(); } elseif (!$warehouse->isPublished() && $stock > 0) { $warehouse->setPublished(); } $warehouse->set('field_available', $stock); $warehouse->set('field_last_linker_stock_sync', time()); $warehouse->save(); } /** * {@inheritdoc} */ public function getAvailableStock(ProductInterface $product, ?ParagraphInterface $product_warehouse = NULL) { $cid = 'get_available_stock_' . $product->id(); $cache_data = $this->cache->get($cid); if (isset($cache_data->data)) { return $cache_data->data; } else { // For regular non-bundle products. if ($product->get('field_bundle_product_skus')->isEmpty()) { $available_stock = $this->doGetAvailableStock($product, $product_warehouse); } // For bundle products we need to check all products that are part of the // bundle. else { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation_item */ $available_stock_for_product = []; foreach ($product->get('field_bundle_product_skus')->referencedEntities() as $variation_item) { $product_item = $variation_item->getProduct(); $available_stock_for_product[] = $this->doGetAvailableStock($product_item, $product_warehouse); } $available_stock = min($available_stock_for_product); } $cache_tags = [ 'commerce_product:' . $product->id(), ]; if ($product_warehouse !== NULL) { $cache_tags[] = 'paragraph:' . $product_warehouse->id(); } $this->cache->set($cid, $available_stock, CacheBackendInterface::CACHE_PERMANENT, $cache_tags); return $available_stock; } } /** * Gets the available stock value. * * @param \Drupal\commerce_product\Entity\ProductInterface $product * The product. * @param \Drupal\paragraphs\ParagraphInterface|null $product_warehouse * The warehouse. * * @return int * The available stock. */ protected function doGetAvailableStock(ProductInterface $product, ?ParagraphInterface $product_warehouse = NULL) { if (!$product_warehouse) { /** @var \Drupal\paragraphs\ParagraphInterface $product_warehouse */ $product_warehouse = $this->getApplicableWarehouse($product); if (!$product_warehouse) { return 0; } } $local_stock = (int) $product_warehouse->get('field_available')->value; $stock_reserved_belmil_de = (int) $product->get('field_stock_reserved_belmil_de')->value; if ($stock_reserved_belmil_de > 0) { $local_stock -= $stock_reserved_belmil_de; } $stock_reserved = (int) $product_warehouse->get('field_reserved')->value; if ($stock_reserved > 0) { $local_stock -= $stock_reserved; } return $local_stock > 0 ? $local_stock : 0; } /** * {@inheritdoc} */ public function checkAccessForProduct(ProductInterface $product) { $cid = 'access_for_product_' . $product->id(); $cache_data = $this->cache->get($cid); if (isset($cache_data->data)) { return $cache_data->data; } else { /** @var \Drupal\paragraphs\ParagraphInterface $warehouse */ $warehouse = $this->getApplicableWarehouse($product); $available = $this->getAvailableStock($product, $warehouse); $result = $warehouse && $available > 0; $cache_tags = [ 'commerce_product:' . $product->id(), ]; if ($warehouse !== NULL) { $cache_tags[] = 'paragraph:' . $warehouse->id(); } $this->cache->set($cid, $result, CacheBackendInterface::CACHE_PERMANENT, $cache_tags); return $result; } } /** * {@inheritdoc} */ public function getCompanyForClient(OrderInterface $order) { $customer_id = $order->getData('client_id', $order->getCustomerId()); if (!$customer_id) { return NULL; } return $this->getCompanyForCustomer($customer_id); } /** * {@inheritdoc} */ public function getCompanyForCustomer($customer_id) { $company_storage = $this->entityTypeManager->getStorage('company'); $company = $company_storage->loadByProperties([ 'employees' => $customer_id, ]); $company = reset($company); if (!$company) { return NULL; } return $company; } /** * {@inheritdoc} */ public function getProductPriceForClient(ProductVariationInterface $variation, OrderInterface $order, CompanyInterface $company = NULL) { $price = $variation->getPrice(); $list_price = $variation->getListPrice(); $calculated_price = [ 'price' => $price, 'list_price' => $list_price, ]; if (!$company) { return $calculated_price; } $order_type = $order->get('field_order_type')->value; $client_price_groups = $company->get('price_group')->referencedEntities() ?? NULL; $with_return = $company->get('auto_generate_return_label')->value; if (!$client_price_groups) { return $calculated_price; } $client_price_group_ids = array_map(function ($client_price_group) { return $client_price_group->id(); }, $client_price_groups); $product = $variation->getProduct(); $product_price_groups = $product->get('field_price_group')->referencedEntities(); $price_groups = array_filter($product_price_groups, function ($product_price_group) use ($client_price_group_ids) { $price_group_terms = $product_price_group->get('field_price_group')->referencedEntities(); /** @var \Drupal\taxonomy\Entity\Term $price_group_term */ $price_group_term = reset($price_group_terms); return $price_group_term && in_array($price_group_term->id(), $client_price_group_ids); }); if (!$price_groups) { return $calculated_price; } $price_group_price = 0; foreach ($price_groups as $price_group) { if ($order_type === 'ddp' || $order_type === 'ddp_reservation') { $price_group_price = $price_group->get('field_ddp')->value; } elseif ($order_type === 'drop_shipping' && !$with_return) { $price_group_price = $price_group->get('field_dsnr')->value; } elseif ($order_type === 'drop_shipping' && $with_return) { $price_group_price = $price_group->get('field_dswr')->value; } if ($price_group_price > 0) { break; } } if ($price_group_price == 0) { return $calculated_price; } $currency = $price->getCurrencyCode(); $calculated_price['price'] = new Price((string) $price_group_price, $currency); if ($list_price) { $calculated_price['list_price'] = new Price((string) $price_group_price, $currency); } return $calculated_price; } /** * {@inheritdoc} */ public function packageMinQuantityIsValid(OrderInterface $order): bool { return $this->getNotFullPackageCount($order) === 0; } /** * {@inheritdoc} */ public function getNotFullPackageCount(OrderInterface $order): int { $order_type = $order->get('field_order_type')->value; $not_valid_packages = 0; if ($order_type === 'drop_shipping') { return 0; } // Sum order item quantities by Tag. $quantities = $this->getOrderedQuantitiesByTag($order->getItems()); if (!$quantities) { return 1; } $shipment_packages = $this->entityTypeManager ->getStorage('shipment_package') ->loadMultiple(); // Check min quantities. foreach ($shipment_packages as $shipment_package) { $ordered_quantity = 0; $min_order_quantity = (int) $shipment_package->get('max_item_per_package')->value; $articles = $shipment_package->get('article_no')->referencedEntities(); foreach ($articles as $article) { if (isset($quantities[$article->id()])) { $ordered_quantity += $quantities[$article->id()]; } } if ($ordered_quantity > 0 && (!$min_order_quantity || $ordered_quantity < $min_order_quantity || $ordered_quantity % $min_order_quantity != 0) ) { $not_valid_packages++; } } return $not_valid_packages; } /** * {@inheritdoc} */ public function firstPackageIsNotFull(OrderInterface $order): bool { $order_type = $order->get('field_order_type')->value; if ($order_type === 'drop_shipping') { return FALSE; } // Sum order item quantities by Tag. $quantities = $this->getOrderedQuantitiesByTag($order->getItems()); return $this->minQuantityIsNotValid($quantities); } /** * Check ordered quantity. * * @param array $quantities * The ordered quantities. * * @return bool * Return TRUE if minimum ordered quantity is not valid. */ public function minQuantityIsNotValid(array $quantities): bool { $shipment_packages = $this->entityTypeManager ->getStorage('shipment_package') ->loadMultiple(); // Check min quantities. foreach ($shipment_packages as $shipment_package) { $ordered_quantity = 0; $min_order_quantity = (int) $shipment_package->get('max_item_per_package')->value; $articles = $shipment_package->get('article_no')->referencedEntities(); foreach ($articles as $article) { if (isset($quantities[$article->id()])) { $ordered_quantity += $quantities[$article->id()]; } } if ($ordered_quantity > 0 && $ordered_quantity < $min_order_quantity) { return TRUE; } } return FALSE; } /** * Gets the order item quantities by tag. * * @param \Drupal\commerce_order\Entity\OrderItemInterface[] $order_items * The order items. */ public function getOrderedQuantitiesByTag(array $order_items): array { $quantities = []; foreach ($order_items as $order_item) { /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchased_entity */ $purchased_entity = $order_item->getPurchasedEntity(); if (!$purchased_entity || $purchased_entity->getEntityTypeId() != 'commerce_product_variation') { continue; } /** @var \Drupal\commerce_product\Entity\ProductInterface $product */ $product = $purchased_entity->getProduct(); $tag = $product->get('field_tag')->referencedEntities(); $tag = reset($tag); if (!$tag) { return []; } $tag_id = $tag->id(); if (isset($quantities[$tag_id])) { $quantities[$tag_id] += (int) $order_item->getQuantity(); } else { $quantities[$tag_id] = (int) $order_item->getQuantity(); } } return $quantities; } /** * {@inheritdoc} */ public function getMinOrderQuantity(ProductInterface $product) { $min_order_quantity = 1; $tag = $product->get('field_tag')->referencedEntities(); $tag = reset($tag); if ($tag) { $shipment_packages = $this->entityTypeManager ->getStorage('shipment_package') ->loadMultiple(); $package = array_filter($shipment_packages, function ($shipment_package) use ($tag) { $terms = $shipment_package->get('article_no')->referencedEntities(); $term_ids = array_map(function ($term) { return $term->id(); }, $terms); return in_array($tag->id(), $term_ids); }); $package = reset($package); $min_order_quantity = $package ? $package->get('max_item_per_package')->value : 1; } return $min_order_quantity; } /** * Resolve shipping for order. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order. * @param \Drupal\profile\Entity\ProfileInterface|null $billing_profile * The billing profile. * @param \Drupal\profile\Entity\ProfileInterface|null $shipping_profile * The shipping profile. * @param string|null $shipping_country * The shipping country. */ public function resolveShipping( OrderInterface $order, ?ProfileInterface $billing_profile = NULL, ?ProfileInterface $shipping_profile = NULL, ?string $shipping_country = NULL ) { if (!$billing_profile) { $billing_profile = $order->getBillingProfile(); } if (!$shipping_profile) { $shipping_profile = $order->collectProfiles()['shipping'] ?? NULL; } if (!$shipping_profile && $billing_profile) { $shipping_profile = $billing_profile->createDuplicate(); $shipping_profile->unsetData('copy_to_address_book'); } if (!$billing_profile && $shipping_profile) { $billing_profile = $shipping_profile->createDuplicate(); $billing_profile->unsetData('copy_to_address_book'); } if (!$billing_profile || !$shipping_profile) { return; } $shipments = $this->shippingOrderManager->pack($order, $shipping_profile); $store_key = 'shipping_force_resolve:' . $order->id(); $shipping_force_resolve = $this->tempStore->get($store_key); $this->tempStore->delete($store_key); $shipping_country = $shipping_country ?: $shipping_profile ->get('address')->country_code; $shipping_method = $this->getShippingMethodForOrder($order, $billing_profile, $shipping_country); if ($shipping_method) { $shipping_adjustments = $order->getAdjustments(['shipping']); foreach ($shipping_adjustments as $adjustment) { $order->get('adjustments')->removeAdjustment($adjustment); } $adjustments = $order->getAdjustments(); /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */ foreach ($shipments as $key => $shipment) { $this->setShippingMethodForShipment($order, $shipment, $shipping_method, $key, $adjustments); if ($shipping_force_resolve) { $shipment->save(); } } $order->set('adjustments', $adjustments); } $order->set('shipments', $shipments); } /** * Get shipping method for order. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order. * @param \Drupal\profile\Entity\ProfileInterface|null $profile * The profile. * @param string|null $shipping_country * The shipping country. * * @return \Drupal\commerce_shipping\Entity\ShippingMethodInterface|null * The shipping method. */ public function getShippingMethodForOrder(OrderInterface $order, ProfileInterface $profile, ?string $shipping_country = NULL) { $shipping_method = NULL; /** @var \Drupal\commerce_shipping\Entity\ShippingMethodInterface[] $shipping_methods */ $shipping_methods = ShippingMethod::loadMultiple(); $shipping_methods = array_filter($shipping_methods, function ($item) { return $item->getPlugin()->getPluginId() == 'belmil_shipping' && $item->isEnabled(); }); usort($shipping_methods, function ($a, $b) { return $a->getWeight() <=> $b->getWeight(); }); $time_now = DrupalDateTime::createFromTimestamp(time()); $time_now->setTimezone(new \DateTimeZone('Europe/Belgrade')); // Saturday is also working day. Only sunday is weekend. $is_weekend = $time_now->format('N') == 7; $order_type = $order->get('field_order_type')->value; $order_source = $order->get('field_source')->value; $belmil_de_shipping_method = NULL; if ($order_source === 'belmilde') { $belmil_de_shipping_method = $order->getData('belmil_de_shipping_method', 'standard'); } $amazon_shipping_method = NULL; if ($order_source === 'amazon') { $amazon_shipping_method = $order->getData('amazon_shipping_method', 'Std DE Dom_3'); } $packstation_address = $profile->hasField('field_packstation_address') && $profile->get('field_packstation_address')->value; $packstation_postnumber = $profile->hasField('field_packstation_postnumber') ? $profile->get('field_packstation_postnumber')->value : NULL; $shipping_profile_country = $shipping_country ?: $profile->get('address')->country_code; $shipping_with_packstation = $shipping_profile_country === 'DE' && $packstation_address && $packstation_postnumber; foreach ($shipping_methods as $shipping_method_entity) { $method_configuration = $shipping_method_entity->getPlugin() ->getConfiguration(); $method_countries = $method_configuration['belmil'] ?? []; // Set amazon related shipping method. if ($order_source == 'amazon') { // DE Standard or Express. if ($shipping_method_entity->label() == 'DEDHL' && in_array($amazon_shipping_method, ['Std DE Dom_3', 'Exp DE Dom_1']) ) { $shipping_method = $shipping_method_entity; break; } // International EU. elseif ($shipping_method_entity->label() == 'DHL DE INTERNATIONAL' && $amazon_shipping_method == 'Std DE Intl_2' ) { $shipping_method = $shipping_method_entity; break; } } // DHL Packstation address. if ($shipping_with_packstation && isset($method_configuration['address']) && $method_configuration['address']['packstation'] ) { foreach ($method_countries as $country_code => $country_config) { if ($shipping_profile_country == $country_code && !empty($country_config['enabled']) ) { $shipping_method = $shipping_method_entity; break 2; } } } // Check store condition. if (!in_array($order->getStoreId(), $shipping_method_entity->getStoreIds())) { continue; } // Order total conditions check. $conditions = $shipping_method_entity->getConditions(); if ($conditions) { /** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface[] $order_total_conditions */ $order_total_conditions = array_filter($conditions, function ($condition) { /** @var \Drupal\commerce\Plugin\Commerce\Condition\ConditionInterface $condition */ return $condition->getEntityTypeId() == 'commerce_order' && $condition->getPluginId() === 'order_total_price'; }); $order_total_condition = reset($order_total_conditions); if ($order_total_condition && !$order_total_condition->evaluate($order)) { continue; } } if ( isset($method_configuration['belmil']) && isset($method_configuration['order_types']) && isset($method_configuration['time']) && !$shipping_with_packstation ) { foreach ($method_countries as $country_code => $country_config) { if ( $shipping_profile_country == $country_code && !empty($country_config['enabled']) && !empty($method_configuration['order_types'][$order_type]) ) { // Check time conditions for weekend. if ($is_weekend === TRUE) { if (!empty($method_configuration['time']['use_on_weekends']) && !empty($method_configuration['time']['use_on_weekends_type'])) { $weekends_time_until = new DrupalDateTime($method_configuration['time']['weekends_time_until']); $weekends_time_after = new DrupalDateTime($method_configuration['time']['weekends_time_after']); // For DDP orders we don't have to check time conditions. $ignore_time_conditions_for_ddp = !empty($method_configuration['time']['ignore_for_ddp']); if ($ignore_time_conditions_for_ddp === TRUE && in_array($order_type, ['ddp', 'ddp_reservation']) ) { $shipping_method = $shipping_method_entity; break 2; } // Check if the current time is in range for non-ddp orders. if ($method_configuration['time']['use_on_weekends_type'] == 'included') { if ($time_now >= $weekends_time_until && $time_now <= $weekends_time_after) { $shipping_method = $shipping_method_entity; break 2; } } elseif ($method_configuration['time']['use_on_weekends_type'] == 'excluded') { if ($time_now < $weekends_time_until || $time_now > $weekends_time_after) { $shipping_method = $shipping_method_entity; break 2; } } } } // Check time conditions for weekdays. else { if (!empty($method_configuration['time']['use_on_workdays']) && !empty($method_configuration['time']['use_on_workdays_type'])) { $workdays_time_until = new DrupalDateTime($method_configuration['time']['workdays_time_until']); $workdays_time_after = new DrupalDateTime($method_configuration['time']['workdays_time_after']); // For DDP orders we don't have to check time conditions. $ignore_time_conditions_for_ddp = !empty($method_configuration['time']['ignore_for_ddp']); if ($ignore_time_conditions_for_ddp === TRUE && in_array($order_type, ['ddp', 'ddp_reservation']) ) { $shipping_method = $shipping_method_entity; break 2; } // Check if the current time is in range for non-ddp orders. if ($method_configuration['time']['use_on_workdays_type'] == 'included') { if ($time_now >= $workdays_time_until && $time_now <= $workdays_time_after) { $shipping_method = $shipping_method_entity; break 2; } } elseif ($method_configuration['time']['use_on_workdays_type'] == 'excluded') { $excluded = $time_now < $workdays_time_until || $time_now > $workdays_time_after; if ($excluded || (!$excluded && $belmil_de_shipping_method === 'standard') ) { $shipping_method = $shipping_method_entity; break 2; } } } } } } } } return $shipping_method; } /** * Set shipping method for shipment. * * @param \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment * The shipment. * @param \Drupal\commerce_shipping\Entity\ShippingMethodInterface $shipping_method * The shipping method. * @param int|null $key * The shipment key. * @param \Drupal\commerce_order\Adjustment[] $adjustments * The order adjustments. */ public function setShippingMethodForShipment(OrderInterface $order, ShipmentInterface $shipment, ShippingMethodInterface $shipping_method, ?int $key = 0, array &$adjustments = []) { $shipment->setShippingMethod($shipping_method); $order_type = $order->get('field_order_type')->value; $order_source = $order->get('field_source')->value; $your_order_id = $order->get('field_your_order_id')->value; $shipping_method_plugin = $shipping_method->getPlugin(); $shipping_rates = $shipping_method_plugin->calculateRates($shipment); $shipping_rate = reset($shipping_rates); $shipping_label = $shipping_rate->getService()->getLabel(); /** @var \Drupal\commerce_price\Price $amount */ $amount = $shipping_rate->getAmount(); // Belmil.de express price is 10 EUR. if ($order_source === 'belmilde' && $shipping_label === 'DEDHL Prime' ) { $amount = new Price('10', $amount->getCurrencyCode()); } // DDP is FREE. if (in_array($order_type, ['ddp', 'ddp_reservation'])) { $amount = new Price('0', $amount->getCurrencyCode()); } // Amazon. if ($order_source === 'amazon') { $amount_number = 0; $amazon_shipping_method = $order->getData('amazon_shipping_method', 'Std DE Dom_3'); // DE Standard. if ($amazon_shipping_method === 'Std DE Dom_3') { $amount_number = $this->baseLinkerConfig->get('amazon_standard_de_price'); } // DE Express. elseif ($amazon_shipping_method === 'Exp DE Dom_1') { $amount_number = $this->baseLinkerConfig->get('amazon_express_de_price'); } // International EU. elseif ($amazon_shipping_method === 'Std DE Intl_2') { $amount_number = $this->baseLinkerConfig->get('amazon_eu_price'); } $items = count($shipment->getItems()); $amount = new Price($items * $amount_number, $amount->getCurrencyCode()); } $shipment->setAmount($amount); $shipping_service = $shipping_rate->getService()->getId(); $shipment->setShippingService($shipping_service); $shipment_number = str_pad(($key + 1), 2, '0', STR_PAD_LEFT); $shipment_number = $your_order_id ? $shipment_number . ' #' . $your_order_id : $shipment_number; $shipment_title = $this->t('Shipping for package @order_id', [ '@order_id' => $shipment_number, ]); $shipment->setTitle($shipment_title); // In case there are some changes on placed order that are // affecting shipment information. if (!empty($order->get('placed')->value)) { $shipment->save(); } $cloned_adjustment = NULL; foreach ($adjustments as $key => $adjustment) { // Edit existing shipment amount. if ($adjustment->getSourceId() == $shipment->id()) { $cloned_adjustment = $adjustment->toArray(); $cloned_adjustment['amount'] = $amount; unset($adjustments[$key]); $order->get('adjustments')->removeAdjustment($adjustment); $adjustments[] = new Adjustment($cloned_adjustment); } } if (!$cloned_adjustment) { $adjustments[] = new Adjustment([ 'type' => 'shipping', 'label' => $shipment_title, 'amount' => $amount, 'source_id' => $shipment->id(), ]); } } /** * Set surcharges on order. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * The order. */ public function setOrderSurcharges(OrderInterface $order) { $adjustments = $order->getAdjustments(['custom']); foreach ($adjustments as $adjustment) { $order->get('adjustments')->removeAdjustment($adjustment); } $currency = $order->getTotalPrice()->getCurrencyCode(); $not_full_package_cnt = $this->getNotFullPackageCount($order); // Convert back to while if we need more surcharge. if ($not_full_package_cnt > 0) { $order->addAdjustment(new Adjustment([ 'type' => 'custom', 'label' => $this->t('Surcharge'), 'amount' => new Price('4.00', $currency), 'source_id' => $order->id() . '|' . $not_full_package_cnt, ])); // $not_full_package_cnt--; } } /** * Get bundle products variation ids. * * @return mixed * The ids. */ public function getBundleProductIds() { $query = $this->database->query("SELECT DISTINCT p.field_bundle_product_skus_target_id AS field_bundle_product_skus_target_id FROM {commerce_product__field_bundle_product_skus} p INNER JOIN {commerce_product_variation_field_data} pv ON pv.variation_id = p.field_bundle_product_skus_target_id LEFT OUTER JOIN {commerce_product__field_main_and_bundle_product} mb ON mb.entity_id = pv.product_id WHERE (p.deleted = 0) AND ((mb.field_main_and_bundle_product_value IS NULL) OR (mb.field_main_and_bundle_product_value <> 1))"); return $query->fetchCol(); } }
<?php namespace Drupal\bb2b_order\Plugin\views\filter; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\filter\FilterPluginBase; /** * Filter products by stock status. * * @ingroup views_filter_handlers * * @ViewsFilter("stock_status") */ class StockStatus extends FilterPluginBase { /** * {@inheritDoc} */ public function acceptExposedInput($input) { return TRUE; } /** * {@inheritDoc} */ public function buildExposedForm(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed'])) { return; } $identifier = $this->options['expose']['identifier']; $exposed_input = $this->view->getExposedInput(); $options = [ NULL => t('Show all products'), 'only_available' => t('Show only available products'), ]; $form[$identifier] = [ '#type' => 'select', '#title' => t('Stock status'), '#options' => $options, '#default_value' => $exposed_input, ]; return $form; } /** * {@inheritDoc} */ public function query() { /** @var \Drupal\views\Plugin\views\query\Sql $query */ $query = $this->query; $stock_status = $this->view->getExposedInput(); if (isset($stock_status['stock_status']) && $stock_status['stock_status'] === 'only_available') { $query->addWhereExpression($this->options['group'], "commerce_product_field_data.stock > 0"); } } }
<?php /** * @file * BaseLinker module functions. */ /** * Implements hook_cron(). */ function bb2b_baselinker_cron() { /** @var \Drupal\bb2b_baselinker\SyncService $sync_service */ $sync_service = \Drupal::service('bb2b_baselinker.sync_service'); $sync_service->getOrders(); $sync_service->addProduct(); } /** * Implements hook_theme(). */ function bb2b_baselinker_theme($existing, $type, $theme, $path) { return [ 'belmilb2b_baselinker_pdf' => [ 'variables' => [ 'title' => '', 'order' => [], 'order_total_paid' => '', 'currency' => '', ], ], ]; }
<?php namespace Drupal\bb2b_baselinker\Plugin\QueueWorker; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Logger\LoggerChannelInterface; use Drupal\Core\Queue\QueueWorkerBase; use Drupal\Core\Queue\RequeueException; use Drupal\Tests\Core\Logger\LoggerChannelFactoryTest; use GuzzleHttp\Client; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines 'bb2b_baselinker_addproduct' queue worker. * * @QueueWorker( * id = "bb2b_baselinker_addproduct", * title = @Translation("AddProduct"), * cron = {"time" = 60} * ) */ class AddProductQueue extends QueueWorkerBase { /** * The http client. * * @var \GuzzleHttp\Client */ protected $httpClient; /** * The logger. * * @var \Drupal\Core\Logger\LoggerChannelInterface */ protected $logger; public function __construct( array $configuration, $plugin_id, $plugin_definition, Client $httpClient, LoggerChannelFactoryInterface $logger_factory ) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->httpClient = $httpClient; $this->logger = $logger_factory->get('bb2b_baselinker'); } public static function create ( ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition ) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('http_client'), $container->get('logger.factory') ); } /** * {@inheritdoc} */ public function processItem($data) { // @todo Process data here. $params = [ 'storage_id' => '4721', 'product_id' => $data['product']->id(), 'ean' => $data['product']->get('ean')->value, ]; try { $response = $this->httpClient->request('post', $data['connected_domain'], [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', 'X-BLToken' => $data['token'], ], 'form_params' => [ 'method' => 'addProduct', 'parameters' => $params, ] ]); } catch (RequeueException $e) { $this->logger->debug('BaseLinker request failed with the message: @message', [ '@message' => $e->getMessage(), ]); } $response = json_decode($response->getStatusCode()); return $response; } }
<?php namespace Drupal\bb2b_baselinker; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\Core\Asset\AssetCollectionRendererInterface; use Drupal\Core\Asset\AssetResolverInterface; use Drupal\Core\Asset\AttachedAssets; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\ExtensionPathResolver; use Drupal\Core\Extension\InfoParserInterface; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileUrlGeneratorInterface; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Queue\QueueFactory; use Drupal\Core\Queue\RequeueException; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\RenderContext; use Drupal\Core\Render\RendererInterface; use Drupal\Core\State\StateInterface; use Drupal\Core\Theme\ThemeInitializationInterface; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; use Drupal\Core\StringTranslation\StringTranslationTrait; use GuzzleHttp\RequestOptions; use Mpdf\Mpdf; use Mpdf\Output\Destination; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * BaseLinker Sync Service. */ class SyncService { use StringTranslationTrait; /** * Get orders method name. * * @var string */ const GET_ORDERS_METHOD = 'getOrders'; /** * Last order confirmed time key. * * @var string */ const LAST_ORDER_CONFIRMED_TIME = 'bb2b_baselinker.last_order_confirmed_time'; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * The config. * * @var \Drupal\Core\Config\ImmutableConfig */ protected $config; /** * The config for athenapdf. * * @var \Drupal\Core\Config\ImmutableConfig */ protected $athenapdfConfig; /** * The logger. * * @var \Drupal\Core\Logger\LoggerChannelInterface */ protected $logger; /** * The http client. * * @var \GuzzleHttp\Client */ protected $httpClient; /** * The order queue. * * @var \Drupal\Core\Queue\QueueFactory */ protected $getOrderQueue; /** * The state. * * @var \Drupal\Core\State\StateInterface */ protected $state; /** * The database connection. * * @var \Drupal\Core\Database\Connection */ protected $database; /** * The renderer. * * @var \Drupal\Core\Render\RendererInterface */ protected $renderer; /** * The theme handler. * * @var \Drupal\Core\Extension\ThemeHandlerInterface */ protected $themeHandler; /** * The extension path resolver. * * @var \Drupal\Core\Extension\ExtensionPathResolver */ protected $extensionPathResolver; /** * The info parser. * * @var \Drupal\Core\Extension\InfoParserInterface */ protected $infoParser; /** * The theme initialization. * * @var \Drupal\Core\Theme\ThemeInitializationInterface */ protected $themeInitialization; /** * The asset resolver. * * @var \Drupal\Core\Asset\AssetResolverInterface */ protected $assetResolver; /** * The CSS collection renderer. * * @var \Drupal\Core\Asset\AssetCollectionRendererInterface */ protected $cssCollectionRenderer; /** * The current request. * * @var \Symfony\Component\HttpFoundation\Request */ protected $request; /** * File system. * * @var \Drupal\Core\File\FileSystemInterface */ protected $fileSystem; /** * The file URL generator. * * @var \Drupal\Core\File\FileUrlGeneratorInterface */ protected $fileUrlGenerator; /** * Constructs a new SyncService object. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The configuration factory. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory_athenapdf * The configuration factory for athenapdf api. * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_factory * The logger. * @param \GuzzleHttp\Client $http_client * The http client. * @param \Drupal\Core\Queue\QueueFactory $queue_factory * The queue factory. * @param \Drupal\Core\State\StateInterface $state * The state. * @param \Drupal\Core\Database\Connection $database * The database connection. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler * The theme handler. * @param \Drupal\Core\Extension\ExtensionPathResolver $extension_path_resolver * The extension path resolver. * @param \Drupal\Core\Extension\InfoParserInterface $info_parser * The info parser. * @param \Drupal\Core\Theme\ThemeInitializationInterface $theme_initialization * The theme initialization. * @param \Drupal\Core\Asset\AssetResolverInterface $asset_resolver * The asset resolver. * @param \Drupal\Core\Asset\AssetCollectionRendererInterface $css_collection_renderer * The CSS collection renderer. * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack * The request stack. * @param \Drupal\Core\File\FileSystemInterface $fileSystem * File System. * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator * The file URL generator. */ public function __construct( EntityTypeManagerInterface $entity_type_manager, ConfigFactoryInterface $config_factory, ConfigFactoryInterface $config_factory_athenapdf, LoggerChannelFactoryInterface $logger_factory, Client $http_client, QueueFactory $queue_factory, StateInterface $state, Connection $database, RendererInterface $renderer, ThemeHandlerInterface $theme_handler, ExtensionPathResolver $extension_path_resolver, InfoParserInterface $info_parser, ThemeInitializationInterface $theme_initialization, AssetResolverInterface $asset_resolver, AssetCollectionRendererInterface $css_collection_renderer, RequestStack $request_stack, FileSystemInterface $fileSystem, FileUrlGeneratorInterface $file_url_generator ) { $this->entityTypeManager = $entity_type_manager; $this->config = $config_factory->get('bb2b_baselinker.settings'); $this->athenapdfConfig = $config_factory_athenapdf->get('athenapdf_api.settings'); $this->logger = $logger_factory->get('bb2b_baselinker'); $this->httpClient = $http_client; $this->getOrderQueue = $queue_factory->get('get_orders_from_baselinker'); $this->addProductQueue = $queue_factory->get('bb2b_baselinker_addproduct'); $this->state = $state; $this->database = $database; $this->renderer = $renderer; $this->themeHandler = $theme_handler; $this->extensionPathResolver = $extension_path_resolver; $this->infoParser = $info_parser; $this->themeInitialization = $theme_initialization; $this->assetResolver = $asset_resolver; $this->cssCollectionRenderer = $css_collection_renderer; $this->request = $request_stack->getCurrentRequest(); $this->fileSystem = $fileSystem; $this->fileUrlGenerator = $file_url_generator; } /** * Get orders from BaseLinker API. * * A maximum of 100 orders are returned at a time. */ public function getOrders() { // The buyer's data are deleted after 30 days of shipment. $date_confirmed_from = $this->state ->get(self::LAST_ORDER_CONFIRMED_TIME, strtotime('-30 days')); $parameters = [ 'date_confirmed_from' => $date_confirmed_from, ]; $items = $this->getItems(self::GET_ORDERS_METHOD, $parameters); $api_orders = $items['orders'] ?? []; if ($api_orders && $items['status'] === 'SUCCESS') { foreach ($api_orders as $order) { if ($order['delivery_fullname'] !== '-') { $query = $this->database->select('queue', 'q'); $query->condition('name', 'get_orders_from_baselinker'); $query->condition('data', serialize($order)); $query->fields('q', ['item_id']); // Skip same queue items. if (empty($query->execute()->fetchAll())) { $this->getOrderQueue->createItem($order); } } } } } /** * Sync products to BaseLinker API. */ public function addProduct() { // BaseLinker API credentials. $data = []; $data['token'] = $this->config->get('token'); $data['connected_domain'] = $this->config->get('connected_domain'); // Get products that we want to integrate in BaseLinker. $products = $this->entityTypeManager ->getStorage('commerce_product') ->loadMultiple(); // Send request to BaseLinker. foreach ($products as $product) { $data['product'] = $product; $params = [ 'storage_id' => '4721', 'product_id' => $data['product']->id(), ]; try { $response = $this->httpClient->request('post', $data['connected_domain'], [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', 'X-BLToken' => $data['token'], ], 'form_params' => [ 'method' => 'addProduct', 'parameters' => $params, ] ]); } catch (RequeueException $e) { $this->logger->debug('BaseLinker request failed with the message: @message', [ '@message' => $e->getMessage(), ]); } $response = json_decode($response->getStatusCode()); } } /** * Request to the connected domain. * * @param string $method * Which method is used for request. * @param array $parameters * Order parameters for request. * * @return array * Return items. */ public function getItems(string $method, array $parameters = []): array { $token = $this->config->get('token'); $connected_domain = $this->config->get('connected_domain'); $base_parameters = []; if ($method === self::GET_ORDERS_METHOD) { $base_parameters = [ 'get_unconfirmed_orders' => FALSE, ]; } $parameters = array_merge($base_parameters, $parameters); try { $response = $this->httpClient->request('post', $connected_domain, [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', 'X-BLToken' => $token, ], 'form_params' => [ 'method' => $method, 'parameters' => json_encode($parameters), ], 'verify' => FALSE, 'http_errors' => FALSE, ]); } catch (RequestException $e) { $this->logger->debug('BaseLinker request failed with the message: @message', [ '@message' => $e->getMessage(), ]); } $this->logger->debug('BaseLinker API response: <pre>@body</pre>', [ '@body' => $response ? $response->getBody()->getContents() : '', ]); $items = json_decode($response->getBody(), TRUE); return $items ?: []; } /** * Generate PDF file. * * @param \Drupal\commerce_order\Entity\OrderInterface $order * Order Interface. * @param bool $is_html * Html. * @param bool $return_with_file * Return with file. * * @return string|\Symfony\Component\HttpFoundation\Response|null * Retrun response. * * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException * @throws \Drupal\Core\Theme\MissingThemeDependencyException * @throws \GuzzleHttp\Exception\GuzzleException */ public function generatePdf(OrderInterface $order, bool $is_html = FALSE, bool $return_with_file = FALSE) { $renderer = $this->renderer; $theme = $this->themeHandler->getDefault(); $theme_path = $this->extensionPathResolver->getPath('theme', $theme); $theme_info = $this->infoParser->parse("$theme_path/$theme.info.yml"); $pdf_title = $this->t('Baselinker'); $applying_guidelines = NULL; $order_items = []; foreach ($order->getItems() as $order_item) { $title = $order_item->get('title')->value; $sku = substr($title, strpos($title, ":") + 1); $shipping = $this->entityTypeManager->getStorage('commerce_shipment') ->load($order->get('shipments')[0]->target_id); // Get asin from product variation. $product = $this->entityTypeManager->getStorage('commerce_product')->load($order_item->getPurchasedEntityId()); if ($product == NULL) { continue; } $order_items[] = [ 'quantity' => $order_item->get('quantity')->value, 'title' => $title, 'price' => $order_item->get('total_price')->number, 'sku' => $sku, 'shipping' => $shipping->get('amount')[0]->number, ]; } $save_order = [ 'delivery_fullname' => $order->getBillingProfile()->get('address')[0]->given_name . ' ' . $order->getBillingProfile()->get('address')->family_name, 'delivery_address' => $order->getBillingProfile()->get('address')->address_line1, 'delivery_postal_code' => $order->getBillingProfile()->get('address')->postal_code, 'delivery_city' => $order->getBillingProfile()->get('address')[0]->locality, 'delivery_country' => $order->getBillingProfile()->get('address')[0]->country_code, 'order_number' => $order->getOrderNumber(), 'date_add' => date('D., d.M.Y', $order->get('created')->value), 'order_items' => $order_items, ]; $currency = $this->entityTypeManager->getStorage('commerce_currency')->load($order->getTotalPrice()->getCurrencyCode()); $build = [ '#theme' => 'belmilb2b_baselinker_pdf', '#order_total_paid' => $order->getTotalPrice()->getNumber(), '#pdf_title' => $pdf_title, '#title' => 'test', '#applying_guidelines' => $applying_guidelines, '#order' => $save_order, '#attached' => [ 'library' => $theme_info['libraries'], ], '#currency' => $currency->getSymbol(), ]; $logo = $this->themeInitialization->getActiveThemeByName($theme) ->getLogo(); if (strpos($logo, '.svg')) { $logo = str_replace('.svg', '.png', $logo); } $build['#site_logo'] = $logo; $context = new RenderContext(); $css_assets = $this->assetResolver->getCssAssets(AttachedAssets::createFromRenderArray($build), TRUE); $rendered_css = $this->cssCollectionRenderer->render($css_assets); /** @var \Drupal\Core\Cache\CacheableDependencyInterface $rendered_css_build */ $rendered_css_build = $this->renderer->executeInRenderContext($context, function () use ($rendered_css, $renderer) { return $renderer->render($rendered_css); }); if (!$context->isEmpty()) { $bubbleable_metadata = $context->pop(); BubbleableMetadata::createFromObject($rendered_css_build) ->merge($bubbleable_metadata); } $build['#rendered_css'] = $rendered_css_build; /** @var \Drupal\Core\Cache\CacheableDependencyInterface $html */ $html = $this->renderer->executeInRenderContext($context, function () use ($build, $renderer) { return $renderer->render($build); }); if (!$context->isEmpty()) { $bubbleable_metadata = $context->pop(); BubbleableMetadata::createFromObject($html) ->merge($bubbleable_metadata); } $host = $this->request->getSchemeAndHttpHost(); if (!$is_html && strpos($host, 'docker') !== FALSE) { $host = 'http://nginx'; } $media_string = '<link rel="stylesheet" media="all" href=""'; $css_string = '<link rel="stylesheet" type="text/css" href=""'; $html = str_replace('<img src=""', '<img src=""' . $host, $html); $html = str_replace($media_string, $media_string . $host, $html); $html = str_replace($css_string, $css_string . $host, $html); if (!$is_html) { $destination_dir = 'public://baselinker_order_pdf'; $destination = $destination_dir . '/baselinker-pdf- ' . $save_order['order_number'] . '.pdf'; $this->fileSystem->prepareDirectory($destination_dir, FileSystemInterface::CREATE_DIRECTORY || FileSystemInterface::MODIFY_PERMISSIONS); $pdf_data = $this->httpClient ->request('POST', $this->athenapdfConfig->get('endpoint') . '?auth=' . $this->athenapdfConfig->get('auth_key') . '&ext=html', [ RequestOptions::MULTIPART => [ [ 'name' => 'file', 'contents' => $html, 'filename' => 'input.html', 'headers' => [ 'Content-Type' => 'text/html; charset=utf-8', ], ], ], RequestOptions::SINK => $destination, ])->getBody()->getContents(); $pdf_file = $this->fileSystem ->saveData($pdf_data, $destination, FileSystemInterface::EXISTS_REPLACE); $order->field_documents->target_id = $pdf_file; $order->save(); if ($return_with_file) { return $pdf_file ? $this->fileUrlGenerator->generateAbsoluteString($pdf_file) : NULL; } else { $this->setPDFTitle($destination, $pdf_title); $response = new Response(); $response->headers->set('Content-Type', 'application/pdf'); $response->headers->set('Content-Disposition', 'inline; filename="' . $pdf_title . '.pdf"'); $response->setContent($pdf_data); return $response; } } else { return new Response($html); } throw new NotFoundHttpException(); } /** * Set PDF title. * * @param string $outputFilePath * Output file path. * @param string $title * Title. */ protected function setPdfTitle(string $outputFilePath, string $title) { try { $mpdf = new Mpdf(['tempDir' => $this->fileSystem->getTempDirectory()]); $page_count = $mpdf->setSourceFile($outputFilePath); for ($i = 1; $i <= $page_count; $i++) { $import_page = $mpdf->ImportPage($i); $mpdf->UseTemplate($import_page); if ($i < $page_count) { $mpdf->AddPage(); } } $mpdf->setTitle($title); $mpdf->Output($outputFilePath, Destination::FILE); } catch (\Exception $e) { // Do nothing. } } }
protected function sendPassMail($order) { // Gathering values for mail. $langcode = $order->getCustomer()->getPreferredLangcode(); $client = $order->getCustomer()->name->value; $shipping_information = \Drupal::service('commerce_shipping.order_shipment_summary')->build($order); $body = [ '#theme' => 'linker_order_pass', '#order' => $order, '#shipping_information' => $shipping_information, ]; $params = [ 'headers' => [ 'Content-Type' => 'text/html; charset=UTF-8;', 'Content-Transfer-Encoding' => '8Bit', ], 'id' => 'linker_order_pass', 'langcode' => $langcode, 'subject' => $client . ' issued the order ' . $order->id(), 'body' => $body, ]; $this->mailManager ->mail('bb2b_linker', $params['id'], 'bestellung@bescool.net', $params['langcode'], $params); } // DI za mailManager-a. /** * The mail manager. * * @var \Drupal\Core\Mail\MailManagerInterface */ protected $mailManager;
/** * Implements hook_mail(). */ function bb2b_linker_mail($key, &$message, $params) { switch ($key) { case 'commerce_tracking_code': case 'linker_order_rejected': case 'linker_order_returned': case 'linker_order_not_pass': case 'linker_order_pass': /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); if (isset($params['headers'])) { $message['headers'] = array_merge($message['headers'], $params['headers']); } if (!empty($params['from'])) { $message['from'] = $params['from']; } $message['subject'] = $params['subject']; $message['body'][] = $renderer->render($params['body']); break; } }
if ($view->id() === 'more_like_this' && $view->current_display === 'rest_similar_by_popularity' ) { $product_id = $view->args[0]; $product = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->load($product_id); $term = $product->get('app_group')->referencedEntities()[0]; $top_term = get_top_level_parent($term); if ($top_term) { switch ($top_term->get('name')->value) { case 'Kültéri lámpák' || 'Beltéri lámpák': // Recommended manufacturer. $manufacturer = \Drupal::entityTypeManager() ->getStorage('taxonomy_term') ->loadByProperties([ 'vid' => 'manufacturer', 'name' => 'AZzardo', ]); $manufacturer = reset($manufacturer); // Get all products belonging to the same term (group) // and recommended manufacturer. $products = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->loadByProperties([ 'app_group' => $term->id(), 'app_manufacturer' => $manufacturer->id(), ]); foreach ($products as $key => $product) { $onDiscount = checkIfOnDiscountAndOnStock($product); if (!$onDiscount) { unset($products[$key]); } } $product_ids = []; array_walk($products, function ($product) use (&$product_ids) { $product_ids[] = $product->id(); }); $query->addWhere(0, 'product_id', $product_ids, 'IN'); break; } } } function checkIfOnDiscountAndOnStock($product): bool { $variations = $product->getVariations(); foreach ($variations as $variation) { if (!empty($variation->get('list_price')) && $variation->get('app_purchaseitem')->value == 1) { if ($variation->get('list_price')->number > $variation->get('price')->number) { return TRUE; } } } return FALSE; } function get_top_level_parent($term) { if ($term->hasField('parent') && $term->get('parent')->target_id !== '0') { $term = $term->get('parent')->referencedEntities()[0]; return get_top_level_parent($term); } else { return $term; } }
/** * Implements hook_views_data(). */ function app_core_views_data() { $data = []; $data['views']['recommended_products'] = [ 'title' => t('Recommended products - Custom Filter' ), 'filter' => [ 'title' => t('Recommended products - Custom Filter' ), 'field' => 'id', 'id' => 'recommended_products' ] ]; return $data; }
<?php namespace Drupal\app_core\Plugin\views\filter; use Drupal\views\Plugin\views\filter\FilterPluginBase; /** * Filter for recommended products. * * @ingroup views_filter_handlers * * @ViewsFilter("recommended_products") */ class RecommendedProductsFilter extends FilterPluginBase { public function query() { $this->ensureMyTable(); $product_id = $this->view->args[0]; $product = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->load($product_id); $term = $product->get('app_group')->referencedEntities()[0]; // Recommended manufacturer. $manufacturer = \Drupal::entityTypeManager() ->getStorage('taxonomy_term') ->loadByProperties([ 'vid' => 'manufacturer', 'name' => 'AZzardo', ]); $manufacturer = reset($manufacturer); // Get all products belonging to the same term (group) // and recommended manufacturer. $products = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->loadByProperties([ 'app_group' => $term->id(), 'app_manufacturer' => $manufacturer->id(), ]); foreach ($products as $key => $product) { $onDiscount = $this->checkIfOnDiscountAndOnStock($product); if (!$onDiscount) { unset($products[$key]); } } $product_ids = []; array_walk($products, function($product) use (&$product_ids) { $product_ids[] = $product->id(); }); $this->query->addWhere(0, 'product_id', $product_ids, 'IN'); $mile = 'mile'; } public function checkIfOnDiscountAndOnStock($product){ $variations = $product->getVariations(); foreach ($variations as $variation) { if (!empty($variation->get('list_price')) && $variation->get('app_purchaseitem')->value == 1) { if ($variation->get('list_price')->number > $variation->get('price')->number) { return TRUE; } } } return FALSE; } }
<?php namespace Drupal\app_core\Plugin\views\filter; use Drupal\views\Plugin\views\filter\FilterPluginBase; /** * Filter for recommended products. * * @ingroup views_filter_handlers * * @ViewsFilter("recommended_products") */ class RecommendedProductsFilter extends FilterPluginBase { public function query() { $this->ensureMyTable(); $product_id = $this->view->args[0]; $product = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->load($product_id); $term = $product->get('app_group')->referencedEntities()[0]; // Get all products belonging to the same term (group). $products = \Drupal::entityTypeManager() ->getStorage('commerce_product') ->loadByProperties([ 'app_group' => $term->id(), ]); $product_ids = []; array_walk($products, function($product) use (&$product_ids) { $product_ids[] = $product->id(); }); $this->query->addWhere(0, 'product_id', $product_ids, 'IN'); // $product_top_group = $this->findProductsTopGroup($term); // $child_terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('group', $product_top_group->id()); // $acceptable_terms = []; // foreach ($child_terms as $child_term) { // $acceptable_terms[] = $child_term->name; // } // $products = \Drupal::entityTypeManager()->getStorage('commerce_product')->loadMultiple(); $mile = 'mile'; } // public function findProductsTopGroup($term) { // if ($term->hasField('parent') && $term->get('parent')->target_id !== '0') { // $term = $term->get('parent')->referencedEntities()[0]; // return $this->findProductsTopGroup($term); // } // else { // return $term; // } // // } }
if ($display->getComponent('item_approvement_table')) { $form = \Drupal::classResolver()->getInstanceFromDefinition(PaymentRequestItemsApprovementForm::class); $form->setPaymentRequest($entity); $form_state = new FormState(); $form_array = \Drupal::formBuilder()->buildForm($form, $form_state); $form_array['#current_tab_redirect'] = TRUE; $build['item_approvement_table'] = $form_array; }
+------------+--------------------------------------------------+-----------+ | Collection | Config | Operation | +------------+--------------------------------------------------+-----------+ | | field.storage.user.field_phone_number | Create | | | field.storage.node.field_media_contact | Create | | | field.field.node.news.field_media_contact | Create | | | field.field.user.user.field_phone_number | Create | | | user.role.media_team | Create | | | system.action.user_remove_role_action.media_team | Create | | | system.action.user_add_role_action.media_team | Create | | | core.entity_form_display.node.news.default | Update | | | core.entity_view_display.user.user.default | Update | | | core.entity_view_display.user.user.compact | Update | | | core.entity_view_display.node.news.teaser_card | Update | | | core.entity_view_display.node.news.teaser | Update | | | core.entity_view_display.node.news.image_card | Update | | | core.entity_view_display.node.news.default | Update | | | core.entity_form_display.user.user.register | Update | | | core.entity_form_display.user.user.default | Update | | | content_access.settings | Update | +------------+--------------------------------------------------+-----------+
/** * Implements hook_preprocess_HOOK(). */ function carters_core_preprocess_facets_result_item(&$variables) { if ($variables['facet']->get('name') == 'Popust') { $variables['value'] = $variables['value'] . '%'; } }
$types = []; $contentTypes = \Drupal::entityTypeManager()->getStorage('node_type')->loadMultiple(); foreach ($contentTypes as $contentType) { $types[] = $contentType->id(); }
<?php /** * @file * Contains musin_core.module. */ use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; use Drupal\Core\Url; /** * Implements hook_views_data_alter(). */ function musin_core_views_data_alter(array &$data) { $data['private_message_threads']['members_list'] = [ 'title' => t('Member(s) name list'), 'help' => t('The member(s) name of the private message thread'), 'field' => [ 'id' => 'musin_core_private_message_members_list', ], ]; $data['private_message_threads']['members_pictures'] = [ 'title' => t('Member(s) pictures'), 'help' => t('The member(s) pictures of the private message thread'), 'field' => [ 'id' => 'musin_core_private_message_members_pictures', ], ]; $data['private_message_threads']['thread_last_message'] = [ 'title' => t('Last message'), 'help' => t('The last message of the private message thread'), 'field' => [ 'id' => 'musin_core_private_message_thread_last_message', ], ]; $data['private_message_threads']['thread_is_unread'] = [ 'title' => t('Is unread or not'), 'help' => t('The last message is unreaded of the private message thread'), 'field' => [ 'id' => 'musin_core_private_message_thread_is_unread', ], ]; } /** * Implements hook_entity_extra_field_info(). */ function musin_core_entity_extra_field_info() { $extra_field = []; $extra_field['private_message']['private_message']['display']['author_image'] = [ 'label' => t('Author image'), 'description' => t('Author image.'), 'weight' => 100, 'visible' => TRUE, ]; $extra_field['private_message']['private_message']['display']['author_name'] = [ 'label' => t('Author name'), 'description' => t('Author name.'), 'weight' => 100, 'visible' => TRUE, ]; return $extra_field; } /** * Implements hook_ENTITY_TYPE_view(). */ function musin_core_private_message_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { if ($display->getComponent('author_image')) { /** @var \Drupal\musin_core\MessagesService $messages_service */ $messages_service = \Drupal::service('musin_core.messages.service'); $build['author_image'] = $messages_service->getUserPictureElement($entity->getOwner()); } if ($display->getComponent('author_name')) { /** @var \Drupal\private_message\Entity\PrivateMessage $entity*/ //$author_name = $entity->getOwner()->get('field_first_name')->value . ' ' . $entity->getOwner()->get('field_last_name')->value; $author_name = $entity->getOwner()->get('name')->value; $build['author_name'] = [ '#type' => 'markup', '#markup' => $author_name, ]; } } /** * Implements hook_form_FORM_ID_alter(). */ function musin_core_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) { $view = $form_state->getStorage('view'); if ($view && $view['view']->id() == 'search') { $form['search_api_fulltext_1']['#prefix'] = '<div class="search-dropdown">'; $form['field_genres']['#suffix'] = '</div>'; $form['field_instruments']['#options']['All'] = 'Instruments'; $form['field_genres']['#options']['All'] = 'Genres'; } } /** * Implements hook_form_FORM_ID_alter(). * Redirect user to profile page after saving the profile */ function musin_core_form_alter(&$form, $form_state, $form_id) { if ($form_id === 'user_form') { $form['#after_build'][] = '_musin_core_user_edit_change_password_label'; $form['actions']['submit']['#submit'][] = 'musin_core_user_edit_form_submit'; } if ($form_id === 'node_gig_edit_form') { $form['revision_information']['#access'] = FALSE; } } function _musin_core_user_edit_change_password_label($form, &$form_state) { //dsm($form['group_email_password_artist_name']['#groups']); $form['group_email_password_artist_name']['#groups']['group_email_password_artist_name'][0]['pass']['pass1']['#title'] = t('New password'); $form['group_email_password_artist_name']['#groups']['group_email_password_artist_name'][0]['pass']['pass2']['#title'] = t('Confirm new password'); return $form; } /** * Implements hook_field_widget_file_generic_form_alter(). */ function musin_core_field_widget_file_generic_form_alter(&$element, FormStateInterface $form_state, $context) { if ($context['form']['#parents'][0] == "field_sample_tracks") { $element['#after_build'][] = '_set_description_field_required'; } } function _set_description_field_required($element, FormStateInterface $form_state) { if (isset($element['description'])) { $element['description']['#required'] = TRUE; } return $element; } function musin_core_user_edit_form_submit($form, &$form_state) { $form_state->setRedirect('entity.user.canonical', ['user' => \Drupal::currentUser()->id()]); } /** * Implements hook_form_FORM_ID_alter(). */ function musin_core_form_user_login_form_alter(&$form, FormStateInterface $form_state, $form_id) { $form['#submit'][] = 'musin_core_user_login_form_submit'; } /** * Custom submit handler for the login form. */ function musin_core_user_login_form_submit($form, FormStateInterface $form_state) { $url = Url::fromRoute('<front>'); $form_state->setRedirectUrl($url); } /** * Implements hook_preprocess_HOOK(). */ function musin_core_preprocess_region(&$variables) { if ($variables['region'] == 'primary_navigation') { $variables['#cache']['contexts'][] = 'user'; } } /** * Implements hook_entity_presave(). * * @param \Drupal\Core\Entity\EntityInterface $entity * @param $term */ function musin_core_entity_presave(EntityInterface $entity) { if ($entity instanceof \Drupal\user\UserInterface) { $completeness = \Drupal\musin_core\Services\UserHelperService::getProfileCompleteness($entity); $entity->set('field_completeness', $completeness); // // Add typed in instrument to users profile view. // $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties([ // 'field_typed_in_instrument' => 1 // ]); // $term = reset($terms); // if ($term !== false) { // $entity->set('field_typed_in_instrument', $term); // } } // Moving typed in instruments to their vocabulary. if ($entity instanceof \Drupal\taxonomy\Entity\Term) { $name = $entity->get('name')->value; if ($entity->get('vid')->getValue()[0]['target_id'] == 'instruments' && $entity->get('field_typed_in_instrument')->value === 1) { $entity->set('vid', 'extra_instruments'); } else if ($entity->get('vid')->getValue()[0]['target_id'] == 'genres' && $entity->get('field_typed_in_genre')->value === 1) { $entity->set('vid', 'extra_genres'); } } }
<?php /** * @file * Contains fontana_commerce.module. */ use Drupal\commerce\EntityHelper; use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\RedirectCommand; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\commerce_product\Entity\ProductVariationInterface; /** * Implements hook_views_data_alter(). */ function fontana_commerce_views_data_alter(array &$data) { $data['views']['custom_category_filter'] = [ 'title' => t('Custom category filter'), 'filter' => [ 'title' => t('Custom category filter'), 'help' => t('Provides a custom filter logic.'), 'field' => 'nid', 'id' => 'category_views_filter', ], ]; $data['views']['sku_filter'] = [ 'title' => t('SKU filter'), 'filter' => [ 'title' => t('SKU filter'), 'help' => t('Provides a custom filter for filtering orders by sku.'), 'field' => 'id', 'id' => 'sku_filter', ], ]; $data['commerce_shipment']['shipping_profile'] = [ 'title' => t('Shipping Profile'), 'help' => t('Reference to the shipping profile of a commerce shipment.'), 'relationship' => [ 'group' => 'Shipment', // Views name of the table being joined to from commerce_shipment. 'base' => 'profile', // Database field name in profile for the join. 'base field' => 'profile_id', // Real database field name in commerce_shipment for the join, to override // 'unique_dummy_name'. 'field' => 'shipping_profile__target_id', // ID of relationship handler plugin to use. 'id' => 'standard', 'label' => t('Shipping Profile'), ], ]; $data['commerce_order']['quick_view'] = [ 'title' => t('Quick view'), 'field' => [ 'id' => 'commerce_order_quick_view', ], ]; $data['commerce_order']['update_state']['field'] = [ 'title' => t('Update state'), 'help' => t('Add buttons for update the order state.'), 'id' => 'commerce_order_update_state', ]; } /** * Implements hook_entity_extra_field_info(). */ function fontana_commerce_entity_extra_field_info() { $extra = []; $extra['commerce_product']['default']['display']['manufacturer_declaration'] = [ 'label' => t('Manufacturer(display: declaration)'), 'visible' => FALSE, ]; $extra['commerce_product']['default']['display']['variation_sizes'] = [ 'label' => t('Product variations size attribute'), 'visible' => TRUE, ]; $extra['commerce_product']['default']['display']['variation_colors'] = [ 'label' => t('Product variations color attribute'), 'visible' => TRUE, ]; return $extra; } /** * Implements hook_entity_view(). */ function fontana_commerce_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { if ($entity->getEntityTypeId() === 'commerce_product' && $entity->bundle() === 'default' && $display->getComponent('manufacturer_declaration')) { if ($entity->hasField('field_manufacturer')) { /** @var \Drupal\taxonomy\Entity\Term $manufacturer */ if ($manufacturer = $entity->get('field_manufacturer')->entity) { $view_builder = \Drupal::entityTypeManager()->getViewBuilder('taxonomy_term'); $build['manufacturer_declaration'] = $view_builder->view($manufacturer, 'declaration'); } } } if ($view_mode === 'teaser' && $entity->getEntityTypeId() === 'commerce_product' && $entity->bundle() === 'default') { $sizes = []; $colors = []; /** @var \Drupal\commerce_product\Entity\ProductVariationInterface $variation */ foreach ($entity->getVariations() as $variation) { if ($size = $variation->getAttributeValue('attribute_size')) { $sizes[] = $size->label(); } if ($color = $variation->getAttributeValue('attribute_boja')) { $colors[] = $color->label(); } } if ($display->getComponent('variation_sizes')) { $build['variation_sizes'] = [ '#type' => 'html_tag', '#tag' => 'div', '#value' => implode(', ', array_unique($sizes)), '#attributes' => [ 'class' => ['size-wrapper'], ], ]; } if ($display->getComponent('variation_colors')) { $build['variation_colors'] = [ '#type' => 'html_tag', '#tag' => 'div', '#value' => implode(', ', array_unique($colors)), '#attributes' => [ 'class' => ['color-wrapper'], ], ]; } } } /** * Implements hook_form_alter(). */ function fontana_commerce_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Get add to cart form from product page. if ( str_contains($form_id, "commerce_order_item_dc_ajax_add_cart_form_commerce_product") || str_contains($form_id, 'commerce_order_item_add_to_cart_form_commerce_product') ) { // Check if product contain variations. if (isset($form['purchased_entity']['widget'][0]['variation']['#options'])) { // Get variations. $variations = $form['purchased_entity']['widget'][0]['variation']['#options']; foreach ($variations as $key => $item) { // Load variation by key(id). $variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation')->load($key); // Set boja if exists. !empty($variation->get('attribute_boja')->target_id) ? $color = $variation->get('attribute_boja')->entity->getName() : $color = ""; // Set size if exists. !empty($variation->get('attribute_size')->target_id) ? $size = $variation->get('attribute_size')->entity->getName() : $size = ""; // If both fields are empty use default option. if (!empty($size) || !empty($color)) { $form['purchased_entity']['widget'][0]['variation']['#options'][$key] = $size . " " . $color; } $item_title = $variation->getTitle(); $variation_images = $variation->get('field_image')->getValue(); $images = []; foreach ($variation_images as $image) { if (empty($image['title'])) { $image['title'] = $item_title; } if (empty($image['alt'])) { $image['alt'] = $item_title; } $images[] = $image; } $variation->set('field_image', $images); } } if (isset($form['purchased_entity']['widget'][0]['variation'])) { if (isset($form['purchased_entity']['widget'][0]['variation']['#value'])) { $variation_id = $form['purchased_entity']['widget'][0]['variation']['#value']; } else { $variation_id = $form['purchased_entity']['widget'][0]['variation']['#default_value']; } $variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation')->load($variation_id); $square_meter_per_box = $variation->get('field_square_meters_per_box')->value; if (!empty($square_meter_per_box)) { $form['quantity']['widget'][0]['value']['#step'] = '0.01'; } } } // Get checkout flow form and step order information. if ($form_id == 'commerce_checkout_flow_multistep_default' && $form['#step_id'] == 'order_information') { $form['actions']['captcha'] = [ '#type' => 'captcha', '#captcha_type' => 'recaptcha/reCAPTCHA', ]; } if ($form_id == 'commerce_order_default_edit_form') { $order_id = \Drupal::routeMatch()->getRawParameter('commerce_order'); $order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id); $payment_gateway = $order->payment_gateway->first()->entity; if (!empty($payment_gateway)) { $payment_label = $payment_gateway->label(); $form['payment_gateway'] = [ '#type' => 'details', '#group' => 'advanced', '#open' => TRUE, '#title' => t('Payment Method'), 'payment_gateway' => [ '#type' => 'item', '#markup' => $payment_label, ], ]; } } $input = $form_state->getUserInput(); $is_ajax = (bool) ($input['_drupal_ajax'] ?? FALSE); if (str_contains($form_id, 'state_machine_transition_form_commerce_order_state') && $is_ajax) { foreach ($form['actions'] as $name => $action) { if (strpos($name, '#') !== FALSE) { continue; } $form['actions'][$name]['#ajax'] = [ 'callback' => 'fontana_commerce_order_state_ajax', ]; } } } /** * Ajax callback for the order state form. * * @param array $form * The form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @return \Drupal\Core\Ajax\AjaxResponse * The ajax response. */ function fontana_commerce_order_state_ajax(array $form, FormStateInterface $form_state) { $response = new AjaxResponse(); $destination = \Drupal::request()->query->get('destination'); $response->addCommand(new RedirectCommand($destination)); return $response; } /** * Implements hook_element_info_alter(). */ function fontana_commerce_element_info_alter(array &$info) { if (isset($info['address'])) { $info['address']['#process'][] = 'fontana_commerce_make_address_line2_visible'; } } /** * Process callback for address element. */ function fontana_commerce_make_address_line2_visible(array &$element, FormStateInterface $form_state, array &$complete_form) { $element['address_line2']['#title_display'] = 'before'; return $element; } /** * Implements hook_preprocess_HOOK(). */ function fontana_commerce_preprocess_commerce_product(&$variables) { /** @var \Drupal\commerce_product\Entity\ProductInterface $product_entity */ $product_entity = $variables['product_entity']; $variation = $product_entity->getDefaultVariation(); if (!$variation instanceof ProductVariationInterface) { $variables['calculator_visible'] = FALSE; } else { /** @var \Drupal\presentcommerce_box_calculator\Service\BoxCalculator $box_calculator */ $box_calculator = \Drupal::service('presentcommerce_box_calculator.box_calculator'); if ($box_calculator->isVisible($variation)) { $variables['calculator_visible'] = TRUE; } else { $variables['calculator_visible'] = FALSE; } } } /** * Implements hook_entity_presave(). */ function fontana_commerce_entity_presave(EntityInterface $entity) { // Check if entity is product variation and if autogenerate title is selected. if ($entity->getEntityTypeId() == "commerce_product_variation" && $entity->get('field_auto_generate_title')->value == TRUE) { $title = generate_variation_title($entity); $entity->setTitle($title); } elseif ($entity->getEntityTypeId() == "commerce_product_variation") { $title_alt = generate_image_title_alt($entity); if ($title_alt !== "") { $entity->set('field_image', $title_alt); } } if ($entity->getEntityTypeId() == 'commerce_product') { $userId = \Drupal::currentUser()->id(); $user = \Drupal::entityTypeManager()->getStorage('user')->load($userId); $entity->set('field_updated_by', $user); } if ($entity->getEntityTypeId() == 'commerce_order_item' && $entity->getPurchasedEntity()->get('field_square_meters_per_box')->value !== NULL) { $quantity = $entity->getQuantity(); $product = \Drupal::entityTypeManager() ->getStorage('commerce_product_variation') ->load($entity->getPurchasedEntityId()); $square_meters = $product->get('field_square_meters_per_box')->value; $number_of_boxes = (integer) round($quantity / $square_meters); if ($number_of_boxes < 1) { $number_of_boxes = 1; } $entity->set('field_number_of_boxes', $number_of_boxes); } } /** * Generate Variation title based on attributes. */ function generate_variation_title(EntityInterface $entity) { if (!$entity->getProductId()) { // Title generation is not possible before the parent product is known. return ''; } $product_title = $entity->getProduct()->getTitle(); if ($attribute_values = $entity->getAttributeValues()) { $attribute_labels = EntityHelper::extractLabels($attribute_values); $title = $product_title . ' - ' . implode(', ', $attribute_labels); } else { // When there are no attribute fields, there's only one variation. $title = $product_title; } return $title; } /** * Generate Variation title based on attributes. */ function generate_image_title_alt(EntityInterface $entity) { if (!$entity->getProductId()) { // Title generation is not possible before the parent product is known. return ''; } $product_title = $entity->getProduct()->getTitle(); $variation_images = $entity->get('field_image')->getValue(); $images = reset($variation_images); foreach ($variation_images as $image) { if (empty($image['alt'])) { $image['alt'] = $product_title; } if (empty($image['title'])) { $image['title'] = $product_title; } $images[] = $image; } return $images; } /** * Implements hook_page_attachments(). */ function fontana_commerce_page_attachments(array &$attachments) { $config = \Drupal::config('system.theme'); $theme = \Drupal::theme()->getActiveTheme()->getName(); if ($theme == $config->get('admin')) { $attachments['#attached']['library'][] = 'fontana_commerce/extra.admin'; } } /** * Implements hook_field_widget_form_alter(). */ function fontana_commerce_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) { // Fix problem with displaying description on shipping pane // for single shipping method. if ($context['items']->getFieldDefinition()->getName() === 'shipping_method' && $context['items']->getFieldDefinition()->getTargetEntityTypeId() === 'commerce_shipment') { foreach ($element['#options'] as $key => $option) { $title = $element[$key]["#rate"]->getService()->getLabel(); $option = (new FormattableMarkup('@service @amount', [ '@service' => $title, '@amount' => '', ])); $element['#options'][$key] = $option; } } } /** * Implements hook_form_BASE_FORM_ID_alter(). */ function fontana_commerce_form_views_form_commerce_cart_form_default_alter(&$form, FormStateInterface $form_state) { $order_items = $form['output'][0]['#view']->result[0]->_entity->getItems(); foreach ($order_items as $key => $order_item) { $purchased_entity = $order_item->getPurchasedEntity(); if (!empty($purchased_entity->get('field_square_meters_per_box')->getValue())) { $form['edit_quantity'][$key]['#step'] = '0.01'; } } }
<?php namespace Drupal\musin_core\Plugin\Field\FieldWidget; use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Form\FormStateInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Custom field widget for instruments. * * @FieldWidget( * id = "instruments_widget", * label = @Translation("Instruments widget"), * description = @Translation("Instruments widget"), * field_types = { * "entity_reference", * "string" * } * ) */ class InstrumentsWidget extends WidgetBase { /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entityTypeManager) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); $this->entityTypeManager = $entityTypeManager; } 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['third_party_settings'], $container->get('entity_type.manager') ); } /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { // TODO: Implement formElement() method. $value = isset($items[$delta]->value) ? $items[$delta]->value : ''; $rows = []; $taxonomies = $this->entityTypeManager ->getStorage('taxonomy_term') ->loadByProperties([ 'vid' => 'instruments', ]); foreach ($taxonomies as $term) { $rows[$term->getName()] = $term->getName(); } $element['first'] = [ '#type' => 'checkboxes', '#options' => $rows, '#attributes' => [ 'name' => 'base_taxonomy', ] ]; $element['second'] = [ '#type' => 'textfield', '#title' => 'Enter your instruments', '#states' => [ 'visible' => [ ':input[name="base_taxonomy"]' => ['value' => 'Other'] ] ] ]; return $element; } }
$variation = \Drupal::entityTypeManager()->getStorage('commerce_product_variation')->load(id)->delete();
<?php namespace Drupal\csv_import\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Messenger\Messenger; use Drupal\Core\Messenger\MessengerInterface; use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\file\Entity\File; use Drupal\node\Entity\Node; use Drupal\paragraphs\Entity\Paragraph; use Symfony\Component\DependencyInjection\ContainerInterface; class CSVImportForm extends FormBase { public function getFormId() { return 'csv_import'; } public function buildForm(array $form, FormStateInterface $form_state) { $form['csv_file'] = [ '#title' => 'Upload your file', '#type' => 'managed_file', '#upload_location' => 'public://', '#upload_validators' => [ 'file_validate_extensions' => ['csv'] ] ]; $form['actions']['#type'] = 'actions'; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), ]; return $form; } public function submitForm(array &$form, FormStateInterface $form_state) { $csv_file = $form_state->getValue('csv_file'); $csv_file = reset($csv_file); $file = File::load($csv_file); $data = $this->csvtoarray($file->getFileUri(), ','); foreach ($data as $row) { $operations[] = ['\Drupal\csv_import\Form\CSVImportForm::addImportContentItem', [$row]]; } $batch = [ 'title' => $this->t('Importing data...'), 'operations' => $operations, 'init_message' => $this->t('Import is starting.'), 'finished' => '\Drupal\csv_import\Form\CSVImportForm::addImportContentItemCallback', ]; batch_set($batch); $this->messenger()->addMessage($this->t('Your form was submitted!')); } public function csvtoarray($filename='', $delimiter) { if (!file_exists($filename) || !is_readable($filename)) return FALSE; $header = NULL; if(($handle = fopen($filename, 'r')) !== FALSE) { while(($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) { if(!$header) { $header = $row; } else { $data[] = array_combine($header, $row); } } fclose($handle); } return $data; } public static function addImportContentItem($item, &$context) { $message = 'Creating ' . $item['Title']; $results = []; self::create_node($item); $context['message'] = $message; $context['results'] = $item; } public function addImportContentItemCallback($success, $results, $operations) { $number = count($results); if ($success) { $message = new PluralTranslatableMarkup($number, 'One item processed.','@count items processed.'); } else { $message = t('Finished with an error.'); } \Drupal::messenger()->addMessage(t($message->render())); } public static function create_node($item) { $data = file_get_contents($item['Image']); $file = file_save_data($data, 'public://sample.png', \Drupal\Core\File\FileSystemInterface::EXISTS_RENAME); $nodes = [ 'type' => 'articles_about_programming', 'title' => $item['Title'], 'field_description' => $item['Description'], 'field_myimage' => [ 'target_id' => $file->id(), 'alt' => 'Sample', 'title' => 'Sample file', ], 'field_link_to_website' => [ 'uri' => 'https://www.' . $item['Link to website'], 'title' => $item['Title'], 'options' => ['target' => '_blank'], ], ]; $node = Node::create($nodes); $node->setPublished(TRUE); $node->save(); } }
// If we want to use it as a dependency injection (we should), // than this is the right way. /** * Logger interface. * * @var \Psr\Log\LoggerInterface */ protected $logger; // After that we add it to constructor method. /** * Controller_name constructor * * @param \Psr\Log\LoggerInterface $logger * Logger interface. */ public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function someFunction(){ if (something) { // Line of code... } else { $this->logger->error('Error message'); } }
stormtextil_core.edifact_orders: path: '/cron/synchronize-edifact-orders' defaults: _controller: '\Drupal\stormtextil_synchronization\Controller\SynchronizeEdifactOrders::parse' _title: 'Edifact Parser' requirements: _permission: 'access content'
<?php namespace Drupal\stormtextil_config\Form; use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Link; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class StormTextil Config Form. */ class StormTextilConfigForm extends ConfigFormBase { /** * EntityTypeManagerInterface. * * @var \Drupal\Core\Entity\EntityTypeManagerInterface */ protected $entityTypeManager; /** * StormTextilConfigForm constructor. * * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager * The Entity Type Manager. */ public function __construct(EntityTypeManagerInterface $entityTypeManager) { $this->entityTypeManager = $entityTypeManager; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager') ); } /** * {@inheritdoc} */ public function getFormId() { return 'stormtextil_config.config_form'; } /** * {@inheritdoc} */ protected function getEditableConfigNames() { return ['stormtextil_config.settings']; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $config = $this->config('stormtextil_config.settings'); // Promotions e-mail. $form['promotions_email'] = [ '#type' => 'details', '#title' => $this->t('Promotions in Order e-mail'), '#description' => $this->t('Add custom promotional text into order confirmation e-mail'), '#open' => FALSE, '#tree' => TRUE, ]; $promotions_email = $config->get('promotions_email'); $form['promotions_email']['enabled'] = [ '#type' => 'checkbox', '#title' => $this->t('Enable promotions'), '#default_value' => isset($promotions_email['enabled']) ? $promotions_email['enabled'] : '', ]; $form['promotions_email']['EN'] = [ '#type' => 'text_format', '#title' => $this->t('Text - en'), '#format' => 'full_html', '#default_value' => isset($promotions_email['EN']['value']) ? $promotions_email['EN']['value'] : '', ]; $form['promotions_email']['DA'] = [ '#type' => 'text_format', '#title' => $this->t('Text - da'), '#format' => 'full_html', '#default_value' => isset($promotions_email['DA']['value']) ? $promotions_email['DA']['value'] : '', ]; $form['promotions_email']['DE'] = [ '#type' => 'text_format', '#title' => $this->t('Text - de'), '#format' => 'full_html', '#default_value' => isset($promotions_email['DE']['value']) ? $promotions_email['DE']['value'] : '', ]; // Stock notify e-mail. $form['stock_notify_email'] = [ '#type' => 'details', '#title' => $this->t('Stock notify e-mail'), '#description' => $this->t('Add custom text into stock notify e-mail'), '#open' => FALSE, '#tree' => TRUE, ]; $stock_notify_email = $config->get('stock_notify_email'); $form['stock_notify_email']['en']['subject'] = [ '#type' => 'textfield', '#title' => $this->t('Subject - en'), '#default_value' => isset($stock_notify_email['en']['subject']) ? $stock_notify_email['en']['subject'] : '', '#size' => 50, ]; $form['stock_notify_email']['en']['message'] = [ '#type' => 'text_format', '#title' => $this->t('Text - en'), '#format' => 'full_html', '#default_value' => isset($stock_notify_email['en']['message']['value']) ? $stock_notify_email['en']['message']['value'] : '', ]; $form['stock_notify_email']['da']['subject'] = [ '#type' => 'textfield', '#title' => $this->t('Subject - da'), '#default_value' => isset($stock_notify_email['da']['subject']) ? $stock_notify_email['da']['subject'] : '', '#size' => 50, ]; $form['stock_notify_email']['da']['message'] = [ '#type' => 'text_format', '#title' => $this->t('Text - da'), '#format' => 'full_html', '#default_value' => isset($stock_notify_email['da']['message']['value']) ? $stock_notify_email['da']['message']['value'] : '', ]; $form['stock_notify_email']['de']['subject'] = [ '#type' => 'textfield', '#title' => $this->t('Subject - de'), '#default_value' => isset($stock_notify_email['de']['subject']) ? $stock_notify_email['de']['subject'] : '', '#size' => 50, ]; $form['stock_notify_email']['de']['message'] = [ '#type' => 'text_format', '#title' => $this->t('Text - de'), '#format' => 'full_html', '#default_value' => isset($stock_notify_email['de']['message']['value']) ? $stock_notify_email['de']['message']['value'] : '', ]; // Exchange rates. $form['exchange_rates'] = [ '#type' => 'details', '#title' => $this->t('Exchange rates'), '#description' => $this->t('Defines the exchange rate for 1 unit of the currency in DKK.'), '#open' => FALSE, '#tree' => TRUE, ]; $exchange_rates = $config->get('exchange_rates'); $form['exchange_rates']['EUR'] = [ '#type' => 'textfield', '#title' => $this->t('EUR to DKK'), '#default_value' => isset($exchange_rates['EUR']) ? $exchange_rates['EUR'] : '', '#size' => 10, ]; $form['exchange_rates']['SEK'] = [ '#type' => 'textfield', '#title' => $this->t('SEK to DKK'), '#default_value' => isset($exchange_rates['SEK']) ? $exchange_rates['SEK'] : '', '#size' => 10, ]; // Order fees. $form['order_fees'] = [ '#type' => 'details', '#title' => $this->t('Order fees'), '#open' => FALSE, '#tree' => TRUE, ]; $form['order_fees']['administration_fee'] = [ '#type' => 'details', '#title' => $this->t('Administration fees'), '#open' => FALSE, '#tree' => TRUE, ]; $administration_fee = $config->get('administration_fee'); $form['order_fees']['administration_fee']['DKK']['range'] = [ '#type' => 'textfield', '#title' => $this->t('Invoice total (DKK)'), '#default_value' => isset($administration_fee['DKK']['range']) ? $administration_fee['DKK']['range'] : '', '#size' => 10, ]; $form['order_fees']['administration_fee']['DKK']['fee'] = [ '#type' => 'textfield', '#title' => $this->t('Fee (DKK)'), '#default_value' => isset($administration_fee['DKK']['fee']) ? $administration_fee['DKK']['fee'] : '', '#size' => 10, ]; $form['order_fees']['administration_fee']['EUR']['range'] = [ '#type' => 'textfield', '#title' => $this->t('Invoice total (EUR)'), '#default_value' => isset($administration_fee['EUR']['range']) ? $administration_fee['EUR']['range'] : '', '#size' => 10, ]; $form['order_fees']['administration_fee']['EUR']['fee'] = [ '#type' => 'textfield', '#title' => $this->t('Fee (EUR)'), '#default_value' => isset($administration_fee['EUR']['fee']) ? $administration_fee['EUR']['fee'] : '', '#size' => 10, ]; $form['order_fees']['administration_fee']['SEK']['range'] = [ '#type' => 'textfield', '#title' => $this->t('Invoice total (SEK)'), '#default_value' => isset($administration_fee['SEK']['range']) ? $administration_fee['SEK']['range'] : '', '#size' => 10, ]; $form['order_fees']['administration_fee']['SEK']['fee'] = [ '#type' => 'textfield', '#title' => $this->t('Fee (SEK)'), '#default_value' => isset($administration_fee['SEK']['fee']) ? $administration_fee['SEK']['fee'] : '', '#size' => 10, ]; // Added costs. $form['order_fees']['added_cost'] = [ '#type' => 'textfield', '#title' => $this->t('Added cost price (DKK)'), '#default_value' => $config->get('added_cost'), '#size' => 10, ]; // VAT. $form['order_fees']['vat'] = [ '#type' => 'textfield', '#title' => $this->t('VAT (%)'), '#default_value' => $config->get('vat'), '#size' => 10, ]; // Balance is overdue notice. $form['balance_is_overdue'] = [ '#type' => 'details', '#title' => $this->t('Balance is overdue notification'), '#description' => $this->t('Add custom notification text for user with overdue balance'), '#open' => FALSE, '#tree' => TRUE, ]; $balance_is_overdue = $config->get('balance_is_overdue'); $form['balance_is_overdue']['enabled'] = [ '#type' => 'checkbox', '#title' => $this->t('Enable notifications'), '#default_value' => isset($balance_is_overdue['enabled']) ? $balance_is_overdue['enabled'] : '', ]; $form['balance_is_overdue']['EN'] = [ '#type' => 'text_format', '#title' => $this->t('Text - en'), '#format' => 'full_html', '#default_value' => isset($balance_is_overdue['EN']['value']) ? $balance_is_overdue['EN']['value'] : '', ]; $form['balance_is_overdue']['DA'] = [ '#type' => 'text_format', '#title' => $this->t('Text - da'), '#format' => 'full_html', '#default_value' => isset($balance_is_overdue['DA']['value']) ? $balance_is_overdue['DA']['value'] : '', ]; $form['balance_is_overdue']['DE'] = [ '#type' => 'text_format', '#title' => $this->t('Text - de'), '#format' => 'full_html', '#default_value' => isset($balance_is_overdue['DE']['value']) ? $balance_is_overdue['DE']['value'] : '', ]; // Edifact orders ftp connection. $form['edifact'] = [ '#type' => 'details', '#title' => $this->t('Ftp connection'), '#description' => $this->t('Configure ftp connection to remote server'), '#open' => FALSE, '#tree' => TRUE, ]; $ftp_connection = $config->get('edifact'); $form['edifact']['server'] = [ '#type' => 'textfield', '#title' => $this->t('Ftp server'), '#default_value' => isset($ftp_connection['server']) ? $ftp_connection['server'] : '', '#size' => 30, ]; $form['edifact']['username'] = [ '#type' => 'textfield', '#title' => $this->t('Username'), '#default_value' => isset($ftp_connection['username']) ? $ftp_connection['username'] : '', '#size' => 30, ]; $form['edifact']['password'] = [ '#type' => 'textfield', '#title' => $this->t('Password'), '#default_value' => isset($ftp_connection['password']) ? $ftp_connection['password'] : '', '#size' => 30, ]; // Samba connection. $form['samba'] = [ '#type' => 'details', '#title' => $this->t('Samba connection'), '#description' => $this->t('Configure connection to remote computer'), '#open' => FALSE, '#tree' => TRUE, ]; $samba = $config->get('samba'); $form['samba']['username'] = [ '#type' => 'textfield', '#title' => $this->t('Username'), '#default_value' => isset($samba['username']) ? $samba['username'] : '', '#size' => 30, ]; $form['samba']['password'] = [ '#type' => 'textfield', '#title' => $this->t('Password'), '#default_value' => isset($samba['password']) ? $samba['password'] : '', '#size' => 30, ]; $form['samba']['workgroup'] = [ '#type' => 'textfield', '#title' => $this->t('Workgroup'), '#default_value' => isset($samba['workgroup']) ? $samba['workgroup'] : '', '#size' => 30, ]; $form['samba']['pdf'] = [ '#type' => 'details', '#title' => $this->t('Order PDF files'), '#description' => $this->t('Configure connection to remote computer to synchronize PDF files'), '#open' => FALSE, '#tree' => TRUE, ]; $form['samba']['pdf']['host'] = [ '#type' => 'textfield', '#title' => $this->t('Host (IP address of remote computer)'), '#default_value' => isset($samba['pdf']['host']) ? $samba['pdf']['host'] : '', '#size' => 30, ]; $form['samba']['pdf']['share'] = [ '#type' => 'textfield', '#title' => $this->t('Shared folder'), '#default_value' => isset($samba['pdf']['share']) ? $samba['pdf']['share'] : '', '#size' => 30, ]; $form['samba']['invoice'] = [ '#type' => 'details', '#title' => $this->t('Order invoices'), '#description' => $this->t('Configure connection to remote computer to synchronize invoices'), '#open' => FALSE, '#tree' => TRUE, ]; $form['samba']['invoice']['host'] = [ '#type' => 'textfield', '#title' => $this->t('Host (IP address of remote computer)'), '#default_value' => isset($samba['invoice']['host']) ? $samba['invoice']['host'] : '', '#size' => 30, ]; $form['samba']['invoice']['share'] = [ '#type' => 'textfield', '#title' => $this->t('Shared folder'), '#default_value' => isset($samba['invoice']['share']) ? $samba['invoice']['share'] : '', '#size' => 30, ]; // Samba connection. $form['theme'] = [ '#type' => 'details', '#title' => $this->t('Theme settings'), '#description' => $this->t('Configure theme specific variables'), '#open' => FALSE, '#tree' => TRUE, ]; $theme = $config->get('theme'); $form['theme']['theme_color'] = [ '#type' => 'textfield', '#title' => $this->t('Theme color'), '#default_value' => isset($theme[