/** * Loads the cached form state. * * @param string $form_build_id * The unique form build ID. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. */ protected function loadCachedFormState($form_build_id, FormStateInterface $form_state) { if ($stored_form_state = $this->keyValueExpirableFactory->get('form_state')->get($form_build_id)) { // Re-populate $form_state for subsequent rebuilds. $form_state->setFormState($stored_form_state); // If the original form is contained in include files, load the files. // @see \Drupal\Core\Form\FormStateInterface::loadInclude() $build_info = $form_state->getBuildInfo(); $build_info += ['files' => []]; foreach ($build_info['files'] as $file) { if (is_array($file)) { $file += array('type' => 'inc', 'name' => $file['module']); $this->moduleHandler->loadInclude($file['module'], $file['type'], $file['name']); } elseif (file_exists($file)) { require_once $this->root . '/' . $file; } } // Retrieve the list of previously known safe strings and store it for // this request. // @todo Ensure we are not storing an excessively large string list // in: https://www.drupal.org/node/2295823 $build_info += ['safe_strings' => []]; SafeMarkup::setMultiple($build_info['safe_strings']); unset($build_info['safe_strings']); $form_state->setBuildInfo($build_info); } }
/** * {@inheritdoc} */ public function getCache($form_build_id, &$form_state) { if ($form = $this->keyValueExpirableFactory->get('form')->get($form_build_id)) { $user = $this->currentUser(); if (isset($form['#cache_token']) && $this->csrfToken->validate($form['#cache_token']) || !isset($form['#cache_token']) && $user->isAnonymous()) { if ($stored_form_state = $this->keyValueExpirableFactory->get('form_state')->get($form_build_id)) { // Re-populate $form_state for subsequent rebuilds. $form_state = $stored_form_state + $form_state; // If the original form is contained in include files, load the files. // @see form_load_include() $form_state['build_info'] += array('files' => array()); foreach ($form_state['build_info']['files'] as $file) { if (is_array($file)) { $file += array('type' => 'inc', 'name' => $file['module']); $this->moduleHandler->loadInclude($file['module'], $file['type'], $file['name']); } elseif (file_exists($file)) { require_once DRUPAL_ROOT . '/' . $file; } } // Retrieve the list of previously known safe strings and store it // for this request. // @todo Ensure we are not storing an excessively large string list // in: https://www.drupal.org/node/2295823 $form_state['build_info'] += array('safe_strings' => array()); SafeMarkup::setMultiple($form_state['build_info']['safe_strings']); unset($form_state['build_info']['safe_strings']); } return $form; } } }
/** * @covers ::setCache */ public function testSetCacheWithSafeStrings() { SafeMarkup::setMultiple([ 'a_safe_string' => ['html' => TRUE], ]); $form_build_id = 'the_form_build_id'; $form = [ '#form_id' => 'the_form_id' ]; $form_state = new FormState(); $this->formCacheStore->expects($this->once()) ->method('setWithExpire') ->with($form_build_id, $form, $this->isType('int')); $form_state_data = $form_state->getCacheableArray(); $form_state_data['build_info']['safe_strings'] = [ 'a_safe_string' => ['html' => TRUE], ]; $this->formStateCacheStore->expects($this->once()) ->method('setWithExpire') ->with($form_build_id, $form_state_data, $this->isType('int')); $this->formCache->setCache($form_build_id, $form, $form_state); }
/** * Tests SafeMarkup::setMultiple(). * * Only TRUE may be passed in as the value. * * @covers ::setMultiple * * @expectedException \UnexpectedValueException */ public function testInvalidSetMultiple() { $texts = array('invalidstring0' => array('html' => 1)); SafeMarkup::setMultiple($texts); }
/** * @covers ::safeJoin */ public function testSafeJoin() { $renderer = $this->prophesize(RendererInterface::class); $renderer->render(['#markup' => '<strong>will be rendered</strong>', '#printed' => FALSE])->willReturn('<strong>will be rendered</strong>'); $renderer = $renderer->reveal(); $twig_extension = new TwigExtension($renderer); $twig_environment = $this->prophesize(TwigEnvironment::class)->reveal(); // Simulate t(). $string = '<em>will be markup</em>'; SafeMarkup::setMultiple([$string => ['html' => TRUE]]); $items = [ '<em>will be escaped</em>', $string, ['#markup' => '<strong>will be rendered</strong>'] ]; $result = $twig_extension->safeJoin($twig_environment, $items, '<br/>'); $this->assertEquals('<em>will be escaped</em><br/><em>will be markup</em><br/><strong>will be rendered</strong>', $result); }
/** * {@inheritdoc} */ public function translate($string, array $args = array(), array $options = array()) { $string = $this->doTranslate($string, $options); if (empty($args)) { // We add the string to the safe list as opposed to making it an object // implementing SafeStringInterface as we may need to call __toString() // on the object before render time, at which point the string ceases to // be safe, and working around this would require significant rework. // Adding this string to the safe list is assumed to be safe because // translate() should only be called with strings defined in code. // @see \Drupal\Core\StringTranslation\TranslationInterface::translate() SafeMarkup::setMultiple([$string => ['html' => TRUE]]); return $string; } else { return SafeMarkup::format($string, $args); } }