/** * Returns an array of route objects. * * @return \Symfony\Component\Routing\Route[] * An array of route objects. */ public function routes() { $routes = array(); $is_multilingual = $this->languageManager->isMultilingual(); /* @var $search_api_page \Drupal\search_api_page\SearchApiPageInterface */ foreach ($this->entityManager->getStorage('search_api_page')->loadMultiple() as $search_api_page) { // Default path. $default_path = $search_api_page->getPath(); // Loop over all languages so we can get the translated path (if any). foreach ($this->languageManager->getLanguages() as $language) { // Check if we are multilingual or not. if ($is_multilingual) { $path = $this->languageManager->getLanguageConfigOverride($language->getId(), 'search_api_page.search_api_page.' . $search_api_page->id())->get('path'); } if (empty($path)) { $path = $default_path; } $args = ['_controller' => 'Drupal\\search_api_page\\Controller\\SearchApiPageController::page', 'search_api_page_name' => $search_api_page->id()]; // Use clean urls or not. if ($search_api_page->getCleanUrl()) { $path .= '/{keys}'; $args['keys'] = ''; } $routes['search_api_page.' . $language->getId() . '.' . $search_api_page->id()] = new Route($path, $args, array('_permission' => 'view search api pages')); } } return $routes; }
/** * Checks translation access for the entity and operation on the given route. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The parametrized route. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * @param string $source * (optional) For a create operation, the language code of the source. * @param string $target * (optional) For a create operation, the language code of the translation. * @param string $language * (optional) For an update or delete operation, the language code of the * translation being updated or deleted. * @param string $entity_type_id * (optional) The entity type ID. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL, $entity_type_id = NULL) { /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if ($entity = $route_match->getParameter($entity_type_id)) { if ($account->hasPermission('translate any entity')) { return AccessResult::allowed()->cachePerRole(); } $operation = $route->getRequirement('_access_content_translation_manage'); /* @var \Drupal\content_translation\ContentTranslationHandlerInterface $handler */ $handler = $this->entityManager->getHandler($entity->getEntityTypeId(), 'translation'); // Load translation. $translations = $entity->getTranslationLanguages(); $languages = $this->languageManager->getLanguages(); switch ($operation) { case 'create': $source_language = $this->languageManager->getLanguage($source) ?: $entity->language(); $target_language = $this->languageManager->getLanguage($target) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); $is_new_translation = $source_language->getId() != $target_language->getId() && isset($languages[$source_language->getId()]) && isset($languages[$target_language->getId()]) && !isset($translations[$target_language->getId()]); return AccessResult::allowedIf($is_new_translation)->cachePerRole()->cacheUntilEntityChanges($entity)->andIf($handler->getTranslationAccess($entity, $operation)); case 'update': case 'delete': $language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); $has_translation = isset($languages[$language->getId()]) && $language->getId() != $entity->getUntranslated()->language()->getId() && isset($translations[$language->getId()]); return AccessResult::allowedIf($has_translation)->cachePerRole()->cacheUntilEntityChanges($entity)->andIf($handler->getTranslationAccess($entity, $operation)); } } // No opinion. return AccessResult::neutral(); }
/** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { $languages = $this->languageManager->getLanguages(); // Count repeated values for uniqueness check. $count = array_count_values($form_state->getValue('prefix')); $default_langcode = $this->config('language.negotiation')->get('selected_langcode'); if ($default_langcode == LanguageInterface::LANGCODE_SITE_DEFAULT) { $default_langcode = $this->languageManager->getDefaultLanguage()->getId(); } foreach ($languages as $langcode => $language) { $value = $form_state->getValue(array('prefix', $langcode)); if ($value === '') { if (!($default_langcode == $langcode) && $form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) { // Throw a form error if the prefix is blank for a non-default language, // although it is required for selected negotiation type. $form_state->setErrorByName("prefix][{$langcode}", $this->t('The prefix may only be left blank for the <a href=":url">selected detection fallback language.</a>', [':url' => $this->getUrlGenerator()->generate('language.negotiation_selected')])); } } elseif (strpos($value, '/') !== FALSE) { // Throw a form error if the string contains a slash, // which would not work. $form_state->setErrorByName("prefix][{$langcode}", $this->t('The prefix may not contain a slash.')); } elseif (isset($count[$value]) && $count[$value] > 1) { // Throw a form error if there are two languages with the same // domain/prefix. $form_state->setErrorByName("prefix][{$langcode}", $this->t('The prefix for %language, %value, is not unique.', array('%language' => $language->getName(), '%value' => $value))); } } // Count repeated values for uniqueness check. $count = array_count_values($form_state->getValue('domain')); foreach ($languages as $langcode => $language) { $value = $form_state->getValue(array('domain', $langcode)); if ($value === '') { if ($form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_DOMAIN) { // Throw a form error if the domain is blank for a non-default language, // although it is required for selected negotiation type. $form_state->setErrorByName("domain][{$langcode}", $this->t('The domain may not be left blank for %language.', array('%language' => $language->getName()))); } } elseif (isset($count[$value]) && $count[$value] > 1) { // Throw a form error if there are two languages with the same // domain/domain. $form_state->setErrorByName("domain][{$langcode}", $this->t('The domain for %language, %value, is not unique.', array('%language' => $language->getName(), '%value' => $value))); } } // Domain names should not contain protocol and/or ports. foreach ($languages as $langcode => $language) { $value = $form_state->getValue(array('domain', $langcode)); if (!empty($value)) { // Ensure we have exactly one protocol when checking the hostname. $host = 'http://' . str_replace(array('http://', 'https://'), '', $value); if (parse_url($host, PHP_URL_HOST) != $value) { $form_state->setErrorByName("domain][{$langcode}", $this->t('The domain for %language may only contain the domain name, not a trailing slash, protocol and/or port.', ['%language' => $language->getName()])); } } } parent::validateForm($form, $form_state); }
/** * {@inheritdoc} */ public function importAll() { $address_formats = $this->externalRepository->getAll(); $country_codes = array_keys($address_formats); // It's nicer API-wise to just pass the country codes. // The external repository maintains a static cache, so the repeated ->get() // calls have minimal performance impact. $this->importEntities($country_codes); if ($this->languageManager->isMultilingual()) { $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_CONFIGURABLE); $this->importTranslations(array_keys($languages)); } }
/** * {@inheritdoc} */ public function summary() { $language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); $selected = $this->configuration['langcodes']; // Reduce the language list to an array of language names. $language_names = array_reduce($language_list, function (&$result, $item) use($selected) { // If the current item of the $language_list array is one of the selected // languages, add it to the $results array. if (!empty($selected[$item->getId()])) { $result[$item->getId()] = $item->getName(); } return $result; }, array()); // If we have more than one language selected, separate them by commas. if (count($this->configuration['langcodes']) > 1) { $languages = implode(', ', $language_names); } else { // If we have just one language just grab the only present value. $languages = array_pop($language_names); } if (!empty($this->configuration['negate'])) { return t('The language is not @languages.', array('@languages' => $languages)); } return t('The language is @languages.', array('@languages' => $languages)); }
/** * {@inheritdoc} */ public function import($currencyCode) { if ($existingEntity = $this->storage->load($currencyCode)) { // Pretend the currency was just imported. return $existingEntity; } $defaultLangcode = $this->languageManager->getDefaultLanguage()->getId(); $currency = $this->externalRepository->get($currencyCode, $defaultLangcode, 'en'); $values = [ 'langcode' => $defaultLangcode, 'currencyCode' => $currency->getCurrencyCode(), 'name' => $currency->getName(), 'numericCode' => $currency->getNumericCode(), 'symbol' => $currency->getSymbol(), 'fractionDigits' => $currency->getFractionDigits(), ]; $entity = $this->storage->create($values); $entity->trustData()->save(); if ($this->languageManager->isMultilingual()) { // Import translations for any additional languages the site has. $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_CONFIGURABLE); $languages = array_diff_key($languages, [$defaultLangcode => $defaultLangcode]); $langcodes = array_map(function ($language) { return $language->getId(); }, $languages); $this->importEntityTranslations($entity, $langcodes); } return $entity; }
/** * {@inheritdoc} */ public function validateDrushParams($args) { $add_language = drush_get_option('languages'); if (!empty($add_language)) { $add_language = explode(',', str_replace(' ', '', $add_language)); // Intersect with the enabled languages to make sure the language args // passed are actually enabled. $values['values']['add_language'] = array_intersect($add_language, array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL))); } $values['kill'] = drush_get_option('kill'); $values['title_length'] = 6; $values['num'] = array_shift($args); $values['max_comments'] = array_shift($args); $all_types = array_keys(node_type_get_names()); $default_types = array_intersect(array('page', 'article'), $all_types); $selected_types = _convert_csv_to_array(drush_get_option('types', $default_types)); if (empty($selected_types)) { return drush_set_error('DEVEL_GENERATE_NO_CONTENT_TYPES', dt('No content types available')); } $values['node_types'] = array_combine($selected_types, $selected_types); $node_types = array_filter($values['node_types']); if (!empty($values['kill']) && empty($node_types)) { return drush_set_error('DEVEL_GENERATE_INVALID_INPUT', dt('Please provide content type (--types) in which you want to delete the content.')); } return $values; }
/** * {@inheritdoc} */ public function searchFormAlter(array &$form, FormStateInterface $form_state) { // Add advanced search keyword-related boxes. $form['advanced'] = array('#type' => 'details', '#title' => t('Advanced search'), '#attributes' => array('class' => array('search-advanced')), '#access' => $this->account && $this->account->hasPermission('use advanced search')); $form['advanced']['keywords-fieldset'] = array('#type' => 'fieldset', '#title' => t('Keywords')); $form['advanced']['keywords'] = array('#prefix' => '<div class="criterion">', '#suffix' => '</div>'); $form['advanced']['keywords-fieldset']['keywords']['or'] = array('#type' => 'textfield', '#title' => t('Containing any of the words'), '#size' => 30, '#maxlength' => 255); $form['advanced']['keywords-fieldset']['keywords']['phrase'] = array('#type' => 'textfield', '#title' => t('Containing the phrase'), '#size' => 30, '#maxlength' => 255); $form['advanced']['keywords-fieldset']['keywords']['negative'] = array('#type' => 'textfield', '#title' => t('Containing none of the words'), '#size' => 30, '#maxlength' => 255); // Add node types. $types = array_map(array('\\Drupal\\Component\\Utility\\String', 'checkPlain'), node_type_get_names()); $form['advanced']['types-fieldset'] = array('#type' => 'fieldset', '#title' => t('Types')); $form['advanced']['types-fieldset']['type'] = array('#type' => 'checkboxes', '#title' => t('Only of the type(s)'), '#prefix' => '<div class="criterion">', '#suffix' => '</div>', '#options' => $types); $form['advanced']['submit'] = array('#type' => 'submit', '#value' => t('Advanced search'), '#prefix' => '<div class="action">', '#suffix' => '</div>', '#weight' => 100); // Add languages. $language_options = array(); $language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); foreach ($language_list as $langcode => $language) { // Make locked languages appear special in the list. $language_options[$langcode] = $language->isLocked() ? t('- @name -', array('@name' => $language->getName())) : $language->getName(); } if (count($language_options) > 1) { $form['advanced']['lang-fieldset'] = array('#type' => 'fieldset', '#title' => t('Languages')); $form['advanced']['lang-fieldset']['language'] = array('#type' => 'checkboxes', '#title' => t('Languages'), '#prefix' => '<div class="criterion">', '#suffix' => '</div>', '#options' => $language_options); } }
/** * {@inheritdoc} */ protected function viewValue(FieldItemInterface $item) { // The 'languages' cache context is not necessary because the language is // either displayed in its configured form (loaded directly from config // storage by LanguageManager::getLanguages()) or in its native language // name. That only depends on formatter settings and no language condition. $languages = $this->getSetting('native_language') ? $this->languageManager->getNativeLanguages(LanguageInterface::STATE_ALL) : $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); return ['#plain_text' => $item->language && isset($languages[$item->language->getId()]) ? $languages[$item->language->getId()]->getName() : '']; }
/** * Form submission handler for ContentTranslationHandler::entityFormAlter(). * * Takes care of the source language change. */ public function entityFormSourceChange($form, FormStateInterface $form_state) { $form_object = $form_state->getFormObject(); $entity = $form_object->getEntity(); $source = $form_state->getValue(array('source_langcode', 'source')); $entity_type_id = $entity->getEntityTypeId(); $form_state->setRedirect('content_translation.translation_add_' . $entity_type_id, array($entity_type_id => $entity->id(), 'source' => $source, 'target' => $form_object->getFormLangcode($form_state))); $languages = $this->languageManager->getLanguages(); drupal_set_message(t('Source language set to: %language', array('%language' => $languages[$source]->getName()))); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class); $this->moduleHandler->getImplementations('entity_type_build')->willReturn([]); $this->moduleHandler->alter('entity_type', Argument::type('array'))->willReturn(NULL); $this->cacheBackend = $this->prophesize(CacheBackendInterface::class); $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); $this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class); $language = new Language(['id' => 'en']); $this->languageManager = $this->prophesize(LanguageManagerInterface::class); $this->languageManager->getCurrentLanguage()->willReturn($language); $this->languageManager->getLanguages()->willReturn(['en' => (object) ['id' => 'en']]); $this->typedDataManager = $this->prophesize(TypedDataManagerInterface::class); $this->cacheBackend = $this->prophesize(CacheBackendInterface::class); $container = $this->prophesize(ContainerInterface::class); $container->get('cache_tags.invalidator')->willReturn($this->cacheTagsInvalidator->reveal()); //$container->get('typed_data_manager')->willReturn($this->typedDataManager->reveal()); \Drupal::setContainer($container->reveal()); $this->entityTypeBundleInfo = new EntityTypeBundleInfo($this->entityTypeManager->reveal(), $this->languageManager->reveal(), $this->moduleHandler->reveal(), $this->typedDataManager->reveal(), $this->cacheBackend->reveal()); }
/** * {@inheritdoc} */ public function setUp() { parent::setup(); require_once $this->root . '/core/includes/entity.inc'; $this->namespaces['Drupal\\Core\\Entity'] = $this->root . '/core/lib/Drupal/Core/Entity'; $language = $this->prophesize(LanguageInterface::class); $language->getId()->willReturn('en'); $this->languageManager = $this->prophesize(LanguageManagerInterface::class); $this->languageManager->getCurrentLanguage()->willReturn($language->reveal()); $this->languageManager->getLanguages()->willReturn([$language->reveal()]); // We need to support multiple entity types, including a test type: $type_info = ['test' => ['id' => 'test', 'label' => 'Test', 'entity_keys' => ['bundle' => 'bundle']], 'user' => ['id' => 'user', 'label' => 'Test User', 'entity_keys' => ['bundle' => 'user']], 'node' => ['id' => 'node', 'label' => 'Test Node', 'entity_keys' => ['bundle' => 'dummy']]]; $type_array = []; foreach ($type_info as $type => $info) { $entity_type = new ContentEntityType($info); $type_array[$type] = $entity_type; $this->entityTypeManager->getDefinition($type)->willReturn($entity_type); $this->entityManager->getDefinition($type)->willReturn($entity_type); } // We need a user_role mock as well. $role_entity_info = ['id' => 'user_role', 'label' => 'Test Role']; $role_type = new ConfigEntityType($role_entity_info); $type_array['user_role'] = $role_type; $this->entityTypeManager->getDefinitions()->willReturn($type_array); $this->entityManager->getDefinitions()->willReturn($type_array); $this->entityAccess = $this->prophesize(EntityAccessControlHandlerInterface::class); $this->entityTypeManager->getAccessControlHandler(Argument::any())->willReturn($this->entityAccess->reveal()); // The base field definitions for our test entity aren't used, and would // require additional mocking. It doesn't appear that any of our tests rely // on this for any other entity type that we are mocking. $this->entityFieldManager->getBaseFieldDefinitions(Argument::any())->willReturn([]); $this->entityManager->getBaseFieldDefinitions(Argument::any())->willReturn([]); // Return some dummy bundle information for now, so that the entity manager // does not call out to the config entity system to get bundle information. $this->entityTypeBundleInfo->getBundleInfo(Argument::any())->willReturn(['test' => ['label' => 'Test']]); $this->entityManager->getBundleInfo(Argument::any())->willReturn(['test' => ['label' => 'Test']]); $this->moduleHandler->getImplementations('entity_type_build')->willReturn([]); $this->fieldTypeManager = new FieldTypePluginManager($this->namespaces, $this->cacheBackend, $this->moduleHandler->reveal(), $this->typedDataManager); $this->container->set('plugin.manager.field.field_type', $this->fieldTypeManager); }
/** * {@inheritdoc} */ public function setUp() { parent::setup(); require_once $this->root . '/core/includes/entity.inc'; $this->namespaces['Drupal\\Core\\Entity'] = $this->root . '/core/lib/Drupal/Core/Entity'; $language = $this->prophesize(LanguageInterface::class); $language->getId()->willReturn('en'); $this->languageManager = $this->prophesize(LanguageManagerInterface::class); $this->languageManager->getCurrentLanguage()->willReturn($language->reveal()); $this->languageManager->getLanguages()->willReturn([$language->reveal()]); $entityType = new ContentEntityType(['id' => 'test', 'label' => 'Test', 'entity_keys' => ['bundle' => 'bundle']]); $this->entityManager->getDefinitions()->willReturn(['test' => $entityType]); $this->entityAccess = $this->prophesize(EntityAccessControlHandlerInterface::class); $this->entityManager->getAccessControlHandler(Argument::any())->willReturn($this->entityAccess->reveal()); // The base field definitions for our test entity aren't used, and would // require additional mocking. $this->entityManager->getBaseFieldDefinitions('test')->willReturn([]); // Return some dummy bundle information for now, so that the entity manager // does not call out to the config entity system to get bundle information. $this->entityManager->getBundleInfo(Argument::any())->willReturn(['test' => ['label' => 'Test']]); $this->moduleHandler->getImplementations('entity_type_build')->willReturn([]); }
/** * {@inheritDoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $options = []; foreach ($this->manager->getDefinitions() as $plugin_id => $plugin_definition) { $options[$plugin_id] = $plugin_definition['label']; } $form['type'] = ['#type' => 'select', '#title' => $this->t('Pattern type'), '#default_value' => $this->entity->getType(), '#options' => $options, '#required' => TRUE, '#limit_validation_errors' => array(array('type')), '#submit' => array('::submitSelectType'), '#executes_submit_callback' => TRUE, '#ajax' => array('callback' => '::ajaxReplacePatternForm', 'wrapper' => 'pathauto-pattern', 'method' => 'replace')]; $form['pattern_container'] = ['#type' => 'container', '#prefix' => '<div id="pathauto-pattern">', '#suffix' => '</div>']; // if there is no type yet, stop here. if ($this->entity->getType()) { $alias_type = $this->entity->getAliasType(); $form['pattern_container']['pattern'] = array('#type' => 'textfield', '#title' => 'Path pattern', '#default_value' => $this->entity->getPattern(), '#size' => 65, '#maxlength' => 1280, '#element_validate' => array('token_element_validate', 'pathauto_pattern_validate'), '#after_build' => array('token_element_validate'), '#token_types' => $alias_type->getTokenTypes(), '#min_tokens' => 1); // Show the token help relevant to this pattern type. $form['pattern_container']['token_help'] = array('#theme' => 'token_tree_link', '#token_types' => $alias_type->getTokenTypes()); // Expose bundle and language conditions. if ($alias_type->getDerivativeId() && ($entity_type = $this->entityTypeManager->getDefinition($alias_type->getDerivativeId()))) { $default_bundles = []; $default_languages = []; foreach ($this->entity->getSelectionConditions() as $condition_id => $condition) { if (in_array($condition->getPluginId(), ['entity_bundle:' . $entity_type->id(), 'node_type'])) { $default_bundles = $condition->getConfiguration()['bundles']; } elseif ($condition->getPluginId() == 'language') { $default_languages = $condition->getConfiguration()['langcodes']; } } if ($entity_type->hasKey('bundle') && ($bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type->id()))) { $bundle_options = []; foreach ($bundles as $id => $info) { $bundle_options[$id] = $info['label']; } $form['pattern_container']['bundles'] = array('#title' => $entity_type->getBundleLabel(), '#type' => 'checkboxes', '#options' => $bundle_options, '#default_value' => $default_bundles, '#description' => t('Check to which types this pattern should be applied. Leave empty to allow any.')); } if ($this->languageManager->isMultilingual() && $entity_type->isTranslatable()) { $language_options = []; foreach ($this->languageManager->getLanguages() as $id => $language) { $language_options[$id] = $language->getName(); } $form['pattern_container']['languages'] = array('#title' => $this->t('Languages'), '#type' => 'checkboxes', '#options' => $language_options, '#default_value' => $default_languages, '#description' => t('Check to which languages this pattern should be applied. Leave empty to allow any.')); } } } $form['label'] = array('#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => $this->entity->label(), '#required' => TRUE); $form['id'] = array('#type' => 'machine_name', '#title' => $this->t('ID'), '#maxlength' => 255, '#default_value' => $this->entity->id(), '#required' => TRUE, '#disabled' => !$this->entity->isNew(), '#machine_name' => array('exists' => 'Drupal\\pathauto\\Entity\\PathautoPattern::load')); $form['status'] = ['#title' => $this->t('Enabled'), '#type' => 'checkbox', '#default_value' => $this->entity->status()]; return parent::buildForm($form, $form_state); }
/** * {@inheritdoc} */ public function getPatterns() { $patterns = []; $languages = $this->languageManager->getLanguages(); if ($this->entityManager->getDefinition($this->getEntityTypeId())->hasKey('bundle')) { foreach ($this->getBundles() as $bundle => $bundle_label) { if (count($languages) && $this->isContentTranslationEnabled($bundle)) { $patterns[$bundle] = $this->t('Default path pattern for @bundle (applies to all @bundle fields with blank patterns below)', array('@bundle' => $bundle_label)); foreach ($languages as $language) { $patterns[$bundle . '_' . $language->getId()] = $this->t('Pattern for all @language @bundle paths', array('@bundle' => $bundle_label, '@language' => $language->getName())); } } else { $patterns[$bundle] = $this->t('Pattern for all @bundle paths', array('@bundle' => $bundle_label)); } } } return $patterns; }
/** * Checks translation access for the entity and operation on the given route. * * @param \Symfony\Component\Routing\Route $route * The route to check against. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The parametrized route. * @param \Drupal\Core\Session\AccountInterface $account * The currently logged in account. * @param string $source * (optional) For a create operation, the language code of the source. * @param string $target * (optional) For a create operation, the language code of the translation. * @param string $language * (optional) For an update or delete operation, the language code of the * translation being updated or deleted. * @param string $entity_type_id * (optional) The entity type ID. * * @return \Drupal\Core\Access\AccessResultInterface * The access result. */ public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL, $entity_type_id = NULL) { /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */ if ($entity = $route_match->getParameter($entity_type_id)) { $operation = $route->getRequirement('_access_content_translation_manage'); $language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); $entity_type = $this->entityManager->getDefinition($entity_type_id); if (in_array($operation, ['update', 'delete'])) { // Translation operations cannot be performed on the default // translation. if ($language->getId() == $entity->getUntranslated()->language()->getId()) { return AccessResult::forbidden()->addCacheableDependency($entity); } // Editors have no access to the translation operations, as entity // access already grants them an equal or greater access level. $templates = ['update' => 'edit-form', 'delete' => 'delete-form']; if ($entity->access($operation) && $entity_type->hasLinkTemplate($templates[$operation])) { return AccessResult::forbidden()->cachePerPermissions(); } } if ($account->hasPermission('translate any entity')) { return AccessResult::allowed()->cachePerPermissions(); } /* @var \Drupal\content_translation\ContentTranslationHandlerInterface $handler */ $handler = $this->entityManager->getHandler($entity->getEntityTypeId(), 'translation'); // Load translation. $translations = $entity->getTranslationLanguages(); $languages = $this->languageManager->getLanguages(); switch ($operation) { case 'create': $source_language = $this->languageManager->getLanguage($source) ?: $entity->language(); $target_language = $this->languageManager->getLanguage($target) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); $is_new_translation = $source_language->getId() != $target_language->getId() && isset($languages[$source_language->getId()]) && isset($languages[$target_language->getId()]) && !isset($translations[$target_language->getId()]); return AccessResult::allowedIf($is_new_translation)->cachePerPermissions()->addCacheableDependency($entity)->andIf($handler->getTranslationAccess($entity, $operation)); case 'delete': case 'update': $has_translation = isset($languages[$language->getId()]) && $language->getId() != $entity->getUntranslated()->language()->getId() && isset($translations[$language->getId()]); return AccessResult::allowedIf($has_translation)->cachePerPermissions()->addCacheableDependency($entity)->andIf($handler->getTranslationAccess($entity, $operation)); } } // No opinion. return AccessResult::neutral(); }
/** * {@inheritdoc} */ public function validateDrushParams($args) { $add_language = drush_get_option('languages'); if (!empty($add_language)) { $add_language = explode(',', str_replace(' ', '', $add_language)); // Intersect with the enabled languages to make sure the language args // passed are actually enabled. $values['values']['add_language'] = array_intersect($add_language, array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL))); } $values['kill'] = drush_get_option('kill'); $values['title_length'] = drush_get_option('title_length', 6); $values['num'] = array_shift($args); $selected_bundles = _convert_csv_to_array(drush_get_option('bundles', [])); if (empty($selected_bundles)) { return drush_set_error('DEVEL_GENERATE_NO_MEDIA_BUNDLES', dt('No media bundles available')); } $values['media_bundles'] = array_combine($selected_bundles, $selected_bundles); return $values; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // If template is required, language code is not given. if ($form_state->getValue('langcode') != LanguageInterface::LANGCODE_SYSTEM) { $language = $this->languageManager->getLanguage($form_state->getValue('langcode')); } else { $language = NULL; } $content_options = $form_state->getValue('content_options', array()); $reader = new PoDatabaseReader(); $language_name = ''; if ($language != NULL) { $reader->setLangcode($language->getId()); $reader->setOptions($content_options); $languages = $this->languageManager->getLanguages(); $language_name = isset($languages[$language->getId()]) ? $languages[$language->getId()]->getName() : ''; $filename = $language->getId() . '.po'; } else { // Template required. $filename = 'drupal.pot'; } $item = $reader->readItem(); if (!empty($item)) { $uri = tempnam('temporary://', 'po_'); $header = $reader->getHeader(); $header->setProjectName($this->config('system.site')->get('name')); $header->setLanguageName($language_name); $writer = new PoStreamWriter(); $writer->setUri($uri); $writer->setHeader($header); $writer->open(); $writer->writeItem($item); $writer->writeItems($reader); $writer->close(); $response = new BinaryFileResponse($uri); $response->setContentDisposition('attachment', $filename); $form_state->setResponse($response); } else { drupal_set_message($this->t('Nothing to export.')); } }
/** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { $form['kill'] = array('#type' => 'checkbox', '#title' => $this->t('<strong>Delete all products</strong> before generating new.'), '#default_value' => $this->getSetting('kill')); $form['num'] = array('#type' => 'number', '#title' => $this->t('How many products would you like to generate?'), '#default_value' => $this->getSetting('num'), '#required' => TRUE, '#min' => 0); $form['title_length'] = array('#type' => 'number', '#title' => $this->t('Maximum number of characters in titles'), '#default_value' => $this->getSetting('title_length'), '#required' => TRUE, '#min' => 1, '#max' => 255); $form['num_var'] = array('#type' => 'number', '#title' => $this->t('How many variations of products would you like to generate?'), '#default_value' => $this->getSetting('num_var'), '#required' => TRUE, '#min' => 0); $form['title_var_length'] = array('#type' => 'number', '#title' => $this->t("Maximum number of characters in variation's titles"), '#default_value' => $this->getSetting('title_var_length'), '#required' => FALSE, '#min' => 1, '#max' => 255); $form['amount'] = array('#type' => 'fieldset', '#title' => t('Amount')); $form['amount']['price_min'] = array('#type' => 'number', '#title' => $this->t('Minimum of variations price to generate?'), '#default_value' => $this->getSetting('price_min'), '#min' => 0); $form['amount']['price_max'] = array('#type' => 'number', '#title' => $this->t('Maximum of variations price to generate?'), '#default_value' => $this->getSetting('price_max'), '#min' => 0); $currency_repository = new CurrencyRepository(); $options = $currency_repository->getList(); $form['amount']['currency'] = array('#type' => 'select', '#title' => $this->t('Set currency'), '#options' => $options); // We always need a language. $options = array(); $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); foreach ($languages as $langcode => $language) { $options[$langcode] = $language->getName(); } $form['add_language'] = array('#type' => 'select', '#title' => $this->t('Set language on products'), '#multiple' => TRUE, '#description' => $this->t('Requires locale.module'), '#options' => $options, '#default_value' => array($this->languageManager->getDefaultLanguage()->getId())); $form['#redirect'] = FALSE; return $form; }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->container = $this->prophesize(ContainerInterface::class); \Drupal::setContainer($this->container->reveal()); $this->typedDataManager = $this->prophesize(TypedDataManagerInterface::class); $this->typedDataManager->getDefinition('field_item:boolean')->willReturn(['class' => BooleanItem::class]); $this->container->get('typed_data_manager')->willReturn($this->typedDataManager->reveal()); $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class); $this->moduleHandler->alter('entity_base_field_info', Argument::type('array'), Argument::any())->willReturn(NULL); $this->moduleHandler->alter('entity_bundle_field_info', Argument::type('array'), Argument::any(), Argument::type('string'))->willReturn(NULL); $this->cacheBackend = $this->prophesize(CacheBackendInterface::class); $this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class); $language = new Language(['id' => 'en']); $this->languageManager = $this->prophesize(LanguageManagerInterface::class); $this->languageManager->getCurrentLanguage()->willReturn($language); $this->languageManager->getLanguages()->willReturn(['en' => (object) ['id' => 'en']]); $this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class); $this->entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); $this->entityTypeRepository = $this->prophesize(EntityTypeRepositoryInterface::class); $this->entityTypeBundleInfo = $this->prophesize(EntityTypeBundleInfoInterface::class); $this->entityDisplayRepository = $this->prophesize(EntityDisplayRepositoryInterface::class); $this->entityFieldManager = new TestEntityFieldManager($this->entityTypeManager->reveal(), $this->entityTypeBundleInfo->reveal(), $this->entityDisplayRepository->reveal(), $this->typedDataManager->reveal(), $this->languageManager->reveal(), $this->keyValueFactory->reveal(), $this->moduleHandler->reveal(), $this->cacheBackend->reveal()); }
/** * {@inheritdoc} */ public function searchFormAlter(array &$form, FormStateInterface $form_state) { $parameters = $this->getParameters(); $keys = $this->getKeywords(); $used_advanced = !empty($parameters[self::ADVANCED_FORM]); if ($used_advanced) { $f = isset($parameters['f']) ? (array) $parameters['f'] : array(); $defaults = $this->parseAdvancedDefaults($f, $keys); } else { $defaults = array('keys' => $keys); } $form['basic']['keys']['#default_value'] = $defaults['keys']; // Add advanced search keyword-related boxes. $form['advanced'] = array('#type' => 'details', '#title' => t('Advanced search'), '#attributes' => array('class' => array('search-advanced')), '#access' => $this->account && $this->account->hasPermission('use advanced search'), '#open' => $used_advanced); $form['advanced']['keywords-fieldset'] = array('#type' => 'fieldset', '#title' => t('Keywords')); $form['advanced']['keywords'] = array('#prefix' => '<div class="criterion">', '#suffix' => '</div>'); $form['advanced']['keywords-fieldset']['keywords']['or'] = array('#type' => 'textfield', '#title' => t('Containing any of the words'), '#size' => 30, '#maxlength' => 255, '#default_value' => isset($defaults['or']) ? $defaults['or'] : ''); $form['advanced']['keywords-fieldset']['keywords']['phrase'] = array('#type' => 'textfield', '#title' => t('Containing the phrase'), '#size' => 30, '#maxlength' => 255, '#default_value' => isset($defaults['phrase']) ? $defaults['phrase'] : ''); $form['advanced']['keywords-fieldset']['keywords']['negative'] = array('#type' => 'textfield', '#title' => t('Containing none of the words'), '#size' => 30, '#maxlength' => 255, '#default_value' => isset($defaults['negative']) ? $defaults['negative'] : ''); // Add node types. $types = array_map(array('\\Drupal\\Component\\Utility\\SafeMarkup', 'checkPlain'), node_type_get_names()); $form['advanced']['types-fieldset'] = array('#type' => 'fieldset', '#title' => t('Types')); $form['advanced']['types-fieldset']['type'] = array('#type' => 'checkboxes', '#title' => t('Only of the type(s)'), '#prefix' => '<div class="criterion">', '#suffix' => '</div>', '#options' => $types, '#default_value' => isset($defaults['type']) ? $defaults['type'] : array()); $form['advanced']['submit'] = array('#type' => 'submit', '#value' => t('Advanced search'), '#prefix' => '<div class="action">', '#suffix' => '</div>', '#weight' => 100); // Add languages. $language_options = array(); $language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); foreach ($language_list as $langcode => $language) { // Make locked languages appear special in the list. $language_options[$langcode] = $language->isLocked() ? t('- @name -', array('@name' => $language->getName())) : $language->getName(); } if (count($language_options) > 1) { $form['advanced']['lang-fieldset'] = array('#type' => 'fieldset', '#title' => t('Languages')); $form['advanced']['lang-fieldset']['language'] = array('#type' => 'checkboxes', '#title' => t('Languages'), '#prefix' => '<div class="criterion">', '#suffix' => '</div>', '#options' => $language_options, '#default_value' => isset($defaults['language']) ? $defaults['language'] : array()); } }
/** * Lists locale translation filters that can be applied. */ protected function translateFilters() { $filters = array(); // Get all languages, except English. $this->languageManager->reset(); $languages = $this->languageManager->getLanguages(); $language_options = array(); foreach ($languages as $langcode => $language) { if (locale_is_translatable($langcode)) { $language_options[$langcode] = $language->getName(); } } // Pick the current interface language code for the filter. $default_langcode = $this->languageManager->getCurrentLanguage()->getId(); if (!isset($language_options[$default_langcode])) { $available_langcodes = array_keys($language_options); $default_langcode = array_shift($available_langcodes); } $filters['string'] = array('title' => $this->t('String contains'), 'description' => $this->t('Leave blank to show all strings. The search is case sensitive.'), 'default' => ''); $filters['langcode'] = array('title' => $this->t('Translation language'), 'options' => $language_options, 'default' => $default_langcode); $filters['translation'] = array('title' => $this->t('Search in'), 'options' => array('all' => $this->t('Both translated and untranslated strings'), 'translated' => $this->t('Only translated strings'), 'untranslated' => $this->t('Only untranslated strings')), 'default' => 'all'); $filters['customized'] = array('title' => $this->t('Translation type'), 'options' => array('all' => $this->t('All'), LOCALE_NOT_CUSTOMIZED => $this->t('Non-customized translation'), LOCALE_CUSTOMIZED => $this->t('Customized translation')), 'states' => array('visible' => array(':input[name=translation]' => array('value' => 'translated'))), 'default' => 'all'); return $filters; }
/** * {@inheritdoc} */ public function indexItems(IndexInterface $index, array $items) { $documents = array(); $ret = array(); $index_id = $this->getIndexId($index->id()); $field_names = $this->getFieldNames($index); $field_names_single_value = $this->getFieldNames($index, TRUE); $languages = $this->languageManager->getLanguages(); $base_urls = array(); // Make sure that we have a Solr connection. $this->connect(); /** @var \Drupal\search_api\Item\ItemInterface[] $items */ foreach ($items as $id => $item) { /** @var \Solarium\QueryType\Update\Query\Document\Document $doc */ $doc = $this->getUpdateQuery()->createDocument(); $doc->setField('id', $this->createId($index_id, $id)); $doc->setField('index_id', $index_id); $doc->setField('item_id', $id); // Add the site hash and language-specific base URL. $doc->setField('hash', SearchApiSolrUtility::getSiteHash()); $lang = $item->getField('search_api_language')->getValues(); $lang = reset($lang); if (empty($base_urls[$lang])) { $url_options = array('absolute' => TRUE); if (isset($languages[$lang])) { $url_options['language'] = $languages[$lang]; } // An exception is thrown if this is called during a non-HTML response // like REST or a redirect without collecting metadata. Avoid that by // collecting and discarding it. // See https://www.drupal.org/node/2638686. $base_urls[$lang] = Url::fromRoute('<front>', array(), $url_options)->toString(TRUE)->getGeneratedUrl(); } $doc->setField('site', $base_urls[$lang]); /** @var \Drupal\search_api\Item\FieldInterface $field */ foreach ($item as $name => $field) { // If the field is not known for the index, something weird has // happened. We refuse to index the items and hope that the others are // OK. if (!isset($field_names[$name])) { $vars = array('%field' => $name, '@id' => $id); \Drupal::logger('search_api_solr')->warning('Error while indexing: Unknown field %field on the item with ID @id.', $vars); $doc = NULL; break; } $this->addIndexField($doc, $field_names[$name], $field_names_single_value[$name], $field->getValues(), $field->getType()); } if ($doc) { $documents[] = $doc; $ret[] = $id; } } // Let other modules alter documents before sending them to solr. $this->moduleHandler->alter('search_api_solr_documents', $documents, $index, $items); $this->alterSolrDocuments($documents, $index, $items); if (!$documents) { return array(); } try { $this->getUpdateQuery()->addDocuments($documents); // Do a commitWithin since that is automatically a softCommit with Solr 4 // and a delayed hard commit with Solr 3.4+. // We wait 1 second after the request arrived for solr to parse the commit. // This allows us to return to Drupal and let Solr handle what it // needs to handle // @see http://wiki.apache.org/solr/NearRealtimeSearch /** @var \Solarium\Plugin\CustomizeRequest\CustomizeRequest $customizer */ $customizer = $this->solr->getPlugin('customizerequest'); $customizer->createCustomization('id')->setType('param')->setName('commitWithin')->setValue('1000'); $this->solr->execute($this->getUpdateQuery()); // Reset the Update query for further calls. static::$updateQuery = NULL; return $ret; } catch (\Exception $e) { watchdog_exception('search_api_solr', $e, "%type while indexing: @message in %function (line %line of %file)."); } return array(); }
/** * {@inheritdoc} */ protected function setUp() { parent::setUp(); $this->moduleHandler = $this->prophesize(ModuleHandlerInterface::class); $this->moduleHandler->getImplementations('entity_type_build')->willReturn([]); $this->moduleHandler->alter('entity_type', Argument::type('array'))->willReturn(NULL); $this->moduleHandler->alter('entity_base_field_info', Argument::type('array'), Argument::any())->willReturn(NULL); $this->moduleHandler->alter('entity_bundle_field_info', Argument::type('array'), Argument::any(), Argument::type('string'))->willReturn(NULL); $this->cacheBackend = $this->prophesize(CacheBackendInterface::class); $this->cacheTagsInvalidator = $this->prophesize(CacheTagsInvalidatorInterface::class); $language = new Language(['id' => 'en']); $this->languageManager = $this->prophesize(LanguageManagerInterface::class); $this->languageManager->getCurrentLanguage()->willReturn($language); $this->languageManager->getLanguages()->willReturn(['en' => (object) ['id' => 'en']]); $this->typedDataManager = $this->prophesize(TypedDataManager::class); $this->typedDataManager->getDefinition('field_item:boolean')->willReturn(['class' => BooleanItem::class]); $this->eventDispatcher = $this->prophesize(EventDispatcherInterface::class); $this->keyValueFactory = $this->prophesize(KeyValueFactoryInterface::class); $this->container = $this->prophesize(ContainerInterface::class); $this->container->get('cache_tags.invalidator')->willReturn($this->cacheTagsInvalidator->reveal()); $this->container->get('typed_data_manager')->willReturn($this->typedDataManager->reveal()); \Drupal::setContainer($this->container->reveal()); $this->discovery = $this->prophesize(DiscoveryInterface::class); $translation_manager = $this->prophesize(TranslationInterface::class); $this->entityManager = new TestEntityManager(new \ArrayObject(), $this->moduleHandler->reveal(), $this->cacheBackend->reveal(), $this->languageManager->reveal(), $translation_manager->reveal(), $this->getClassResolverStub(), $this->typedDataManager->reveal(), $this->keyValueFactory->reveal(), $this->eventDispatcher->reveal()); $this->entityManager->setContainer($this->container->reveal()); $this->entityManager->setDiscovery($this->discovery->reveal()); }
/** * Loads values of fields stored in dedicated tables for a group of entities. * * @param array &$values * An array of values keyed by entity ID. * @param bool $load_from_revision * (optional) Flag to indicate whether revisions should be loaded or not, * defaults to FALSE. */ protected function loadFromDedicatedTables(array &$values, $load_from_revision) { if (empty($values)) { return; } // Collect entities ids, bundles and languages. $bundles = array(); $ids = array(); $default_langcodes = array(); foreach ($values as $key => $entity_values) { $bundles[$this->bundleKey ? $entity_values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : $this->entityTypeId] = TRUE; $ids[] = !$load_from_revision ? $key : $entity_values[$this->revisionKey][LanguageInterface::LANGCODE_DEFAULT]; if ($this->langcodeKey && isset($entity_values[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT])) { $default_langcodes[$key] = $entity_values[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT]; } } // Collect impacted fields. $storage_definitions = array(); $definitions = array(); $table_mapping = $this->getTableMapping(); foreach ($bundles as $bundle => $v) { $definitions[$bundle] = $this->entityManager->getFieldDefinitions($this->entityTypeId, $bundle); foreach ($definitions[$bundle] as $field_name => $field_definition) { $storage_definition = $field_definition->getFieldStorageDefinition(); if ($table_mapping->requiresDedicatedTableStorage($storage_definition)) { $storage_definitions[$field_name] = $storage_definition; } } } // Load field data. $langcodes = array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL)); foreach ($storage_definitions as $field_name => $storage_definition) { $table = !$load_from_revision ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition); // Ensure that only values having valid languages are retrieved. Since we // are loading values for multiple entities, we cannot limit the query to // the available translations. $results = $this->database->select($table, 't')->fields('t')->condition(!$load_from_revision ? 'entity_id' : 'revision_id', $ids, 'IN')->condition('deleted', 0)->condition('langcode', $langcodes, 'IN')->orderBy('delta')->execute(); foreach ($results as $row) { $bundle = $row->bundle; // Field values in default language are stored with // LanguageInterface::LANGCODE_DEFAULT as key. $langcode = LanguageInterface::LANGCODE_DEFAULT; if ($this->langcodeKey && isset($default_langcodes[$row->entity_id]) && $row->langcode != $default_langcodes[$row->entity_id]) { $langcode = $row->langcode; } if (!isset($values[$row->entity_id][$field_name][$langcode])) { $values[$row->entity_id][$field_name][$langcode] = array(); } // Ensure that records for non-translatable fields having invalid // languages are skipped. if ($langcode == LanguageInterface::LANGCODE_DEFAULT || $definitions[$bundle][$field_name]->isTranslatable()) { if ($storage_definition->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($values[$row->entity_id][$field_name][$langcode]) < $storage_definition->getCardinality()) { $item = array(); // For each column declared by the field, populate the item from the // prefixed database column. foreach ($storage_definition->getColumns() as $column => $attributes) { $column_name = $table_mapping->getFieldColumnName($storage_definition, $column); // Unserialize the value if specified in the column schema. $item[$column] = !empty($attributes['serialize']) ? unserialize($row->{$column_name}) : $row->{$column_name}; } // Add the item to the field values for the entity. $values[$row->entity_id][$field_name][$langcode][] = $item; } } } } }
/** * Returns links to the current page with different langcodes. * * Using #type 'link' causes these links to be rendered with _l(). */ public function typeLinkActiveClass() { // We assume that 'en' and 'fr' have been configured. $languages = $this->languageManager->getLanguages(); return array('no_language' => array('#type' => 'link', '#title' => t('Link to the current path with no langcode provided.'), '#url' => Url::fromRoute('<current>'), '#options' => array('attributes' => array('id' => 'no_lang_link'), 'set_active_class' => TRUE)), 'fr' => array('#type' => 'link', '#title' => t('Link to a French version of the current path.'), '#url' => Url::fromRoute('<current>'), '#options' => array('language' => $languages['fr'], 'attributes' => array('id' => 'fr_link'), 'set_active_class' => TRUE)), 'en' => array('#type' => 'link', '#title' => t('Link to an English version of the current path.'), '#url' => Url::fromRoute('<current>'), '#options' => array('language' => $languages['en'], 'attributes' => array('id' => 'en_link'), 'set_active_class' => TRUE))); }