/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, PageInterface $page = NULL, $display_variant_id = NULL) { $form = parent::buildForm($form, $form_state, $page, $display_variant_id); // Set up the attributes used by a modal to prevent duplication later. $attributes = ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 'auto'])]; $add_button_attributes = NestedArray::mergeDeep($attributes, ['class' => ['button', 'button--small', 'button-action']]); if ($this->displayVariant instanceof ConditionVariantInterface) { if ($selection_conditions = $this->displayVariant->getSelectionConditions()) { // Selection conditions. $form['selection_section'] = ['#type' => 'details', '#title' => $this->t('Selection Conditions'), '#open' => TRUE]; $form['selection_section']['add'] = ['#type' => 'link', '#title' => $this->t('Add new selection condition'), '#url' => Url::fromRoute('page_manager.selection_condition_select', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['selection_section']['table'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Description'), $this->t('Operations')], '#empty' => $this->t('There are no selection conditions.')]; $form['selection_section']['selection_logic'] = ['#type' => 'radios', '#options' => ['and' => $this->t('All conditions must pass'), 'or' => $this->t('Only one condition must pass')], '#default_value' => $this->displayVariant->getSelectionLogic()]; $form['selection_section']['selection'] = ['#tree' => TRUE]; foreach ($selection_conditions as $selection_id => $selection_condition) { $row = []; $row['label']['#markup'] = $selection_condition->getPluginDefinition()['label']; $row['description']['#markup'] = $selection_condition->summary(); $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.selection_condition_edit', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id(), 'condition_id' => $selection_id]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.selection_condition_delete', ['page' => $this->page->id(), 'display_variant_id' => $this->displayVariant->id(), 'condition_id' => $selection_id]), 'attributes' => $attributes]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['selection_section']['table'][$selection_id] = $row; } } } return $form; }
protected function getRequestParams(Request $request) { $params = array_merge(['where' => [], 'limit' => null], $request->query->all()); $params['where'] = Json::decode($params['where']); ksort($params['where']); return $params; }
/** * Test base logic for the Juicebox field formatter. */ public function testFieldFormatter() { $node = $this->node; $xml_path = 'juicebox/xml/field/node/' . $node->id() . '/' . $this->instFieldName . '/full'; $xml_url = \Drupal::url('juicebox.xml_field', array('entityType' => 'node', 'entityId' => $node->id(), 'fieldName' => $this->instFieldName, 'displayName' => 'full')); // Get the urls to the test image and thumb derivative used by default. $uri = \Drupal\file\Entity\File::load($node->{$this->instFieldName}[0]->target_id)->getFileUri(); $test_image_url = entity_load('image_style', 'juicebox_medium')->buildUrl($uri); $test_thumb_url = entity_load('image_style', 'juicebox_square_thumb')->buildUrl($uri); // Check for correct embed markup. $this->drupalGet('node/' . $node->id()); $this->assertRaw(trim(json_encode(array('configUrl' => $xml_url)), '{}"'), 'Gallery setting found in Drupal.settings.'); $this->assertRaw('id="node--' . $node->id() . '--' . str_replace('_', '-', $this->instFieldName) . '--full"', 'Embed code wrapper found.'); $this->assertRaw(Html::escape(file_url_transform_relative($test_image_url)), 'Test image found in embed code'); // Check for correct XML. $this->drupalGet($xml_path); $this->assertRaw('<?xml version="1.0" encoding="UTF-8"?>', 'Valid XML detected.'); $this->assertRaw('imageURL="' . Html::escape($test_image_url), 'Test image found in XML.'); $this->assertRaw('thumbURL="' . Html::escape($test_thumb_url), 'Test thumbnail found in XML.'); // Check for contextual links in embed code. It might we worth checking if // there is a more programmatic way to build the related id at some point. $this->drupalLogin($this->webUser); // Need access to contextual links. $this->drupalGet('node/' . $node->id()); $id = 'juicebox_xml_field:entityType=node&entityId=' . $node->id() . '&fieldName=' . $this->instFieldName . '&displayName=full:langcode=en|juicebox_conf_field_node:view_mode_name=default&node_type=' . $this->instBundle . ':langcode=en|juicebox_conf_global::langcode=en'; $this->assertRaw('<div data-contextual-id="' . Html::escape($id) . '"></div>', 'Correct contextual link placeholders found.'); $json = Json::decode($this->renderContextualLinks(array($id), 'node/' . $node->id())); $this->assertResponse(200); $this->assertTrue(preg_match('|/juicebox/xml/field/node/' . $node->id() . '/' . $this->instFieldName . '/full.*/admin/structure/types/manage/' . $this->instBundle . '/display/default.*/admin/config/media/juicebox|', $json[$id]), 'Correct contextual links found.'); }
/** * Tests file field formatter Entity Embed Display plugins. */ public function testFileFieldFormatter() { // Ensure that file field formatters are available as plugins. $this->assertAvailableDisplayPlugins($this->file, ['entity_reference:entity_reference_label', 'entity_reference:entity_reference_entity_id', 'file:file_default', 'file:file_table', 'file:file_url_plain']); // Ensure that correct form attributes are returned for the file field // formatter plugins. $form = array(); $form_state = new FormState(); $plugins = array('file:file_table', 'file:file_default', 'file:file_url_plain'); // Ensure that description field is available for all the 'file' plugins. foreach ($plugins as $plugin) { $display = $this->displayPluginManager()->createInstance($plugin, array()); $display->setContextValue('entity', $this->file); $conf_form = $display->buildConfigurationForm($form, $form_state); $this->assertIdentical(array_keys($conf_form), array('description')); $this->assertIdentical($conf_form['description']['#type'], 'textfield'); $this->assertIdentical((string) $conf_form['description']['#title'], 'Description'); } // Test entity embed using 'Generic file' Entity Embed Display plugin. $embed_settings = array('description' => "This is sample description"); $content = '<drupal-entity data-entity-type="file" data-entity-uuid="' . $this->file->uuid() . '" data-entity-embed-display="file:file_default" data-entity-embed-settings=\'' . Json::encode($embed_settings) . '\'>This placeholder should not be rendered.</drupal-entity>'; $settings = array(); $settings['type'] = 'page'; $settings['title'] = 'Test entity embed with file:file_default'; $settings['body'] = array(array('value' => $content, 'format' => 'custom_format')); $node = $this->drupalCreateNode($settings); $this->drupalGet('node/' . $node->id()); $this->assertText($embed_settings['description'], 'Description of the embedded file exists in page.'); $this->assertNoText(strip_tags($content), 'Placeholder does not appears in the output when embed is successful.'); $this->assertLinkByHref(file_create_url($this->file->getFileUri()), 0, 'Link to the embedded file exists.'); }
/** * @todo . */ public function messageHandler() { if (!isset($_POST['serviceKey']) || !nodejs_is_valid_service_key($_POST['serviceKey'])) { return new JsonResponse(array('error' => 'Invalid service key.')); } if (!isset($_POST['messageJson'])) { return new JsonResponse(array('error' => 'No message.')); } $message = Json::decode($_POST['messageJson']); $response = array(); switch ($message['messageType']) { case 'authenticate': $response = nodejs_auth_check($message); break; case 'userOffline': nodejs_user_set_offline($message['uid']); break; default: $handlers = array(); foreach (module_implements('nodejs_message_callback') as $module) { $function = $module . '_nodejs_message_callback'; $handlers += $function($message['messageType']); } foreach ($handlers as $callback) { $callback($message, $response); } } \Drupal::moduleHandler()->alter('nodejs_message_response', $response, $message); return new JsonResponse($response ? $response : array('error' => 'Not implemented')); }
/** * Tests several valid and invalid read requests on all entity types. */ public function testRead() { // @todo Expand this at least to users. // Define the entity types we want to test. $entity_types = array('entity_test', 'node'); foreach ($entity_types as $entity_type) { $this->enableService('entity:' . $entity_type, 'GET'); // Create a user account that has the required permissions to read // resources via the REST API. $permissions = $this->entityPermissions($entity_type, 'view'); $permissions[] = 'restful get entity:' . $entity_type; $account = $this->drupalCreateUser($permissions); $this->drupalLogin($account); // Create an entity programmatically. $entity = $this->entityCreate($entity_type); $entity->save(); // Read it over the REST API. $response = $this->httpRequest($entity->getSystemPath(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse('200', 'HTTP response code is correct.'); $this->assertHeader('content-type', $this->defaultMimeType); $data = Json::decode($response); // Only assert one example property here, other properties should be // checked in serialization tests. $this->assertEqual($data['uuid'][0]['value'], $entity->uuid(), 'Entity UUID is correct'); // Try to read the entity with an unsupported mime format. $response = $this->httpRequest($entity->getSystemPath(), 'GET', NULL, 'application/wrongformat'); $this->assertResponse(200); $this->assertHeader('Content-type', 'text/html; charset=UTF-8'); // Try to read an entity that does not exist. $response = $this->httpRequest($entity_type . '/9999', 'GET', NULL, $this->defaultMimeType); $this->assertResponse(404); $path = $entity_type == 'node' ? '/node/{node}' : '/entity_test/{entity_test}'; $expected_message = Json::encode(['error' => 'A fatal error occurred: The "' . $entity_type . '" parameter was not converted for the path "' . $path . '" (route name: "rest.entity.' . $entity_type . '.GET.hal_json")']); $this->assertIdentical($expected_message, $response, 'Response message is correct.'); // Make sure that field level access works and that the according field is // not available in the response. Only applies to entity_test. // @see entity_test_entity_field_access() if ($entity_type == 'entity_test') { $entity->field_test_text->value = 'no access value'; $entity->save(); $response = $this->httpRequest($entity->getSystemPath(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse(200); $this->assertHeader('content-type', $this->defaultMimeType); $data = Json::decode($response); $this->assertFalse(isset($data['field_test_text']), 'Field access protected field is not visible in the response.'); } // Try to read an entity without proper permissions. $this->drupalLogout(); $response = $this->httpRequest($entity->getSystemPath(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse(403); $this->assertIdentical('{}', $response); } // Try to read a resource which is not REST API enabled. $account = $this->drupalCreateUser(); $this->drupalLogin($account); $response = $this->httpRequest($account->getSystemPath(), 'GET', NULL, $this->defaultMimeType); $this->assertResponse(404); $expected_message = Json::encode(['error' => 'A fatal error occurred: Unable to find the controller for path "/user/4". Maybe you forgot to add the matching route in your routing configuration?']); $this->assertIdentical($expected_message, $response); }
/** * Sets up all of our services with mock methods so buildForm() is possible. * * @param string $catalog_id * Catalog id. * @param string $application_id * Application id. * @param [] $filters * An optional list of filters for the client to receive. */ protected function baseMockBuild($catalog_id, $application_id, $filters = []) { // Field manager mocking. $field_settings = ['max_filesize' => '2 MB', 'file_extensions' => self::MOCK_FIELD_SETTINGS_FILE_EXTENSIONS, 'catalog_id' => $catalog_id]; $this->fieldConfig->expects($this->once())->method('getName')->willReturn('field_test'); $this->fieldConfig->expects($this->once())->method('getSettings')->willReturn($field_settings); // Search filter always starts with the extensions OR filter. $extension_filter_value = str_replace(',', '|', self::MOCK_FIELD_SETTINGS_FILE_EXTENSIONS); $extension_filter = ['field' => 'fileformat', 'operator' => 'matches', 'value' => $extension_filter_value]; array_unshift($filters, $extension_filter); // Client mocking. $search_response = $this->json->decode(file_get_contents('expected/search-expected-small-response.json', TRUE)); $per_page = 8; $page = 1; $this->client->expects($this->once())->method('search')->with($page, $per_page, $filters)->willReturn($search_response); // Entity type storage mocking. $mock_catalog = $this->getMockBuilder('\\Drupal\\embridge\\EmbridgeCatalogInterface')->disableOriginalConstructor()->getMock(); $mock_catalog->expects($this->once())->method('getApplicationId')->willReturn($application_id); $mock_catalog_storage = $this->getMock(EntityStorageInterface::class); $mock_catalog_storage->expects($this->once())->method('load')->with($catalog_id)->willReturn($mock_catalog); $this->entityTypeManager->expects($this->once())->method('getStorage')->with('embridge_catalog')->willReturn($mock_catalog_storage); // Create mock assets. foreach ($search_response['results'] as $i => $result) { $mock_asset = $this->getMockBuilder('\\Drupal\\embridge\\EmbridgeAssetEntityInterface')->disableOriginalConstructor()->getMock(); $mock_asset->expects($this->once())->method('id')->willReturn($i); $this->mockAssets[$i]['asset'] = $mock_asset; $this->mockAssets[$i]['result'] = $result; } // Mock up the asset helper. $return_map = []; foreach ($this->mockAssets as $id => $asset_result) { $return_map[] = [$asset_result['result'], $catalog_id, $asset_result['asset']]; } $this->assetHelper->expects($this->exactly(count($this->mockAssets)))->method('searchResultToAsset')->will($this->returnValueMap($return_map)); }
/** * Tests if custom variables are properly added to the page. */ public function testPiwikCustomVariables() { $site_id = '3'; $this->config('piwik.settings')->set('site_id', $site_id)->save(); $this->config('piwik.settings')->set('url_http', 'http://www.example.com/piwik/')->save(); $this->config('piwik.settings')->set('url_https', 'https://www.example.com/piwik/')->save(); // Basic test if the feature works. $custom_vars = [1 => ['slot' => 1, 'name' => 'Foo 1', 'value' => 'Bar 1', 'scope' => 'visit'], 2 => ['slot' => 2, 'name' => 'Foo 2', 'value' => 'Bar 2', 'scope' => 'page'], 3 => ['slot' => 3, 'name' => 'Foo 3', 'value' => 'Bar 3', 'scope' => 'page'], 4 => ['slot' => 4, 'name' => 'Foo 4', 'value' => 'Bar 4', 'scope' => 'visit'], 5 => ['slot' => 5, 'name' => 'Foo 5', 'value' => 'Bar 5', 'scope' => 'visit']]; $this->config('piwik.settings')->set('custom.variable', $custom_vars)->save(); $this->drupalGet(''); foreach ($custom_vars as $slot) { $this->assertRaw('_paq.push(["setCustomVariable", ' . Json::encode($slot['slot']) . ', ' . Json::encode($slot['name']) . ', ' . Json::encode($slot['value']) . ', ' . Json::encode($slot['scope']) . ']);', '[testPiwikCustomVariables]: setCustomVariable ' . $slot['slot'] . ' is shown.'); } // Test whether tokens are replaced in custom variable names. $site_slogan = $this->randomMachineName(16); $this->config('system.site')->set('slogan', $site_slogan)->save(); $custom_vars = [1 => ['slot' => 1, 'name' => 'Name: [site:slogan]', 'value' => 'Value: [site:slogan]', 'scope' => 'visit'], 2 => ['slot' => 2, 'name' => '', 'value' => $this->randomMachineName(16), 'scope' => 'page'], 3 => ['slot' => 3, 'name' => $this->randomMachineName(16), 'value' => '', 'scope' => 'visit'], 4 => ['slot' => 4, 'name' => '', 'value' => '', 'scope' => 'page'], 5 => ['slot' => 5, 'name' => '', 'value' => '', 'scope' => 'visit']]; $this->config('piwik.settings')->set('custom.variable', $custom_vars)->save(); $this->verbose('<pre>' . print_r($custom_vars, TRUE) . '</pre>'); $this->drupalGet(''); $this->assertRaw('_paq.push(["setCustomVariable", 1, ' . Json::encode("Name: {$site_slogan}") . ', ' . Json::encode("Value: {$site_slogan}") . ', "visit"]', '[testPiwikCustomVariables]: Tokens have been replaced in custom variable.'); $this->assertNoRaw('_paq.push(["setCustomVariable", 2,', '[testPiwikCustomVariables]: Value with empty name is not shown.'); $this->assertNoRaw('_paq.push(["setCustomVariable", 3,', '[testPiwikCustomVariables]: Name with empty value is not shown.'); $this->assertNoRaw('_paq.push(["setCustomVariable", 4,', '[testPiwikCustomVariables]: Empty name and value is not shown.'); $this->assertNoRaw('_paq.push(["setCustomVariable", 5,', '[testPiwikCustomVariables]: Empty name and value is not shown.'); }
/** * Writes a log messages and retrieves it via the REST API. */ public function testWatchdog() { // Write a log message to the DB. $this->container->get('logger.channel.rest')->notice('Test message'); // Get the ID of the written message. $id = db_query_range("SELECT wid FROM {watchdog} WHERE type = :type ORDER BY wid DESC", 0, 1, array(':type' => 'rest'))->fetchField(); // Create a user account that has the required permissions to read // the watchdog resource via the REST API. $account = $this->drupalCreateUser(array('restful get dblog')); $this->drupalLogin($account); $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => $id, '_format' => $this->defaultFormat]), 'GET'); $this->assertResponse(200); $this->assertHeader('content-type', $this->defaultMimeType); $log = Json::decode($response); $this->assertEqual($log['wid'], $id, 'Log ID is correct.'); $this->assertEqual($log['type'], 'rest', 'Type of log message is correct.'); $this->assertEqual($log['message'], 'Test message', 'Log message text is correct.'); // Request an unknown log entry. $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 9999, '_format' => $this->defaultFormat]), 'GET'); $this->assertResponse(404); $decoded = Json::decode($response); $this->assertEqual($decoded['message'], 'Log entry with ID 9999 was not found', 'Response message is correct.'); // Make a bad request (a true malformed request would never be a route match). $response = $this->httpRequest(Url::fromRoute('rest.dblog.GET.' . $this->defaultFormat, ['id' => 0, '_format' => $this->defaultFormat]), 'GET'); $this->assertResponse(400); $decoded = Json::decode($response); $this->assertEqual($decoded['message'], 'No log entry ID was provided', 'Response message is correct.'); }
/** * Tests an ajax view. */ public function testAjaxView() { $this->drupalGet('test_ajax_view'); $drupal_settings = $this->getDrupalSettings(); $this->assertTrue(isset($drupal_settings['views']['ajax_path']), 'The Ajax callback path is set in drupalSettings.'); $this->assertEqual(count($drupal_settings['views']['ajaxViews']), 1); $view_entry = array_keys($drupal_settings['views']['ajaxViews'])[0]; $this->assertEqual($drupal_settings['views']['ajaxViews'][$view_entry]['view_name'], 'test_ajax_view', 'The view\'s ajaxViews array entry has the correct \'view_name\' key.'); $this->assertEqual($drupal_settings['views']['ajaxViews'][$view_entry]['view_display_id'], 'page_1', 'The view\'s ajaxViews array entry has the correct \'view_display_id\' key.'); $data = array(); $data['view_name'] = 'test_ajax_view'; $data['view_display_id'] = 'test_ajax_view'; $post = array('view_name' => 'test_ajax_view', 'view_display_id' => 'page_1'); $post += $this->getAjaxPageStatePostData(); $response = $this->drupalPost('views/ajax', 'application/vnd.drupal-ajax', $post); $data = Json::decode($response); $this->assertTrue(isset($data[0]['settings']['views']['ajaxViews'])); $this->assertEqual($data[1]['command'], 'add_css'); // Ensure that the view insert command is part of the result. $this->assertEqual($data[2]['command'], 'insert'); $this->assertTrue(strpos($data[2]['selector'], '.js-view-dom-id-') === 0); $this->setRawContent($data[2]['data']); $result = $this->xpath('//div[contains(@class, "views-row")]'); $this->assertEqual(count($result), 2, 'Ensure that two items are rendered in the HTML.'); }
/** * Presents a list of conditions to add to the block_visibility_group entity. * * @param \Drupal\block_visibility_groups\Entity\BlockVisibilityGroup $block_visibility_group * The block_visibility_group entity. * * @return array * The condition selection page. */ public function selectCondition(BlockVisibilityGroup $block_visibility_group, $redirect) { $build = [ '#theme' => 'links', '#links' => [], ]; $available_plugins = $this->conditionManager->getDefinitions(); // @todo Should nesting Conditions be allowed unset($available_plugins['condition_group']); foreach ($available_plugins as $condition_id => $condition) { $build['#links'][$condition_id] = [ 'title' => $condition['label'], 'url' => Url::fromRoute('block_visibility_groups.condition_add', [ 'block_visibility_group' => $block_visibility_group->id(), 'condition_id' => $condition_id, 'redirect' => $redirect, ]), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode([ 'width' => 'auto', ]), ], ]; } return $build; }
/** * Attempts to decode the incoming request's content as JSON. * * @param \Symfony\Component\HttpFoundation\Request $request * * @return mixed * * @throws \Drupal\panels_ipe\Exception\EmptyRequestContentException */ protected static function decodeRequest(Request $request) { if (empty($request->getContent())) { throw new EmptyRequestContentException(); } return Json::decode($request->getContent()); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $form_state->cleanValues(); // This won't have a proper JSON header, but Drupal doesn't check for that // anyway so this is fine until it's replaced with a JsonResponse. print Json::encode($form_state->getValues()); exit; }
/** * {@inheritdoc} */ public function submitForm(array &$form, array &$form_state) { form_state_values_clean($form_state); // This won't have a proper JSON header, but Drupal doesn't check for that // anyway so this is fine until it's replaced with a JsonResponse. print Json::encode($form_state['values']); exit; }
/** * {@inheritdoc} */ public function render(array $js_assets) { $elements = array(); // A dummy query-string is added to filenames, to gain control over // browser-caching. The string changes on every update or full cache // flush, forcing browsers to load a new copy of the files, as the // URL changed. Files that should not be cached (see _drupal_add_js()) // get REQUEST_TIME as query-string instead, to enforce reload on every // page request. $default_query_string = $this->state->get('system.css_js_query_string') ?: '0'; // For inline JavaScript to validate as XHTML, all JavaScript containing // XHTML needs to be wrapped in CDATA. To make that backwards compatible // with HTML 4, we need to comment out the CDATA-tag. $embed_prefix = "\n<!--//--><![CDATA[//><!--\n"; $embed_suffix = "\n//--><!]]>\n"; // Defaults for each SCRIPT element. $element_defaults = array('#type' => 'html_tag', '#tag' => 'script', '#value' => ''); // Loop through all JS assets. foreach ($js_assets as $js_asset) { // Element properties that do not depend on JS asset type. $element = $element_defaults; $element['#browsers'] = $js_asset['browsers']; // Element properties that depend on item type. switch ($js_asset['type']) { case 'setting': $element['#value_prefix'] = $embed_prefix; $element['#value'] = 'var drupalSettings = ' . Json::encode(drupal_merge_js_settings($js_asset['data'])) . ";"; $element['#value_suffix'] = $embed_suffix; break; case 'inline': $element['#value_prefix'] = $embed_prefix; $element['#value'] = $js_asset['data']; $element['#value_suffix'] = $embed_suffix; break; case 'file': $query_string = empty($js_asset['version']) ? $default_query_string : 'v=' . $js_asset['version']; $query_string_separator = strpos($js_asset['data'], '?') !== FALSE ? '&' : '?'; $element['#attributes']['src'] = file_create_url($js_asset['data']); // Only add the cache-busting query string if this isn't an aggregate // file. if (!isset($js_asset['preprocessed'])) { $element['#attributes']['src'] .= $query_string_separator . ($js_asset['cache'] ? $query_string : REQUEST_TIME); } break; case 'external': $element['#attributes']['src'] = $js_asset['data']; break; default: throw new \Exception('Invalid JS asset type.'); } // Attributes may only be set if this script is output independently. if (!empty($element['#attributes']['src']) && !empty($js_asset['attributes'])) { $element['#attributes'] += $js_asset['attributes']; } $elements[] = $element; } return $elements; }
/** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); $form['use_admin_theme'] = ['#type' => 'checkbox', '#title' => $this->t('Use admin theme'), '#default_value' => $this->entity->usesAdminTheme()]; $attributes = ['class' => ['use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 'auto'])]; $add_button_attributes = NestedArray::mergeDeep($attributes, ['class' => ['button', 'button--small', 'button-action']]); $form['context'] = ['#type' => 'details', '#title' => $this->t('Available context'), '#open' => TRUE]; $form['context']['add'] = ['#type' => 'link', '#title' => $this->t('Add new static context'), '#url' => Url::fromRoute('page_manager.static_context_add', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['context']['available_context'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Name'), $this->t('Type'), $this->t('Operations')], '#empty' => $this->t('There is no available context.')]; $contexts = $this->entity->getContexts(); foreach ($contexts as $name => $context) { $context_definition = $context->getContextDefinition(); $row = []; $row['label'] = ['#markup' => $context_definition->getLabel()]; $row['machine_name'] = ['#markup' => $name]; $row['type'] = ['#markup' => $context_definition->getDataType()]; // Add operation links if the context is a static context. $operations = []; if ($this->entity->getStaticContext($name)) { $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.static_context_edit', ['page' => $this->entity->id(), 'name' => $name]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.static_context_delete', ['page' => $this->entity->id(), 'name' => $name]), 'attributes' => $attributes]; } $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['context']['available_context'][$name] = $row; } $form['display_variant_section'] = ['#type' => 'details', '#title' => $this->t('Display variants'), '#open' => TRUE]; $form['display_variant_section']['add_new_page'] = ['#type' => 'link', '#title' => $this->t('Add new display variant'), '#url' => Url::fromRoute('page_manager.display_variant_select', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['display_variant_section']['display_variants'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Plugin'), $this->t('Weight'), $this->t('Operations')], '#empty' => $this->t('There are no display variants.'), '#tabledrag' => [['action' => 'order', 'relationship' => 'sibling', 'group' => 'display-variant-weight']]]; foreach ($this->entity->getVariants() as $display_variant_id => $display_variant) { $row = ['#attributes' => ['class' => ['draggable']]]; $row['label']['#markup'] = $display_variant->label(); $row['id']['#markup'] = $display_variant->adminLabel(); $row['weight'] = ['#type' => 'weight', '#default_value' => $display_variant->getWeight(), '#title' => $this->t('Weight for @display_variant display variant', ['@display_variant' => $display_variant->label()]), '#title_display' => 'invisible', '#attributes' => ['class' => ['display-variant-weight']]]; $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.display_variant_edit', ['page' => $this->entity->id(), 'display_variant_id' => $display_variant_id])]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.display_variant_delete', ['page' => $this->entity->id(), 'display_variant_id' => $display_variant_id])]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['display_variant_section']['display_variants'][$display_variant_id] = $row; } if ($access_conditions = $this->entity->getAccessConditions()) { $form['access_section_section'] = ['#type' => 'details', '#title' => $this->t('Access Conditions'), '#open' => TRUE]; $form['access_section_section']['add'] = ['#type' => 'link', '#title' => $this->t('Add new access condition'), '#url' => Url::fromRoute('page_manager.access_condition_select', ['page' => $this->entity->id()]), '#attributes' => $add_button_attributes, '#attached' => ['library' => ['core/drupal.ajax']]]; $form['access_section_section']['access_section'] = ['#type' => 'table', '#header' => [$this->t('Label'), $this->t('Description'), $this->t('Operations')], '#empty' => $this->t('There are no access conditions.')]; $form['access_section_section']['access_logic'] = ['#type' => 'radios', '#options' => ['and' => $this->t('All conditions must pass'), 'or' => $this->t('Only one condition must pass')], '#default_value' => $this->entity->getAccessLogic()]; $form['access_section_section']['access'] = ['#tree' => TRUE]; foreach ($access_conditions as $access_id => $access_condition) { $row = []; $row['label']['#markup'] = $access_condition->getPluginDefinition()['label']; $row['description']['#markup'] = $access_condition->summary(); $operations = []; $operations['edit'] = ['title' => $this->t('Edit'), 'url' => Url::fromRoute('page_manager.access_condition_edit', ['page' => $this->entity->id(), 'condition_id' => $access_id]), 'attributes' => $attributes]; $operations['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('page_manager.access_condition_delete', ['page' => $this->entity->id(), 'condition_id' => $access_id]), 'attributes' => $attributes]; $row['operations'] = ['#type' => 'operations', '#links' => $operations]; $form['access_section_section']['access_section'][$access_id] = $row; } } return $form; }
/** * Sets the raw content (e.g. HTML). * * @param string $content * The raw content to set. */ protected function setRawContent($content) { $this->content = $content; $this->plainTextContent = NULL; $this->elements = NULL; $this->drupalSettings = array(); if (preg_match('@<script type="application/json" data-drupal-selector="drupal-settings-json">([^<]*)</script>@', $content, $matches)) { $this->drupalSettings = Json::decode($matches[1]); } }
public static function genRandomExpoFront($nodenums = 1, $stickymax = 78, $storymax = 10) { $ns = 'public318'; $fetchurl = _expo_coll_fetchurl($ns); $json_fn = $ns . '-all'; $cache_fn_all = _expo_get_json_fn($json_fn); $json = WG::fetch_url($fetchurl, $cache_fn_all); $ret = Json::decode($json); $datas0 = $ret['results']; $public318_ids = [10478, 11857, 11861, 11897, 11902, 11914, 11933, 11940, 11941, 11956, 11960, 11962, 12377, 12378, 12382, 12395, 12578, 12663, 12669, 12681, 12684, 13035, 13049, 13050, 13051, 13064, 13065, 13066, 13067, 13070, 13076, 13077, 13078, 13100, 13121, 13122, 13130, 13135, 13136, 13138, 13140, 13142, 13144, 13145, 13149, 13173, 13182, 13202, 13225, 13253, 13255, 13258, 13259, 13260, 13264, 13265, 13266, 13267, 13292, 13305, 13313, 13325, 13328, 13329, 13343, 13348, 13349, 13350, 13351, 13352, 13353, 13354, 13356, 13377, 13391, 13394, 13395, 13396, 13413, 13416, 13428, 14944, 14945, 14946, 14948, 14951, 14952, 14953, 14954, 14955, 14956, 14957, 14959, 14960, 14961, 14962, 14963, 14967, 14968, 14969, 14970, 14971, 14972]; $datas = []; foreach ($datas0 as $data0) { $id = $data0['identifier']; if (in_array($id, $public318_ids)) { //echo $id.' '; $datas[$id] = $data0; } } for ($i = 1; $i <= $nodenums; $i++) { $d = []; $d['title'] = 'expo-autofront-' . date('ymdhi'); $d['public'] = 0; $d['showinfront'] = 1; $items = self::_getRandomItems2($storymax - 1, $stickymax - 1, $public318_ids); $easteregg_index = rand(0, $stickymax - 1); $el = ['itemtype' => 'story', 'id' => WG::config_get('expo.settings', 'easter_egg.nid')]; $items = DT::array_insert_element($items, $easteregg_index, $el); //print_r($items); //die(); $pos = 0; foreach ($items as $item) { $collitem = []; $collitem['weight'] = $pos; $pos++; DT::dnotice($pos . '-' . $item['itemtype'] . ':' . $item['id']); switch ($item['itemtype']) { case 'story': $collitem['target'] = 'storynode://' . $item['id']; $collitem['annotation'] = []; break; case 'public318': $id = $item['id']; //echo $id.' '; $entity = $datas[$id]; self::_fetch_public318($entity); $collitem['target'] = 'public318://' . $entity['identifier']; $text = $entity['text']; $text = str_replace(';;;', "\n", $text); $collitem['annotation'] = ['format' => 'rich_html_base', 'value' => $text]; break; } $d['collitems'][] = $collitem; } \Drupal\expo\ExpoCrud::saveExpo($d); } }
/** * Sets the raw content (e.g. HTML). * * @param string $content * The raw content to set. */ protected function setRawContent($content) { $this->content = $content; $this->plainTextContent = NULL; $this->elements = NULL; $this->drupalSettings = array(); if (preg_match('/var drupalSettings = (.*?);$/m', $content, $matches)) { $this->drupalSettings = Json::decode($matches[1]); } }
/** * @param \Symfony\Component\HttpKernel\Profiler\Profile $profile * @param \Symfony\Component\HttpFoundation\Request $request * * @return \Symfony\Component\HttpFoundation\JsonResponse */ public function savePerformanceTimingAction(Profile $profile, Request $request) { $this->profiler->disable(); $data = Json::decode($request->getContent()); /** @var $collector */ $collector = $profile->getCollector('performance_timing'); $collector->setData($data); $this->profiler->updateProfile($profile); return new JsonResponse(['success' => TRUE]); }
/** * Tests contextual links with different permissions. * * Ensures that contextual link placeholders always exist, even if the user is * not allowed to use contextual links. */ function testDifferentPermissions() { $this->drupalLogin($this->editor_user); // Create three nodes in the following order: // - An article, which should be user-editable. // - A page, which should not be user-editable. // - A second article, which should also be user-editable. $node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); $node2 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 1)); $node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1)); // Now, on the front page, all article nodes should have contextual links // placeholders, as should the view that contains them. $ids = array('node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime(), 'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime(), 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime(), 'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1'); // Editor user: can access contextual links and can edit articles. $this->drupalGet('node'); for ($i = 0; $i < count($ids); $i++) { $this->assertContextualLinkPlaceHolder($ids[$i]); } $this->renderContextualLinks(array(), 'node'); $this->assertResponse(400); $this->assertRaw('No contextual ids specified.'); $response = $this->renderContextualLinks($ids, 'node'); $this->assertResponse(200); $json = Json::decode($response); $this->assertIdentical($json[$ids[0]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/1/edit">Edit</a></li></ul>'); $this->assertIdentical($json[$ids[1]], ''); $this->assertIdentical($json[$ids[2]], '<ul class="contextual-links"><li class="entitynodeedit-form"><a href="' . base_path() . 'node/3/edit">Edit</a></li></ul>'); $this->assertIdentical($json[$ids[3]], ''); // Authenticated user: can access contextual links, cannot edit articles. $this->drupalLogin($this->authenticated_user); $this->drupalGet('node'); for ($i = 0; $i < count($ids); $i++) { $this->assertContextualLinkPlaceHolder($ids[$i]); } $this->renderContextualLinks(array(), 'node'); $this->assertResponse(400); $this->assertRaw('No contextual ids specified.'); $response = $this->renderContextualLinks($ids, 'node'); $this->assertResponse(200); $json = Json::decode($response); $this->assertIdentical($json[$ids[0]], ''); $this->assertIdentical($json[$ids[1]], ''); $this->assertIdentical($json[$ids[2]], ''); $this->assertIdentical($json[$ids[3]], ''); // Anonymous user: cannot access contextual links. $this->drupalLogin($this->anonymous_user); $this->drupalGet('node'); for ($i = 0; $i < count($ids); $i++) { $this->assertContextualLinkPlaceHolder($ids[$i]); } $this->renderContextualLinks(array(), 'node'); $this->assertResponse(403); $this->renderContextualLinks($ids, 'node'); $this->assertResponse(403); }
/** * Displays test links that will open in offcanvas tray. * * @return array * Render array with links. */ public function linksDisplay() { return [ 'offcanvas_link_1' => [ '#title' => 'Click Me 1!', '#type' => 'link', '#url' => Url::fromRoute('offcanvas_test.thing1'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', 'data-dialog-renderer' => 'offcanvas', ], '#attached' => [ 'library' => [ 'outside_in/drupal.outside_in', ], ], ], 'offcanvas_link_2' => [ '#title' => 'Click Me 2!', '#type' => 'link', '#url' => Url::fromRoute('offcanvas_test.thing2'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', 'data-dialog-renderer' => 'offcanvas', 'data-dialog-options' => Json::encode([ 'width' => 555, ]), ], '#attached' => [ 'library' => [ 'outside_in/drupal.outside_in', ], ], ], 'other_dialog_links' => [ '#title' => 'Display more links!', '#type' => 'link', '#url' => Url::fromRoute('offcanvas_test.dialog_links'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', 'data-dialog-renderer' => 'offcanvas', ], '#attached' => [ 'library' => [ 'outside_in/drupal.outside_in', ], ], ], ]; }
/** * Test comment row. */ public function testCommentRestExport() { $this->drupalGet(sprintf('node/%d/comments', $this->nodeUserCommented->id()), [], ['Accept' => 'application/hal+json']); $this->assertResponse(200); $contents = Json::decode($this->getRawContent()); $this->assertEqual($contents[0]['subject'], 'How much wood would a woodchuck chuck'); $this->assertEqual($contents[1]['subject'], 'A lot, apparently'); $this->assertEqual(count($contents), 2); // Ensure field-level access is respected - user shouldn't be able to see // mail or hostname fields. $this->assertNoText('*****@*****.**'); $this->assertNoText('public.example.com'); }
/** * Tests the UI of field handlers. */ public function testFieldUI() { // Ensure the field is not marked as hidden on the first run. $this->drupalGet('admin/structure/views/view/test_view/edit'); $this->assertText('Views test: Name'); $this->assertNoText('Views test: Name [' . t('hidden') . ']'); // Hides the field and check whether the hidden label is appended. $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/name'; $this->drupalPostForm($edit_handler_url, array('options[exclude]' => TRUE), t('Apply')); $this->assertText('Views test: Name [' . t('hidden') . ']'); // Ensure that the expected tokens appear in the UI. $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/age'; $this->drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); $this->assertEqual((string) $result[0], '{{ age }} == Age'); $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/id'; $this->drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); $this->assertEqual((string) $result[0], '{{ age }} == Age'); $this->assertEqual((string) $result[1], '{{ id }} == ID'); $edit_handler_url = 'admin/structure/views/nojs/handler/test_view/default/field/name'; $this->drupalGet($edit_handler_url); $result = $this->xpath('//details[@id="edit-options-alter-help"]/div[@class="details-wrapper"]/div[@class="item-list"]/ul/li'); $this->assertEqual((string) $result[0], '{{ age }} == Age'); $this->assertEqual((string) $result[1], '{{ id }} == ID'); $this->assertEqual((string) $result[2], '{{ name }} == Name'); $result = $this->xpath('//details[@id="edit-options-more"]'); $this->assertEqual(empty($result), TRUE, "Container 'more' is empty and should not be displayed."); // Ensure that dialog titles are not escaped. $edit_groupby_url = 'admin/structure/views/nojs/handler/test_view/default/field/name'; $this->assertNoLinkByHref($edit_groupby_url, 0, 'No aggregation link found.'); // Enable aggregation on the view. $edit = array( 'group_by' => TRUE, ); $this->drupalPostForm('/admin/structure/views/nojs/display/test_view/default/group_by', $edit, t('Apply')); $this->assertLinkByHref($edit_groupby_url, 0, 'Aggregation link found.'); $edit_handler_url = '/admin/structure/views/ajax/handler-group/test_view/default/field/name'; $this->drupalGet($edit_handler_url); $data = Json::decode($this->getRawContent()); $this->assertEqual($data[3]['dialogOptions']['title'], 'Configure aggregation settings for field Views test: Name'); }
/** * Test loading of untransformed text when a user does have access to it. */ public function testUserWithPermission() { $user = $this->drupalCreateUser(array_merge(static::$basicPermissions, array('edit any article content', 'access in-place editing'))); $this->drupalLogin($user); $this->drupalGet('node/1'); // Ensure the text is transformed. $this->assertRaw('<p>Do you also love Drupal?</p><figure role="group" class="caption caption-img"><img src="druplicon.png" /><figcaption>Druplicon</figcaption></figure>'); $response = $this->drupalPost('editor/' . 'node/1/body/en/full', 'application/vnd.drupal-ajax', array()); $this->assertResponse(200); $ajax_commands = Json::decode($response); $this->assertIdentical(1, count($ajax_commands), 'The untransformed text POST request results in one AJAX command.'); $this->assertIdentical('editorGetUntransformedText', $ajax_commands[0]['command'], 'The first AJAX command is an editorGetUntransformedText command.'); $this->assertIdentical('<p>Do you also love Drupal?</p><img src="druplicon.png" data-caption="Druplicon" />', $ajax_commands[0]['data'], 'The editorGetUntransformedText command contains the expected data.'); }
/** * Page callback to output a token tree as an empty page. */ function outputTree(Request $request) { $build['#title'] = $this->t('Available tokens'); $options = $request->query->has('options') ? Json::decode($request->query->get('options')) : array(); // Force the dialog option to be false so we're not creating a dialog within // a dialog. $options['dialog'] = FALSE; // Build a render array with the options. foreach ($options as $key => $value) { $build['tree']['#' . $key] = $value; } $build['tree']['#theme'] = 'token_tree'; return $build; }
/** * Asserts the cache context for the wrapper format is always present. */ function testWrapperFormatCacheContext() { $this->drupalGet('common-test/type-link-active-class'); $this->assertIdentical(0, strpos($this->getRawContent(), "<!DOCTYPE html>\n<html")); $this->assertIdentical('text/html; charset=UTF-8', $this->drupalGetHeader('Content-Type')); $this->assertTitle('Test active link class | Drupal'); $this->assertCacheContext('url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT); $this->drupalGet('common-test/type-link-active-class', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'json']]); $this->assertIdentical('application/json', $this->drupalGetHeader('Content-Type')); $json = Json::decode($this->getRawContent()); $this->assertEqual(['content', 'title'], array_keys($json)); $this->assertIdentical('Test active link class', $json['title']); $this->assertCacheContext('url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $main_config = $this->configFactory->get('nodejs.config'); $ext = $form_state->getValue('nodejs_config_extensions'); if ($ext == !NULL) { $ext = explode("\n", str_replace("\r", '', $ext)); } $array = array('scheme' => $form_state->getValue('nodejs_server_scheme'), 'host' => $form_state->getValue('nodejs_config_host'), 'port' => (int) $form_state->getValue('nodejs_config_port'), 'key' => $form_state->getValue('nodejs_config_key'), 'cert' => $form_state->getValue('nodejs_config_cert'), 'resource' => $form_state->getValue('nodejs_config_resource'), 'publishUrl' => $form_state->getValue('nodejs_config_publish_url'), 'serviceKey' => $main_config->get('nodejs_service_key'), 'backend' => array('port' => (int) $form_state->getValue('nodejs_config_backend_port'), 'host' => $form_state->getValue('nodejs_config_backend_host'), 'messagePath' => $form_state->getValue('nodejs_config_backend_message_path')), 'clientsCanWriteToChannels' => (bool) $form_state->getValue('nodejs_config_write_channels'), 'clientsCanWriteToClients' => (bool) $form_state->getValue('nodejs_config_write_clients'), 'extensions' => $ext, 'debug' => (bool) $form_state->getValue('nodejs_config_debug'), 'transports' => array('websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling'), 'jsMinification' => true, 'jsEtag' => true, 'logLevel' => 1); $output = 'backendSettings = ' . Json::encode($array); $output = str_replace(array('= {', ',', '}}', ':{', '\\/'), array("= {\n ", ",\n ", "\n }\n}", ":{\n ", '/'), $output); $output = "/**\n* This configuration file was built using the 'Node.js server configuration builder'.\n* For a more fully commented example see the file nodejs.config.js.example in the root of this module\n*/\n" . $output . ';'; $this->configFactory->getEditable('nodejs_config.settings')->set('js_suggestion', $output)->set('host', $form_state->getValue('nodejs_config_host'))->set('port', (int) $form_state->getValue('nodejs_config_port'))->set('scheme', $form_state->getValue('nodejs_server_scheme'))->set('key', $form_state->getValue('nodejs_config_key'))->set('cert', $form_state->getValue('nodejs_config_cert'))->set('resource', $form_state->getValue('nodejs_config_resource'))->set('publish_url', $form_state->getValue('nodejs_config_publish_url'))->set('backend_port', (int) $form_state->getValue('nodejs_config_backend_port'))->set('backend_host', $form_state->getValue('nodejs_config_backend_host'))->set('backend_message_path', $form_state->getValue('nodejs_config_backend_message_path'))->set('write_channels', (bool) $form_state->getValue('nodejs_config_write_channels'))->set('write_clients', (bool) $form_state->getValue('nodejs_config_write_clients'))->set('debug', (bool) $form_state->getValue('nodejs_config_debug'))->set('extensions', $form_state->getValue('nodejs_config_extensions'))->save(); parent::submitForm($form, $form_state); }
/** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); $menu_links_elements = $this->getMenuLinkElements($this->entity->getTargetMenu()); $layout_options = $this->getLayoutOptions(); $table_header = ['label' => $this->t('Label'), 'category' => $this->t('Category'), 'region' => $this->t('Region'), 'weight' => $this->t('Weight'), 'operations' => $this->t('Operations')]; $form['links'] = ['#type' => 'container', '#title' => $this->t('Menu links'), '#tree' => TRUE]; $blocks = $this->entity->getAllBlocksSortedByLink(); foreach ($menu_links_elements as $link_element_id => $link_element) { // Replace any dots with a underscore since dots are not supported as // keys in the configuration data. $link_element_id = str_replace('.', '_', $link_element_id); $link_layout = $this->entity->getLinkLayout($link_element_id); $regions = $this->getLayoutRegions($link_layout); $link_id = Html::getId($link_element_id); $form['links'][$link_element_id] = ['#type' => 'fieldset', '#title' => $link_element->link->getTitle()]; $form['links'][$link_element_id]['layout'] = ['#type' => 'select', '#title' => $this->t('Layout'), '#options' => $layout_options, '#default_value' => $link_layout, '#ajax' => ['callback' => '::onLayoutSelect', 'wrapper' => "mega-menu-link-{$link_id}-blocks-wrapper"], '#attributes' => ['data-link-element-id' => $link_element_id]]; $form['links'][$link_element_id]['blocks'] = ['#prefix' => '<div id="mega-menu-link-' . $link_id . '-blocks-wrapper">', '#suffix' => '</div>', '#type' => 'table', '#header' => $table_header, '#empty' => $this->t('There are no regions for blocks.')]; // Add regions. foreach ($regions as $region_key => $region_name) { // Tabledrag stuff. $form['links'][$link_element_id]['blocks']['#tabledrag'][] = ['action' => 'match', 'relationship' => 'sibling', 'group' => 'block-region-select', 'subgroup' => 'block-region-' . $region_key, 'hidden' => FALSE]; $form['links'][$link_element_id]['blocks']['#tabledrag'][] = ['action' => 'order', 'relationship' => 'sibling', 'group' => 'block-weight', 'subgroup' => 'block-weight-' . $region_key]; // Regions. $form['links'][$link_element_id]['blocks'][$region_key] = ['#attributes' => ['class' => ['region-title', 'region-title-' . $region_key], 'no_striping' => TRUE]]; if ($region_key === MegaMenuInterface::NO_REGION) { $form['links'][$link_element_id]['blocks'][$region_key]['title'] = ['#markup' => $region_name, '#wrapper_attributes' => ['colspan' => 5]]; } else { $form['links'][$link_element_id]['blocks'][$region_key]['title'] = ['#theme_wrappers' => ['container' => ['#attributes' => ['class' => ['region-title__action']]]], '#prefix' => $region_name, '#type' => 'link', '#title' => $this->t('Place block <span class="visually-hidden">in the %region region</span>', ['%region' => $region_name]), '#url' => Url::fromRoute('mega_menu.block_library', ['mega_menu' => $this->entity->id()], ['query' => ['link' => $link_element_id, 'region' => $region_key]]), '#wrapper_attributes' => ['colspan' => 5], '#attributes' => ['class' => ['use-ajax', 'button', 'button--small'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]]; } $blocks_by_region = isset($blocks[$link_element_id]) ? $blocks[$link_element_id]->getAllByRegion() : []; $region_message_class = empty($blocks_by_region[$region_key]) ? 'region-empty' : 'region-populated'; $form['links'][$link_element_id]['blocks'][$region_key . '-message'] = ['#attributes' => ['class' => ['region-message', 'region-' . $region_key . '-message', $region_message_class]]]; $form['links'][$link_element_id]['blocks'][$region_key . '-message']['message'] = ['#markup' => '<em>' . $this->t('No blocks in this region') . '</em>', '#wrapper_attributes' => ['colspan' => 5]]; if (!isset($blocks_by_region[$region_key])) { continue; } /** @var BlockPluginInterface $block */ foreach ($blocks_by_region[$region_key] as $block_id => $block) { if (!isset($form['links'][$link_element_id])) { continue; } $operations = ['edit' => ['title' => $this->t('Edit'), 'url' => Url::fromRoute('mega_menu.block_edit', ['mega_menu' => $this->entity->id(), 'block_id' => $block_id], ['query' => ['link' => $link_element_id, 'region' => $region_key]]), 'attributes' => ['class' => ['use-ajax', 'button', 'button--small'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]], 'delete' => ['title' => $this->t('Delete'), 'url' => Url::fromRoute('mega_menu.block_delete', ['mega_menu' => $this->entity->id(), 'block_id' => $block_id], ['query' => ['link' => $link_element_id]]), 'attributes' => ['class' => ['use-ajax', 'button', 'button--small'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode(['width' => 700])]]]; $configuration = $block->getConfiguration(); $form['links'][$link_element_id]['blocks'][$block_id] = ['#attributes' => ['class' => ['draggable']], 'label' => ['#markup' => $block->label()], 'category' => ['#markup' => $block->getPluginDefinition()['category']], 'region' => ['#type' => 'select', '#title' => $this->t('Region for @block block', ['@block' => $block->label()]), '#title_display' => 'invisible', '#default_value' => $region_key, '#options' => $regions, '#attributes' => ['class' => ['block-region-select', 'block-region-' . $region_key]]], 'weight' => ['#type' => 'weight', '#default_value' => isset($configuration['weight']) ? $configuration['weight'] : 0, '#title' => $this->t('Weight for @block block', ['@block' => $block->label()]), '#title_display' => 'invisible', '#attributes' => ['class' => ['block-weight', 'block-weight-' . $configuration['region']]]], 'operations' => ['#type' => 'operations', '#links' => $operations]]; } } } return $form; }
/** * Test using pre-packaged base Juicebox view. */ public function testViews() { $node = $this->node; $xml_path = 'juicebox/xml/viewsstyle/juicebox_views_test/page_1'; $xml_url = \Drupal::url('juicebox.xml_viewsstyle', array('viewName' => 'juicebox_views_test', 'displayName' => 'page_1')); // Get the urls to the test image and thumb derivative used by default. $uri = \Drupal\file\Entity\File::load($node->{$this->instFieldName}[0]->target_id)->getFileUri(); $test_image_url = entity_load('image_style', 'juicebox_medium')->buildUrl($uri); $test_thumb_url = entity_load('image_style', 'juicebox_square_thumb')->buildUrl($uri); // Check for correct embed markup. $this->drupalGet('juicebox-views-test'); $this->assertRaw(trim(json_encode(array('configUrl' => $xml_url)), '{}"'), 'Gallery setting found in Drupal.settings.'); $this->assertRaw('juicebox-views-test--page-1', 'Embed code wrapper found.'); $this->assertRaw(Html::escape($test_image_url), 'Test image found in embed code'); // Check for correct XML. $this->drupalGet($xml_path); $this->assertRaw('<?xml version="1.0" encoding="UTF-8"?>', 'Valid XML detected.'); $this->assertRaw('imageURL="' . Html::escape($test_image_url), 'Test image found in XML.'); $this->assertRaw('thumbURL="' . Html::escape($test_thumb_url), 'Test thumbnail found in XML.'); // A test leveraging fields with formattiong options also allows us to test // as additional global justboc configuration - the markup filter. The // node's title and body are mapped to the image title and caption. Most // formatting should be maintained in the caption because it's based on // a body field (with default settings to use "basic_html" text format). // However that our Juicebox markup filter should have stripped the // block-level p tags that were *added* by default by the text format. $this->assertRaw('<title><![CDATA[' . $this->node->getTitle() . ']]></title>', 'Image title text found in XML.'); $this->assertRaw('<caption><![CDATA[Some body content on node ' . $this->node->id() . ' <strong>with formatting</strong>]]></caption>', 'Image caption text found in XML.'); // Check for contextual links in embed code. It might we worth checking if // there is a more programmatic way to build the related id at some point. $this->drupalLogin($this->webUser); // Need access to contextual links. $this->drupalGet('juicebox-views-test'); $id = 'juicebox_xml_viewsstyle:viewName=juicebox_views_test&displayName=page_1:langcode=en|juicebox_conf_global::langcode=en'; $this->assertRaw('<div data-contextual-id="' . Html::escape($id) . '"></div>', 'Correct contextual link placeholders found.'); $json = Json::decode($this->renderContextualLinks(array($id), 'juicebox-views-test')); $this->assertResponse(200); $this->assertTrue(preg_match('|/' . $xml_path . '.*/admin/config/media/juicebox|', $json[$id]), 'Correct contextual links found.'); // Also test the toggle for the Juicebox markup filter. $edit = array('apply_markup_filter' => FALSE); $this->drupalPostForm('admin/config/media/juicebox', $edit, t('Save configuration')); $this->assertText(t('The Juicebox configuration options have been saved'), 'Custom global options saved.'); // Logout and test the formatting changge. $this->drupalLogout(); $this->drupalGet($xml_path); // With the filter off, the p tags in our example caption should come // through. $this->assertRaw('<caption><![CDATA[<p>Some body content on node ' . $this->node->id() . ' <strong>with formatting</strong></p>', 'Image caption text found in XML.'); }