/** * {@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(); }
/** * {@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; }
/** * 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; }