/**
  * @covers ::getContextValues
  */
 public function testGetContextValuesEntityContext()
 {
     $input = ['foo' => ['label' => 'Foo', 'type' => 'entity:node', 'value' => 'the_node_uuid']];
     $expected = new EntityLazyLoadContext(new ContextDefinition('entity:node', 'Foo'), $this->entityRepository->reveal(), 'the_node_uuid');
     $actual = $this->staticContext->getContextValues($input)['foo'];
     $this->assertEquals($expected, $actual);
 }
 /**
  * {@inheritdoc}
  */
 public function getContextValue()
 {
     if (!$this->contextData) {
         $entity_type_id = substr($this->contextDefinition->getDataType(), 7);
         $this->setContextValue($this->entityRepository->loadEntityByUuid($entity_type_id, $this->uuid));
     }
     return parent::getContextValue();
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $name = '')
 {
     $this->page = $page;
     $this->staticContext = $this->page->getStaticContext($name);
     // Allow the condition to add to the form.
     $form['label'] = ['#type' => 'textfield', '#title' => $this->t('Label'), '#default_value' => isset($this->staticContext['label']) ? $this->staticContext['label'] : '', '#required' => TRUE];
     $form['machine_name'] = ['#type' => 'machine_name', '#maxlength' => 64, '#required' => TRUE, '#machine_name' => ['exists' => [$this, 'contextExists'], 'source' => ['label']], '#default_value' => $name];
     $form['entity_type'] = ['#type' => 'select', '#title' => $this->t('Entity type'), '#options' => $this->entityTypeRepository->getEntityTypeLabels(TRUE), '#limit_validation_errors' => array(array('entity_type')), '#submit' => ['::rebuildSubmit'], '#executes_submit_callback' => TRUE, '#ajax' => array('callback' => '::updateEntityType', 'wrapper' => 'add-static-context-wrapper', 'method' => 'replace')];
     $entity = NULL;
     if ($form_state->hasValue('entity_type')) {
         $entity_type = $form_state->getValue('entity_type');
         if ($this->staticContext['value']) {
             $entity = $this->entityRepository->loadEntityByUuid($entity_type, $this->staticContext['value']);
         }
     } elseif (!empty($this->staticContext['type'])) {
         list(, $entity_type) = explode(':', $this->staticContext['type']);
         $entity = $this->entityRepository->loadEntityByUuid($entity_type, $this->staticContext['value']);
     } elseif ($this->entityTypeManager->hasDefinition('node')) {
         $entity_type = 'node';
     } else {
         $entity_type = 'user';
     }
     $form['entity_type']['#default_value'] = $entity_type;
     $form['selection'] = ['#type' => 'entity_autocomplete', '#prefix' => '<div id="add-static-context-wrapper">', '#suffix' => '</div>', '#required' => TRUE, '#target_type' => $entity_type, '#default_value' => $entity, '#title' => $this->t('Select entity')];
     $form['actions'] = ['#type' => 'actions'];
     $form['actions']['submit'] = ['#type' => 'submit', '#value' => $this->submitButtonText(), '#button_type' => 'primary'];
     return $form;
 }
 /**
  * Tests buildForm() with existing element input, with a new image being ULd.
  *
  * @covers ::buildForm
  *
  * @test
  */
 public function buildFormWithExistingImageElementAndNewUploadReturnsExpectedForm()
 {
     $mock_asset = $this->getMockBuilder(EmbridgeAssetEntity::class)->disableOriginalConstructor()->getMock();
     $mock_asset->expects($this->once())->method('id')->willReturn(self::MOCK_ASSET_ID);
     $this->setUpBuildForm($mock_asset);
     $form = [];
     // This is what the form recevies from ckeditor.
     $user_input['editor_object'] = ['src' => 'www.example.com/test_catalog/views/modules/asset/downloads/preview/thumb/2016/03/113/test.jpg/thumb.jpg', 'alt' => 'test image', 'width' => '100', 'height' => '100', 'data-entity-type' => 'embridge_asset_entity', 'data-entity-uuid' => self::MOCK_ASSET_UUID, 'data-align' => 'right', 'data-conversion' => 'center'];
     $user_input['_triggering_element_name'] = 'not_the_remove_button';
     // Have to mock this because of:
     // LogicException: Form state caching on GET requests is not allowed.
     /** @var FormState|\PHPUnit_Framework_MockObject_MockObject $form_state */
     $form_state = $this->getMockBuilder(FormState::class)->disableOriginalConstructor()->getMock();
     $form_state->expects($this->once())->method('getUserInput')->willReturn($user_input);
     $form_state->expects($this->once())->method('setCached');
     $form_state->expects($this->once())->method('set')->with('image_element', $user_input['editor_object']);
     $form_state->expects($this->once())->method('getValues')->willReturn(['aid' => [self::MOCK_ASSET_ID]]);
     $form_state->expects($this->once())->method('getValue')->with(['asset', 0])->willReturn(self::MOCK_ASSET_ID);
     $this->entityRepository->expects($this->once())->method('loadEntityByUuid')->with('embridge_asset_entity', self::MOCK_ASSET_UUID)->willReturn($mock_asset);
     $this->assetHelper->expects($this->once())->method('getAssetConversionUrl')->with($mock_asset, 'test_application', 'thumb')->willReturn('www.example.com/test_application/path/to/preview/thumb.png');
     $actual = $this->form->buildForm($form, $form_state, $this->mockFilter);
     $expected = file_get_contents('expected/image-dialog-existing-image-expected-build.json', TRUE);
     // Test form builds correctly.
     $this->assertJsonStringEqualsJsonString($expected, Json::encode($actual));
 }
예제 #5
0
 /**
  * Determines the entity.
  *
  * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
  *   The route match.
  * @param \Drupal\Core\Entity\EntityInterface $_entity
  *   (optional) The entity, set in
  *   \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer.
  *
  * @return \Drupal\Core\Entity\EntityInterface|null
  *   The entity, if it is passed in directly or if the first parameter of the
  *   active route is an entity; otherwise, NULL.
  */
 protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL)
 {
     if ($_entity) {
         $entity = $_entity;
     } else {
         // Let's look up in the route object for the name of upcasted values.
         foreach ($route_match->getParameters() as $parameter) {
             if ($parameter instanceof EntityInterface) {
                 $entity = $parameter;
                 break;
             }
         }
     }
     if (isset($entity)) {
         return $this->entityRepository->getTranslationFromContext($entity);
     }
 }
 /**
  * {@inheritdoc}
  */
 protected function init()
 {
     // Collect the args from the path manually. We can't pass them in from the
     // controller base because that class has to work for a variable number
     // of args.
     $attribs = $this->request->attributes->get('_raw_variables');
     // Set data sources as properties.
     $this->entityType = $attribs->get('entityType');
     $this->entityId = $attribs->get('entityId');
     $this->fieldName = $attribs->get('fieldName');
     $this->displayName = $attribs->get('displayName');
     // Grab the loaded entity as well, translated appropriately.
     $entity_base = $this->entityTypeManager->getStorage($this->entityType)->load($this->entityId);
     $this->entity = $this->entityRepository->getTranslationFromContext($entity_base);
     if (is_object($this->entity) && $this->entity instanceof EntityInterface) {
         // All looks good.
         return;
     }
     throw new \Exception(t('Cannot instantiate field-based Juicebox gallery as no entity can be loaded.'));
 }
 /**
  * Locate all images in a piece of text that need replacing.
  *
  *   An array of settings that will be used to identify which images need
  *   updating. Includes the following:
  *
  *   - image_locations: An array of acceptable image locations.
  *     of the following values: "remote". Remote image will be downloaded and
  *     saved locally. This procedure is intensive as the images need to
  *     be retrieved to have their dimensions checked.
  *
  * @param string $text
  *   The text to be updated with the new img src tags.
  *
  * @return array $images
  *   An list of images.
  */
 private function getImages($text)
 {
     $dom = Html::load($text);
     $xpath = new \DOMXPath($dom);
     /** @var \DOMNode $node */
     foreach ($xpath->query('//img') as $node) {
         $file = $this->entityRepository->loadEntityByUuid('file', $node->getAttribute('data-entity-uuid'));
         // If the image hasn't an uuid then don't try to resize it.
         if (is_null($file)) {
             continue;
         }
         $image = $this->imageFactory->get($node->getAttribute('src'));
         // Checking if the image needs to be resized.
         if ($image->getWidth() == $node->getAttribute('width') && $image->getHeight() == $node->getAttribute('height')) {
             continue;
         }
         $target = file_uri_target($file->getFileUri());
         $dirname = dirname($target) != '.' ? dirname($target) . '/' : '';
         $info = pathinfo($file->getFileUri());
         $resize_file_path = 'public://resize/' . $dirname . $info['filename'] . '-' . $node->getAttribute('width') . 'x' . $node->getAttribute('height') . '.' . $info['extension'];
         // Checking if the image was already resized:
         if (file_exists($resize_file_path)) {
             $node->setAttribute('src', file_url_transform_relative(file_create_url($resize_file_path)));
             continue;
         }
         // Delete this when https://www.drupal.org/node/2211657#comment-11510213
         // be fixed.
         $dirname = $this->fileSystem->dirname($resize_file_path);
         if (!file_exists($dirname)) {
             file_prepare_directory($dirname, FILE_CREATE_DIRECTORY);
         }
         // Checks if the resize filter exists if is not then create it.
         $copy = file_unmanaged_copy($file->getFileUri(), $resize_file_path, FILE_EXISTS_REPLACE);
         $copy_image = $this->imageFactory->get($copy);
         $copy_image->resize($node->getAttribute('width'), $node->getAttribute('height'));
         $copy_image->save();
         $node->setAttribute('src', file_url_transform_relative(file_create_url($copy)));
     }
     return Html::serialize($dom);
 }
 /**
  * {@inheritdoc}
  *
  * @param \Drupal\filter\Entity\FilterFormat $filter_format
  *   The filter format for which this dialog corresponds.
  */
 public function buildForm(array $form, FormStateInterface $form_state, FilterFormat $filter_format = NULL)
 {
     // This form is special, in that the default values do not come from the
     // server side, but from the client side, from a text editor. We must cache
     // this data in form state, because when the form is rebuilt, we will be
     // receiving values from the form, instead of the values from the text
     // editor. If we don't cache it, this data will be lost.
     $user_input = $form_state->getUserInput();
     if (isset($user_input['editor_object'])) {
         // By convention, the data that the text editor sends to any dialog is in
         // the 'editor_object' key. And the image dialog for text editors expects
         // that data to be the attributes for an <img> element.
         $image_element = $user_input['editor_object'];
         $form_state->set('image_element', $image_element);
         $form_state->setCached(TRUE);
     } elseif ($form_state->getTemporaryValue('wizard')) {
         $image_element = $form_state->getTemporaryValue('wizard')['image_element'];
     } else {
         // Retrieve the image element's attributes from form state.
         $image_element = $form_state->get('image_element') ?: [];
     }
     // Add libraries and wrap the form in ajax wrappers.
     $form['#tree'] = TRUE;
     $form['#attached']['library'][] = 'editor/drupal.editor.dialog';
     $form['#prefix'] = '<div id="' . self::AJAX_WRAPPER_ID . '">';
     $form['#suffix'] = '</div>';
     /** @var \Drupal\editor\Entity\Editor $editor */
     $editor = $this->entityTypeManager->getStorage('editor')->load($filter_format->id());
     // Construct strings to use in the upload validators.
     $embridge_image_settings = $editor->getSettings()['plugins']['embridgeimage']['embridge_image_upload'];
     $max_filesize = min(Bytes::toInt($embridge_image_settings['max_size']), file_upload_max_size());
     /** @var \Drupal\embridge\EmbridgeAssetEntityInterface $existing_asset */
     $existing_asset = isset($image_element['data-entity-uuid']) ? $this->entityRepository->loadEntityByUuid('embridge_asset_entity', $image_element['data-entity-uuid']) : NULL;
     $asset_id = $existing_asset ? $existing_asset->id() : NULL;
     /** @var \Drupal\embridge\EmbridgeCatalogInterface $catalog */
     $catalog = $this->entityTypeManager->getStorage('embridge_catalog')->load($embridge_image_settings['catalog_id']);
     // Create a preview image.
     $preview = FALSE;
     if (!empty($user_input['_triggering_element_name'])) {
         $triggering_element = $user_input['_triggering_element_name'];
     }
     // If we are editing an existing asset, use that thumbnail.
     if (empty($form_state->getValues()) && $existing_asset) {
         $preview = $this->assetHelper->getAssetConversionUrl($existing_asset, $catalog->getApplicationId(), 'thumb');
     } elseif (isset($triggering_element) && $triggering_element != 'asset_remove_button' && ($uploaded_id = $form_state->getValue(['asset', 0]))) {
         /** @var \Drupal\embridge\EmbridgeAssetEntityInterface $uploaded_asset */
         $uploaded_asset = $this->entityTypeManager->getStorage('embridge_asset_entity')->load($uploaded_id);
         if ($uploaded_asset) {
             $preview = $this->assetHelper->getAssetConversionUrl($uploaded_asset, $catalog->getApplicationId(), 'thumb');
         }
     }
     // Use a stock image for preview.
     if (!$preview) {
         $preview = drupal_get_path('module', 'embridge_ckeditor') . '/images/preview-image.png';
     }
     // TODO: Make this configurable.
     $allowed_extensions = 'gif png jpg jpeg';
     $url_options = ['filter_format' => $filter_format->id(), 'extensions' => $allowed_extensions, 'catalog_id' => $embridge_image_settings['catalog_id']];
     $link_url = Url::fromRoute('embridge_ckeditor.image.wizard', $url_options);
     $link_url->setOptions(['attributes' => ['class' => ['use-ajax', 'button'], 'data-accepts' => 'application/vnd.drupal-modal', 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 1000])]]);
     $class = get_class($this);
     $form['asset'] = ['preview' => ['#theme' => 'image', '#uri' => $preview, '#weight' => -100], '#title' => $this->t('Image'), '#type' => 'embridge_asset', '#catalog_id' => $embridge_image_settings['catalog_id'], '#library_id' => $embridge_image_settings['library_id'], '#upload_location' => 'public://' . $embridge_image_settings['directory'], '#default_value' => $asset_id ? [$asset_id] : NULL, '#upload_validators' => ['validateFileExtensions' => [$allowed_extensions], 'validateFileSize' => [$max_filesize]], '#pre_render' => [[$class, 'preRenderAssetElement']], '#allow_search' => FALSE, '#required' => TRUE, 'search_link' => Link::fromTextAndUrl('Search asset library', $link_url)->toRenderable()];
     $form['asset']['search_link']['#weight'] = 100;
     $form['attributes'] = ['#type' => 'container', '#tree' => TRUE, '#attributes' => ['class' => ['image-attributes']]];
     $form['attributes']['src'] = ['#type' => 'value'];
     $alt = isset($image_element['alt']) ? $image_element['alt'] : '';
     $form['attributes']['alt'] = ['#title' => $this->t('Alternative text'), '#description' => $this->t('The alt text describes the image for non-sighted users. <br/>The alt text can remain empty only if the image conveys no meaning (is decorative only).'), '#type' => 'textfield', '#default_value' => $alt, '#maxlength' => 2048];
     $conversion = isset($image_element['data-conversion']) ? $image_element['data-conversion'] : '';
     $conversions_array = $catalog->getConversionsArray();
     $form['attributes']['data-conversion'] = ['#title' => $this->t('Image size'), '#description' => $this->t('Choose the image size conversion to display.'), '#type' => 'select', '#default_value' => $conversion, '#options' => array_combine($conversions_array, $conversions_array)];
     // When Drupal core's filter_align is being used, the text editor may
     // offer the ability to change the alignment.
     if ($filter_format->filters('filter_align')->status) {
         $data_align = !empty($image_element['data-align']) ? $image_element['data-align'] : '';
         $form['attributes']['data-align'] = ['#title' => $this->t('Align'), '#description' => $this->t('How the image will align within the content.'), '#type' => 'select', '#options' => ['none' => $this->t('None'), 'left' => $this->t('Left'), 'center' => $this->t('Center'), 'right' => $this->t('Right')], '#default_value' => $data_align];
     }
     $form['actions'] = ['#type' => 'actions'];
     $form['actions']['save_modal'] = ['#type' => 'submit', '#value' => $this->t('Save'), '#submit' => [], '#ajax' => ['callback' => [$this, 'ajaxSave'], 'event' => 'click'], '#attributes' => ['class' => ['button--primary']]];
     return $form;
 }
 /**
  * {@inheritdoc}
  */
 public function convert($value, $definition, $name, array $defaults)
 {
     list(, $entity_type_id) = explode(':', $definition['type'], 2);
     $entity = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($value);
     return $this->entityRepository->getTranslationFromContext($entity);
 }