Update to Drupal 8.2.5. For more information, see https://www.drupal.org/project/drupal/releases/8.2.5
This commit is contained in:
		
							parent
							
								
									8544b60b39
								
							
						
					
					
						commit
						db56c09587
					
				
					 86 changed files with 2413 additions and 488 deletions
				
			
		|  | @ -123,7 +123,6 @@ Color | |||
| - ? | ||||
| 
 | ||||
| Comment | ||||
| - Dick Olsson 'dixon_' https://www.drupal.org/u/dixon_ | ||||
| - Lee Rowlands 'larowlan' https://www.drupal.org/u/larowlan | ||||
| - Andrey Postnikov 'andypost' https://www.drupal.org/u/andypost | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,7 +74,7 @@ function drupal_get_schema_versions($module) { | |||
|  *   module is not installed. | ||||
|  */ | ||||
| function drupal_get_installed_schema_version($module, $reset = FALSE, $array = FALSE) { | ||||
|   static $versions = array(); | ||||
|   $versions = &drupal_static(__FUNCTION__, array()); | ||||
| 
 | ||||
|   if ($reset) { | ||||
|     $versions = array(); | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ class Drupal { | |||
|   /** | ||||
|    * The current system version. | ||||
|    */ | ||||
|   const VERSION = '8.2.4'; | ||||
|   const VERSION = '8.2.5'; | ||||
| 
 | ||||
|   /** | ||||
|    * Core API compatibility. | ||||
|  | @ -556,8 +556,7 @@ class Drupal { | |||
|    * Renders a link with a given link text and Url object. | ||||
|    * | ||||
|    * This method is a convenience wrapper for the link generator service's | ||||
|    * generate() method. For detailed documentation, see | ||||
|    * \Drupal\Core\Routing\LinkGeneratorInterface::generate(). | ||||
|    * generate() method. | ||||
|    * | ||||
|    * @param string $text | ||||
|    *   The link text for the anchor tag. | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ use Drupal\Core\Render\Element; | |||
|  * Properties: | ||||
|  * - #default_value: An array with the keys: 'year', 'month', and 'day'.
 | ||||
|  *   Defaults to the current date if no value is supplied. | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * @code | ||||
|  * $form['expiration'] = array( | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ use Drupal\Core\Render\Element; | |||
|  * | ||||
|  * Properties: | ||||
|  * - #default_value: An RFC-compliant email address.
 | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Example usage: | ||||
|  * @code | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ use Drupal\Component\Utility\Number as NumberUtility; | |||
|  * - #step: Ensures that the number is an even multiple of step, offset by #min
 | ||||
|  *   if specified. A #min of 1 and a #step of 2 would allow values of 1, 3, 5,
 | ||||
|  *   etc. | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  |  | |||
|  | @ -8,6 +8,9 @@ use Drupal\Core\Render\Element; | |||
| /** | ||||
|  * Provides a form element for entering a password, with hidden text. | ||||
|  * | ||||
|  * Properties: | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  * $form['pass'] = array( | ||||
|  |  | |||
|  | @ -10,6 +10,9 @@ use Drupal\Core\Form\FormStateInterface; | |||
|  * Formats as a pair of password fields, which do not validate unless the two | ||||
|  * entered passwords match. | ||||
|  * | ||||
|  * Properties: | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  * $form['pass'] = array( | ||||
|  |  | |||
|  | @ -14,8 +14,31 @@ use Drupal\Core\Render\Element; | |||
|  *   list. If a value is an array, it will be rendered similarly, but as an | ||||
|  *   optgroup. The key of the sub-array will be used as the label for the | ||||
|  *   optgroup. Nesting optgroups is not allowed. | ||||
|  * - #empty_option: The label that will be displayed to denote no selection.
 | ||||
|  * - #empty_value: The value of the option that is used to denote no selection.
 | ||||
|  * - #empty_option: (optional) The label to show for the first default option.
 | ||||
|  *   By default, the label is automatically set to "- Select -" for a required | ||||
|  *   field and "- None -" for an optional field. | ||||
|  * - #empty_value: (optional) The value for the first default option, which is
 | ||||
|  *   used to determine whether the user submitted a value or not. | ||||
|  *   - If #required is TRUE, this defaults to '' (an empty string).
 | ||||
|  *   - If #required is not TRUE and this value isn't set, then no extra option
 | ||||
|  *     is added to the select control, leaving the control in a slightly | ||||
|  *     illogical state, because there's no way for the user to select nothing, | ||||
|  *     since all user agents automatically preselect the first available | ||||
|  *     option. But people are used to this being the behavior of select | ||||
|  *     controls. | ||||
|  *     @todo Address the above issue in Drupal 8. | ||||
|  *   - If #required is not TRUE and this value is set (most commonly to an
 | ||||
|  *     empty string), then an extra option (see #empty_option above)
 | ||||
|  *     representing a "non-selection" is added with this as its value. | ||||
|  * - #multiple: (optional) Indicates whether one or more options can be
 | ||||
|  *   selected. Defaults to FALSE. | ||||
|  * - #default_value: Must be NULL or not set in case there is no value for the
 | ||||
|  *   element yet, in which case a first default option is inserted by default. | ||||
|  *   Whether this first option is a valid option depends on whether the field | ||||
|  *   is #required or not.
 | ||||
|  * - #required: (optional) Whether the user needs to select an option (TRUE)
 | ||||
|  *   or not (FALSE). Defaults to FALSE. | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  | @ -66,31 +89,7 @@ class Select extends FormElement { | |||
|    * select lists. | ||||
|    * | ||||
|    * @param array $element | ||||
|    *   The form element to process. Properties used: | ||||
|    *   - #multiple: (optional) Indicates whether one or more options can be
 | ||||
|    *     selected. Defaults to FALSE. | ||||
|    *   - #default_value: Must be NULL or not set in case there is no value for the
 | ||||
|    *     element yet, in which case a first default option is inserted by default. | ||||
|    *     Whether this first option is a valid option depends on whether the field | ||||
|    *     is #required or not.
 | ||||
|    *   - #required: (optional) Whether the user needs to select an option (TRUE)
 | ||||
|    *     or not (FALSE). Defaults to FALSE. | ||||
|    *   - #empty_option: (optional) The label to show for the first default option.
 | ||||
|    *     By default, the label is automatically set to "- Select -" for a required | ||||
|    *     field and "- None -" for an optional field. | ||||
|    *   - #empty_value: (optional) The value for the first default option, which is
 | ||||
|    *     used to determine whether the user submitted a value or not. | ||||
|    *     - If #required is TRUE, this defaults to '' (an empty string).
 | ||||
|    *     - If #required is not TRUE and this value isn't set, then no extra option
 | ||||
|    *       is added to the select control, leaving the control in a slightly | ||||
|    *       illogical state, because there's no way for the user to select nothing, | ||||
|    *       since all user agents automatically preselect the first available | ||||
|    *       option. But people are used to this being the behavior of select | ||||
|    *       controls. | ||||
|    *       @todo Address the above issue in Drupal 8. | ||||
|    *     - If #required is not TRUE and this value is set (most commonly to an
 | ||||
|    *       empty string), then an extra option (see #empty_option above)
 | ||||
|    *       representing a "non-selection" is added with this as its value. | ||||
|    *   The form element to process. | ||||
|    * @param \Drupal\Core\Form\FormStateInterface $form_state | ||||
|    *   The current state of the form. | ||||
|    * @param array $complete_form | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ use Drupal\Component\Utility\Html as HtmlUtility; | |||
|  *   providing responsive tables.  Defaults to TRUE. | ||||
|  * - #sticky: Indicates whether to add the drupal.tableheader library that makes
 | ||||
|  *   table headers always visible at the top of the page. Defaults to FALSE. | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  |  | |||
|  | @ -10,6 +10,9 @@ use Drupal\Core\Render\Element; | |||
|  * Provides an HTML5 input element with type of "tel". It provides no special | ||||
|  * validation. | ||||
|  * | ||||
|  * Properties: | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  * $form['phone'] = array( | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ use Drupal\Core\Render\Element; | |||
|  * | ||||
|  * Properties: | ||||
|  * - #default_value: A valid URL string.
 | ||||
|  * - #size: The size of the input element in characters.
 | ||||
|  * | ||||
|  * Usage example: | ||||
|  * @code | ||||
|  |  | |||
|  | @ -254,13 +254,13 @@ | |||
|  * form array, which specifies the form elements for an HTML form; see the | ||||
|  * @link form_api Form generation topic @endlink for more information on forms. | ||||
|  * | ||||
|  * Render arrays (at each level in the hierarchy) will usually have one of the | ||||
|  * following three properties defined: | ||||
|  * Render arrays (at any level of the hierarchy) will usually have one of the | ||||
|  * following properties defined: | ||||
|  * - #type: Specifies that the array contains data and options for a particular
 | ||||
|  *   type of "render element" (examples: 'form', for an HTML form; 'textfield', | ||||
|  *   'submit', and other HTML form element types; 'table', for a table with | ||||
|  *   rows, columns, and headers). See @ref elements below for more on render | ||||
|  *   element types. | ||||
|  *   type of "render element" (for example, 'form', for an HTML form; | ||||
|  *   'textfield', 'submit', for HTML form element types; 'table', for a table | ||||
|  *   with rows, columns, and headers). See @ref elements below for more on | ||||
|  *   render element types. | ||||
|  * - #theme: Specifies that the array contains data to be themed by a particular
 | ||||
|  *   theme hook. Modules define theme hooks by implementing hook_theme(), which | ||||
|  *   specifies the input "variables" used to provide data and options; if a | ||||
|  | @ -277,30 +277,29 @@ | |||
|  *   can customize the markup. Note that the value is passed through | ||||
|  *   \Drupal\Component\Utility\Xss::filterAdmin(), which strips known XSS | ||||
|  *   vectors while allowing a permissive list of HTML tags that are not XSS | ||||
|  *   vectors. (I.e, <script> and <style> are not allowed.) See | ||||
|  *   \Drupal\Component\Utility\Xss::$adminTags for the list of tags that will | ||||
|  *   be allowed. If your markup needs any of the tags that are not in this | ||||
|  *   whitelist, then you can implement a theme hook and template file and/or | ||||
|  *   an asset library. Aternatively, you can use the render array key | ||||
|  *   #allowed_tags to alter which tags are filtered.
 | ||||
|  *   vectors. (For example, <script> and <style> are not allowed.) See | ||||
|  *   \Drupal\Component\Utility\Xss::$adminTags for the list of allowed tags. If | ||||
|  *   your markup needs any of the tags not in this whitelist, then you can | ||||
|  *   implement a theme hook and/or an asset library. Alternatively, you can use | ||||
|  *   the key #allowed_tags to alter which tags are filtered.
 | ||||
|  * - #plain_text: Specifies that the array provides text that needs to be
 | ||||
|  *   escaped. This value takes precedence over #markup if present.
 | ||||
|  * - #allowed_tags: If #markup is supplied this can be used to change which tags
 | ||||
|  *   are using to filter the markup. The value should be an array of tags that | ||||
|  *   Xss::filter() would accept. If #plain_text is set this value is ignored.
 | ||||
|  *   escaped. This value takes precedence over #markup.
 | ||||
|  * - #allowed_tags: If #markup is supplied, this can be used to change which
 | ||||
|  *   tags are allowed in the markup. The value is an array of tags that | ||||
|  *   Xss::filter() would accept. If #plain_text is set, this value is ignored.
 | ||||
|  * | ||||
|  *   Usage example: | ||||
|  *   @code | ||||
|  *   $output['admin_filtered_string'] = array( | ||||
|  *   $output['admin_filtered_string'] = [ | ||||
|  *     '#markup' => '<em>This is filtered using the admin tag list</em>', | ||||
|  *   ); | ||||
|  *   $output['filtered_string'] = array( | ||||
|  *     '#markup' => '<em>This is filtered</em>', | ||||
|  *     '#allowed_tags' => ['strong'], | ||||
|  *   ); | ||||
|  *   $output['escaped_string'] = array( | ||||
|  *   ]; | ||||
|  *   $output['filtered_string'] = [ | ||||
|  *     '#markup' => '<video><source src="v.webm" type="video/webm"></video>', | ||||
|  *     '#allowed_tags' => ['video', 'source'], | ||||
|  *   ]; | ||||
|  *   $output['escaped_string'] = [ | ||||
|  *     '#plain_text' => '<em>This is escaped</em>', | ||||
|  *   ); | ||||
|  *   ]; | ||||
|  *   @endcode | ||||
|  * | ||||
|  *   @see core.libraries.yml | ||||
|  |  | |||
|  | @ -138,6 +138,12 @@ interface BigPipeInterface { | |||
|    *   The HTML response content to send. | ||||
|    * @param array $attachments | ||||
|    *   The HTML response's attachments. | ||||
|    * | ||||
|    * @internal | ||||
|    *   This method should only be invoked by | ||||
|    *   \Drupal\big_pipe\Render\BigPipeResponse, which is itself an internal | ||||
|    *   class. Furthermore, the signature of this method will change in | ||||
|    *   https://www.drupal.org/node/2657684. | ||||
|    */ | ||||
|   public function sendContent($content, array $attachments); | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,7 +13,10 @@ use Drupal\Core\Render\HtmlResponse; | |||
|  * | ||||
|  * @see \Drupal\big_pipe\Render\BigPipeInterface | ||||
|  * | ||||
|  * @todo Will become obsolete with https://www.drupal.org/node/2577631 | ||||
|  * @internal | ||||
|  *   This is a temporary solution until a generic response emitter interface is | ||||
|  *   created in https://www.drupal.org/node/2577631. Only code internal to | ||||
|  *   BigPipe should instantiate or type hint to this class. | ||||
|  */ | ||||
| class BigPipeResponse extends HtmlResponse { | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										14
									
								
								core/modules/ckeditor/js/ckeditor.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								core/modules/ckeditor/js/ckeditor.js
									
										
									
									
										vendored
									
									
								
							|  | @ -273,6 +273,20 @@ | |||
|     } | ||||
|   }); | ||||
| 
 | ||||
|   // Redirect on hash change when the original hash has an associated CKEditor.
 | ||||
|   function redirectTextareaFragmentToCKEditorInstance() { | ||||
|     var hash = location.hash.substr(1); | ||||
|     var element = document.getElementById(hash); | ||||
|     if (element) { | ||||
|       var editor = CKEDITOR.dom.element.get(element).getEditor(); | ||||
|       if (editor) { | ||||
|         var id = editor.container.getAttribute('id'); | ||||
|         location.replace('#' + id); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   $(window).on('hashchange.ckeditor', redirectTextareaFragmentToCKEditorInstance); | ||||
| 
 | ||||
|   // Set the CKEditor cache-busting string to the same value as Drupal.
 | ||||
|   CKEDITOR.timestamp = drupalSettings.ckeditor.timestamp; | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,121 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\ckeditor\FunctionalJavascript; | ||||
| 
 | ||||
| use Drupal\Core\Entity\Entity\EntityFormDisplay; | ||||
| use Drupal\editor\Entity\Editor; | ||||
| use Drupal\field\Entity\FieldConfig; | ||||
| use Drupal\field\Entity\FieldStorageConfig; | ||||
| use Drupal\filter\Entity\FilterFormat; | ||||
| use Drupal\FunctionalJavascriptTests\JavascriptTestBase; | ||||
| use Drupal\node\Entity\NodeType; | ||||
| 
 | ||||
| /** | ||||
|  * Tests the integration of CKEditor. | ||||
|  * | ||||
|  * @group ckeditor | ||||
|  */ | ||||
| class CKEditorIntegrationTest extends JavascriptTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * The account. | ||||
|    * | ||||
|    * @var \Drupal\user\UserInterface | ||||
|    */ | ||||
|   protected $account; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = ['node', 'ckeditor', 'filter']; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
| 
 | ||||
|     // Create a text format and associate CKEditor.
 | ||||
|     $filtered_html_format = FilterFormat::create([ | ||||
|       'format' => 'filtered_html', | ||||
|       'name' => 'Filtered HTML', | ||||
|       'weight' => 0, | ||||
|     ]); | ||||
|     $filtered_html_format->save(); | ||||
| 
 | ||||
|     Editor::create([ | ||||
|       'format' => 'filtered_html', | ||||
|       'editor' => 'ckeditor', | ||||
|     ])->save(); | ||||
| 
 | ||||
|     // Create a node type for testing.
 | ||||
|     NodeType::create(['type' => 'page', 'name' => 'page'])->save(); | ||||
| 
 | ||||
|     $field_storage = FieldStorageConfig::loadByName('node', 'body'); | ||||
| 
 | ||||
|     // Create a body field instance for the 'page' node type.
 | ||||
|     FieldConfig::create([ | ||||
|       'field_storage' => $field_storage, | ||||
|       'bundle' => 'page', | ||||
|       'label' => 'Body', | ||||
|       'settings' => ['display_summary' => TRUE], | ||||
|       'required' => TRUE, | ||||
|     ])->save(); | ||||
| 
 | ||||
|     // Assign widget settings for the 'default' form mode.
 | ||||
|     EntityFormDisplay::create([ | ||||
|       'targetEntityType' => 'node', | ||||
|       'bundle' => 'page', | ||||
|       'mode' => 'default', | ||||
|       'status' => TRUE, | ||||
|     ])->setComponent('body', ['type' => 'text_textarea_with_summary']) | ||||
|       ->save(); | ||||
| 
 | ||||
|     $this->account = $this->drupalCreateUser([ | ||||
|       'administer nodes', | ||||
|       'create page content', | ||||
|       'use text format filtered_html', | ||||
|     ]); | ||||
|     $this->drupalLogin($this->account); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests if the fragment link to a textarea works with CKEditor enabled. | ||||
|    */ | ||||
|   public function testFragmentLink() { | ||||
|     $session = $this->getSession(); | ||||
|     $web_assert = $this->assertSession(); | ||||
|     $ckeditor_id = '#cke_edit-body-0-value'; | ||||
| 
 | ||||
|     $this->drupalGet('node/add/page'); | ||||
| 
 | ||||
|     $session->getPage(); | ||||
| 
 | ||||
|     // Add a bottom margin to the title field to be sure the body field is not
 | ||||
|     // visible. PhantomJS runs with a resolution of 1024x768px.
 | ||||
|     $session->executeScript("document.getElementById('edit-title-0-value').style.marginBottom = '800px';"); | ||||
| 
 | ||||
|     // Check that the CKEditor-enabled body field is currently not visible in
 | ||||
|     // the viewport.
 | ||||
|     $web_assert->assertNotVisibleInViewport('css', $ckeditor_id, 'topLeft', 'CKEditor-enabled body field is visible.'); | ||||
| 
 | ||||
|     $before_url = $session->getCurrentUrl(); | ||||
| 
 | ||||
|     // Trigger a hash change with as target the hidden textarea.
 | ||||
|     $session->executeScript("location.hash = '#edit-body-0-value';"); | ||||
| 
 | ||||
|     // Check that the CKEditor-enabled body field is visible in the viewport.
 | ||||
|     $web_assert->assertVisibleInViewport('css', $ckeditor_id, 'topLeft', 'CKEditor-enabled body field is not visible.'); | ||||
| 
 | ||||
|     // Use JavaScript to go back in the history instead of
 | ||||
|     // \Behat\Mink\Session::back() because that function doesn't work after a
 | ||||
|     // hash change.
 | ||||
|     $session->executeScript("history.back();"); | ||||
| 
 | ||||
|     $after_url = $session->getCurrentUrl(); | ||||
| 
 | ||||
|     // Check that going back in the history worked.
 | ||||
|     self::assertEquals($before_url, $after_url, 'History back works.'); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -36,3 +36,4 @@ migration_dependencies: | |||
|   optional: | ||||
|     - d7_node_type | ||||
|     - d7_comment_type | ||||
|     - d7_taxonomy_vocabulary | ||||
|  |  | |||
|  | @ -96,13 +96,9 @@ function file_requirements($phase) { | |||
|       $value = t('Not enabled'); | ||||
|       $description = t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php or PHP-FPM and not as FastCGI.'); | ||||
|     } | ||||
|     elseif (!$implementation && extension_loaded('apcu')) { | ||||
|       $value = t('Not enabled'); | ||||
|       $description = t('Your server is capable of displaying file upload progress through APC, but it is not enabled. Add <code>apc.rfc1867 = 1</code> to your php.ini configuration. Alternatively, it is recommended to use <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>, which supports more than one simultaneous upload.'); | ||||
|     } | ||||
|     elseif (!$implementation) { | ||||
|       $value = t('Not enabled'); | ||||
|       $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a> (preferred) or to install <a href="http://php.net/apcu">APC</a>.'); | ||||
|       $description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a>.'); | ||||
|     } | ||||
|     elseif ($implementation == 'apc') { | ||||
|       $value = t('Enabled (<a href="http://php.net/manual/apcu.configuration.php#ini.apcu.rfc1867">APC RFC1867</a>)'); | ||||
|  |  | |||
|  | @ -929,7 +929,7 @@ function file_progress_implementation() { | |||
|     if (extension_loaded('uploadprogress')) { | ||||
|       $implementation = 'uploadprogress'; | ||||
|     } | ||||
|     elseif (extension_loaded('apc') && ini_get('apc.rfc1867')) { | ||||
|     elseif (version_compare(PHP_VERSION, '7', '<') && extension_loaded('apc') && ini_get('apc.rfc1867')) { | ||||
|       $implementation = 'apc'; | ||||
|     } | ||||
|   } | ||||
|  |  | |||
|  | @ -291,6 +291,21 @@ class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface { | |||
|     return $new_values; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) { | ||||
|     parent::extractFormValues($items, $form, $form_state); | ||||
| 
 | ||||
|     // Update reference to 'items' stored during upload to take into account
 | ||||
|     // changes to values like 'alt' etc.
 | ||||
|     // @see \Drupal\file\Plugin\Field\FieldWidget\FileWidget::submit()
 | ||||
|     $field_name = $this->fieldDefinition->getName(); | ||||
|     $field_state = static::getWidgetState($form['#parents'], $field_name, $form_state); | ||||
|     $field_state['items'] = $items->getValue(); | ||||
|     static::setWidgetState($form['#parents'], $field_name, $form_state, $field_state); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Form API callback. Retrieves the value for the file_generic field element. | ||||
|    * | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| id: d7_filter_settings | ||||
| label: Drupal 7 filter settings | ||||
| migration_tags: | ||||
|   - Drupal 7 | ||||
| source: | ||||
|   plugin: variable | ||||
|   variables: | ||||
|     - filter_fallback_format | ||||
| process: | ||||
|   fallback_format: filter_fallback_format | ||||
| destination: | ||||
|   plugin: config | ||||
|   config_name: filter.settings | ||||
|  | @ -0,0 +1,32 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\filter\Kernel\Migrate\d7; | ||||
| 
 | ||||
| use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; | ||||
| 
 | ||||
| /** | ||||
|  * Tests migration of Filter's settings to configuration. | ||||
|  * | ||||
|  * @group filter | ||||
|  */ | ||||
| class MigrateFilterSettingsTest extends MigrateDrupal7TestBase { | ||||
| 
 | ||||
|   public static $modules = ['filter']; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
|     $this->installConfig(static::$modules); | ||||
|     $this->executeMigration('d7_filter_settings'); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests migration of Filter variables to configuration. | ||||
|    */ | ||||
|   public function testFilterSettings() { | ||||
|     $this->assertSame('plain_text', $this->config('filter.settings')->get('fallback_format')); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,111 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\inline_form_errors\FunctionalJavascript; | ||||
| 
 | ||||
| use Drupal\Core\Entity\Entity\EntityFormDisplay; | ||||
| use Drupal\editor\Entity\Editor; | ||||
| use Drupal\field\Entity\FieldConfig; | ||||
| use Drupal\field\Entity\FieldStorageConfig; | ||||
| use Drupal\filter\Entity\FilterFormat; | ||||
| use Drupal\FunctionalJavascriptTests\JavascriptTestBase; | ||||
| use Drupal\node\Entity\NodeType; | ||||
| 
 | ||||
| /** | ||||
|  * Tests the inline errors fragment link to a CKEditor-enabled textarea. | ||||
|  * | ||||
|  * @group ckeditor | ||||
|  */ | ||||
| class FormErrorHandlerCKEditorTest extends JavascriptTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = ['node', 'ckeditor', 'inline_form_errors', 'filter']; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
| 
 | ||||
|     // Create a text format and associate CKEditor.
 | ||||
|     $filtered_html_format = FilterFormat::create([ | ||||
|       'format' => 'filtered_html', | ||||
|       'name' => 'Filtered HTML', | ||||
|       'weight' => 0, | ||||
|     ]); | ||||
|     $filtered_html_format->save(); | ||||
| 
 | ||||
|     Editor::create([ | ||||
|       'format' => 'filtered_html', | ||||
|       'editor' => 'ckeditor', | ||||
|     ])->save(); | ||||
| 
 | ||||
|     // Create a node type for testing.
 | ||||
|     NodeType::create(['type' => 'page', 'name' => 'page'])->save(); | ||||
| 
 | ||||
|     $field_storage = FieldStorageConfig::loadByName('node', 'body'); | ||||
| 
 | ||||
|     // Create a body field instance for the 'page' node type.
 | ||||
|     FieldConfig::create([ | ||||
|       'field_storage' => $field_storage, | ||||
|       'bundle' => 'page', | ||||
|       'label' => 'Body', | ||||
|       'settings' => ['display_summary' => TRUE], | ||||
|       'required' => TRUE, | ||||
|     ])->save(); | ||||
| 
 | ||||
|     // Assign widget settings for the 'default' form mode.
 | ||||
|     EntityFormDisplay::create([ | ||||
|       'targetEntityType' => 'node', | ||||
|       'bundle' => 'page', | ||||
|       'mode' => 'default', | ||||
|       'status' => TRUE, | ||||
|     ])->setComponent('body', ['type' => 'text_textarea_with_summary']) | ||||
|       ->save(); | ||||
| 
 | ||||
|     $account = $this->drupalCreateUser([ | ||||
|       'administer nodes', | ||||
|       'create page content', | ||||
|       'use text format filtered_html', | ||||
|     ]); | ||||
|     $this->drupalLogin($account); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests if the fragment link to a textarea works with CKEditor enabled. | ||||
|    */ | ||||
|   public function testFragmentLink() { | ||||
|     $session = $this->getSession(); | ||||
|     $web_assert = $this->assertSession(); | ||||
|     $ckeditor_id = '#cke_edit-body-0-value'; | ||||
| 
 | ||||
|     $this->drupalGet('node/add/page'); | ||||
| 
 | ||||
|     $page = $this->getSession()->getPage(); | ||||
| 
 | ||||
|     // Only enter a title in the node add form and leave the body field empty.
 | ||||
|     $edit = ['edit-title-0-value' => 'Test inline form error with CKEditor']; | ||||
| 
 | ||||
|     $this->submitForm($edit, 'Save and publish'); | ||||
| 
 | ||||
|     // Add a bottom margin to the title field to be sure the body field is not
 | ||||
|     // visible. PhantomJS runs with a resolution of 1024x768px.
 | ||||
|     $session->executeScript("document.getElementById('edit-title-0-value').style.marginBottom = '800px';"); | ||||
| 
 | ||||
|     // Check that the CKEditor-enabled body field is currently not visible in
 | ||||
|     // the viewport.
 | ||||
|     $web_assert->assertNotVisibleInViewport('css', $ckeditor_id, 'topLeft', 'CKEditor-enabled body field is not visible.'); | ||||
| 
 | ||||
|     // Check if we can find the error fragment link within the errors summary
 | ||||
|     // message.
 | ||||
|     $errors_link = $page->find('css', '.messages--error a[href=\#edit-body-0-value]'); | ||||
|     $this->assertTrue($errors_link->isVisible(), 'Error fragment link is visible.'); | ||||
| 
 | ||||
|     $errors_link->click(); | ||||
| 
 | ||||
|     // Check that the CKEditor-enabled body field is visible in the viewport.
 | ||||
|     $web_assert->assertVisibleInViewport('css', $ckeditor_id, 'topLeft', 'CKEditor-enabled body field is visible.'); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -20,7 +20,7 @@ process: | |||
|       plugin: skip_on_empty | ||||
|       method: row | ||||
|   'link/uri': | ||||
|     plugin: d7_internal_uri | ||||
|     plugin: link_uri | ||||
|     source: | ||||
|       - link_path | ||||
|   'link/options': options | ||||
|  |  | |||
|  | @ -63,6 +63,9 @@ class LinkUri extends ProcessPluginBase implements ContainerFactoryPluginInterfa | |||
|     $path = ltrim($path, '/'); | ||||
| 
 | ||||
|     if (parse_url($path, PHP_URL_SCHEME) === NULL) { | ||||
|       if ($path == '<front>') { | ||||
|         $path = ''; | ||||
|       } | ||||
|       $path = 'internal:/' . $path; | ||||
| 
 | ||||
|       // Convert entity URIs to the entity scheme, if the path matches a route
 | ||||
|  |  | |||
|  | @ -2,42 +2,12 @@ | |||
| 
 | ||||
| namespace Drupal\menu_link_content\Plugin\migrate\process\d7; | ||||
| 
 | ||||
| use Drupal\migrate\MigrateExecutableInterface; | ||||
| use Drupal\migrate\ProcessPluginBase; | ||||
| use Drupal\migrate\Row; | ||||
| use Drupal\menu_link_content\Plugin\migrate\process\LinkUri; | ||||
| 
 | ||||
| /** | ||||
|  * Process a path into an 'internal:' URI. | ||||
|  * Processes an internal uri into an 'internal:' or 'entity:' URI. | ||||
|  * | ||||
|  * @MigrateProcessPlugin( | ||||
|  *   id = "d7_internal_uri" | ||||
|  * ) | ||||
|  * @deprecated in Drupal 8.2.0, will be removed before Drupal 9.0.0. Use | ||||
|  * \Drupal\menu_link_content\Plugin\migrate\process\LinkUri instead. | ||||
|  */ | ||||
| class InternalUri extends ProcessPluginBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { | ||||
|     list($path) = $value; | ||||
|     $path = ltrim($path, '/'); | ||||
| 
 | ||||
|     if (parse_url($path, PHP_URL_SCHEME) == NULL) { | ||||
|       // If $path is the node page (i.e. node/[nid]) then return entity path.
 | ||||
|       if (preg_match('/^node\/\d+$/', $path)) { | ||||
|         // "entity: URI"s enable the menu link to appear in the Menu Settings
 | ||||
|         // section on the node edit page. Other entities (e.g. taxonomy terms,
 | ||||
|         // users) do not have the Menu Settings section.
 | ||||
|         return 'entity:' . $path; | ||||
|       } | ||||
|       elseif ($path == '<front>') { | ||||
|         return 'internal:/'; | ||||
|       } | ||||
|       else { | ||||
|         return 'internal:/' . $path; | ||||
|       } | ||||
|     } | ||||
|     return $path; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| class InternalUri extends LinkUri {} | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ namespace Drupal\Tests\menu_link_content\Kernel\Migrate\d7; | |||
| use Drupal\Core\Menu\MenuTreeParameters; | ||||
| use Drupal\menu_link_content\Entity\MenuLinkContent; | ||||
| use Drupal\menu_link_content\MenuLinkContentInterface; | ||||
| use Drupal\node\Entity\Node; | ||||
| use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; | ||||
| 
 | ||||
| /** | ||||
|  | @ -18,7 +19,7 @@ class MigrateMenuLinkTest extends MigrateDrupal7TestBase { | |||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = array('link', 'menu_ui', 'menu_link_content'); | ||||
|   public static $modules = array('link', 'menu_ui', 'menu_link_content', 'node'); | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|  | @ -26,6 +27,13 @@ class MigrateMenuLinkTest extends MigrateDrupal7TestBase { | |||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
|     $this->installEntitySchema('menu_link_content'); | ||||
|     $this->installEntitySchema('node'); | ||||
|     $node = Node::create([ | ||||
|       'nid' => 3, | ||||
|       'title' => 'node link test', | ||||
|       'type' => 'article', | ||||
|     ]); | ||||
|     $node->save(); | ||||
|     $this->executeMigrations(['d7_menu', 'd7_menu_links']); | ||||
|     \Drupal::service('router.builder')->rebuild(); | ||||
|   } | ||||
|  |  | |||
|  | @ -117,6 +117,10 @@ class LinkUriTest extends UnitTestCase { | |||
|     $expected = 'internal:/test'; | ||||
|     $tests['without_scheme'] = [$value, $expected]; | ||||
| 
 | ||||
|     $value = ['<front>']; | ||||
|     $expected = 'internal:/'; | ||||
|     $tests['front'] = [$value, $expected]; | ||||
| 
 | ||||
|     $url = Url::fromRoute('route_name'); | ||||
|     $tests['with_route'] = [$value, $expected, $url]; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,73 +0,0 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\menu_link_content\Unit\Plugin\migrate\process\d7; | ||||
| 
 | ||||
| use Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri; | ||||
| use Drupal\migrate\MigrateExecutableInterface; | ||||
| use Drupal\migrate\Row; | ||||
| use Drupal\Tests\UnitTestCase; | ||||
| 
 | ||||
| /** | ||||
|  * Tests \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri. | ||||
|  * | ||||
|  * @group menu_link_content | ||||
|  * | ||||
|  * @coversDefaultClass \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri | ||||
|  */ | ||||
| class InternalUriTest extends UnitTestCase { | ||||
| 
 | ||||
|   /** | ||||
|    * The 'd7_internal_uri' process plugin being tested. | ||||
|    * | ||||
|    * @var \Drupal\menu_link_content\Plugin\migrate\process\d7\InternalUri | ||||
|    */ | ||||
|   protected $processPlugin; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
| 
 | ||||
|     $this->processPlugin = new InternalUri([], 'd7_internal_uri', []); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests InternalUri::transform(). | ||||
|    * | ||||
|    * @param array $value | ||||
|    *   The value to pass to InternalUri::transform(). | ||||
|    * @param string $expected | ||||
|    *   The expected return value of InternalUri::transform(). | ||||
|    * | ||||
|    * @dataProvider providerTestTransform | ||||
|    * | ||||
|    * @covers ::transform | ||||
|    */ | ||||
|   public function testTransform(array $value, $expected) { | ||||
|     $migrate_executable = $this->prophesize(MigrateExecutableInterface::class); | ||||
|     $row = $this->prophesize(Row::class); | ||||
| 
 | ||||
|     $actual = $this->processPlugin->transform($value, $migrate_executable->reveal(), $row->reveal(), 'link/uri'); | ||||
|     $this->assertEquals($expected, $actual); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Provides test cases for InternalUriTest::testTransform(). | ||||
|    * | ||||
|    * @return array | ||||
|    *   An array of test cases, each which the following values: | ||||
|    *   - The value array to pass to InternalUri::transform(). | ||||
|    *   - The expected path returned by InternalUri::transform(). | ||||
|    */ | ||||
|   public function providerTestTransform() { | ||||
|     $tests = []; | ||||
|     $tests['with_scheme'] = [['http://example.com'], 'http://example.com']; | ||||
|     $tests['leading_slash'] = [['/test'], 'internal:/test']; | ||||
|     $tests['without_scheme'] = [['test'], 'internal:/test']; | ||||
|     $tests['front'] = [['<front>'], 'internal:/']; | ||||
|     $tests['node'] = [['node/27'], 'entity:node/27']; | ||||
|     return $tests; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -108,8 +108,13 @@ class Download extends ProcessPluginBase implements ContainerFactoryPluginInterf | |||
|     // Stream the request body directly to the final destination stream.
 | ||||
|     $this->configuration['guzzle_options']['sink'] = $destination_stream; | ||||
| 
 | ||||
|     // Make the request. Guzzle throws an exception for anything other than 200.
 | ||||
|     $this->httpClient->get($source, $this->configuration['guzzle_options']); | ||||
|     try { | ||||
|       // Make the request. Guzzle throws an exception for anything but 200.
 | ||||
|       $this->httpClient->get($source, $this->configuration['guzzle_options']); | ||||
|     } | ||||
|     catch (\Exception $e) { | ||||
|       throw new MigrateException("{$e->getMessage()} ($source)"); | ||||
|     } | ||||
| 
 | ||||
|     return $final_destination; | ||||
|   } | ||||
|  |  | |||
|  | @ -112,20 +112,17 @@ class FileCopy extends ProcessPluginBase implements ContainerFactoryPluginInterf | |||
|       return $destination; | ||||
|     } | ||||
| 
 | ||||
|     $replace = $this->getOverwriteMode(); | ||||
|     // We attempt the copy/move first to avoid calling file_prepare_directory()
 | ||||
|     // any more than absolutely necessary.
 | ||||
|     $final_destination = $this->writeFile($source, $destination, $replace); | ||||
|     if ($final_destination) { | ||||
|       return $final_destination; | ||||
|     } | ||||
|     // If writeFile didn't work, make sure there's a writable directory in
 | ||||
|     // place.
 | ||||
|     // Check if a writable directory exists, and if not try to create it.
 | ||||
|     $dir = $this->getDirectory($destination); | ||||
|     if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { | ||||
|       throw new MigrateException("Could not create or write to directory '$dir'"); | ||||
|     // If the directory exists and is writable, avoid file_prepare_directory()
 | ||||
|     // call and write the file to destination.
 | ||||
|     if (!is_dir($dir) || !is_writable($dir)) { | ||||
|       if (!file_prepare_directory($dir, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { | ||||
|         throw new MigrateException("Could not create or write to directory '$dir'"); | ||||
|       } | ||||
|     } | ||||
|     $final_destination = $this->writeFile($source, $destination, $replace); | ||||
| 
 | ||||
|     $final_destination = $this->writeFile($source, $destination, $this->getOverwriteMode()); | ||||
|     if ($final_destination) { | ||||
|       return $final_destination; | ||||
|     } | ||||
|  |  | |||
|  | @ -22,15 +22,17 @@ class Iterator extends ProcessPluginBase { | |||
|    * Runs a process pipeline on each destination property per list item. | ||||
|    */ | ||||
|   public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { | ||||
|     $return = array(); | ||||
|     foreach ($value as $key => $new_value) { | ||||
|       $new_row = new Row($new_value, array()); | ||||
|       $migrate_executable->processRow($new_row, $this->configuration['process']); | ||||
|       $destination = $new_row->getDestination(); | ||||
|       if (array_key_exists('key', $this->configuration)) { | ||||
|         $key = $this->transformKey($key, $migrate_executable, $new_row); | ||||
|     $return = []; | ||||
|     if (!is_null($value)) { | ||||
|       foreach ($value as $key => $new_value) { | ||||
|         $new_row = new Row($new_value, []); | ||||
|         $migrate_executable->processRow($new_row, $this->configuration['process']); | ||||
|         $destination = $new_row->getDestination(); | ||||
|         if (array_key_exists('key', $this->configuration)) { | ||||
|           $key = $this->transformKey($key, $migrate_executable, $new_row); | ||||
|         } | ||||
|         $return[$key] = $destination; | ||||
|       } | ||||
|       $return[$key] = $destination; | ||||
|     } | ||||
|     return $return; | ||||
|   } | ||||
|  |  | |||
|  | @ -310,13 +310,13 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter | |||
|     while (!isset($this->currentRow) && $this->getIterator()->valid()) { | ||||
| 
 | ||||
|       $row_data = $this->getIterator()->current() + $this->configuration; | ||||
|       $this->getIterator()->next(); | ||||
|       $this->fetchNextRow(); | ||||
|       $row = new Row($row_data, $this->migration->getSourcePlugin()->getIds(), $this->migration->getDestinationIds()); | ||||
| 
 | ||||
|       // Populate the source key for this row.
 | ||||
|       $this->currentSourceIds = $row->getSourceIdValues(); | ||||
| 
 | ||||
|       // Pick up the existing map row, if any, unless getNextRow() did it.
 | ||||
|       // Pick up the existing map row, if any, unless fetchNextRow() did it.
 | ||||
|       if (!$this->mapRowAdded && ($id_map = $this->idMap->getRowBySource($this->currentSourceIds))) { | ||||
|         $row->setIdMap($id_map); | ||||
|       } | ||||
|  | @ -348,7 +348,14 @@ abstract class SourcePluginBase extends PluginBase implements MigrateSourceInter | |||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Checks if the incoming data is newer than what we've previously imported. | ||||
|    * Position the iterator to the following row. | ||||
|    */ | ||||
|   protected function fetchNextRow() { | ||||
|     $this->getIterator()->next(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Check if the incoming data is newer than what we've previously imported. | ||||
|    * | ||||
|    * @param \Drupal\migrate\Row $row | ||||
|    *   The row we're importing. | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ namespace Drupal\migrate\Plugin\migrate\source; | |||
| use Drupal\Core\Database\Database; | ||||
| use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | ||||
| use Drupal\Core\State\StateInterface; | ||||
| use Drupal\migrate\MigrateException; | ||||
| use Drupal\migrate\Plugin\MigrationInterface; | ||||
| use Drupal\migrate\Plugin\migrate\id_map\Sql; | ||||
| use Drupal\migrate\Plugin\MigrateIdMapInterface; | ||||
|  | @ -42,6 +43,22 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi | |||
|    */ | ||||
|   protected $state; | ||||
| 
 | ||||
|   /** | ||||
|    * The count of the number of batches run. | ||||
|    * | ||||
|    * @var int | ||||
|    */ | ||||
|   protected $batch = 0; | ||||
| 
 | ||||
|   /** | ||||
|    * Number of records to fetch from the database during each batch. | ||||
|    * | ||||
|    * A value of zero indicates no batching is to be done. | ||||
|    * | ||||
|    * @var int | ||||
|    */ | ||||
|   protected $batchSize = 0; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|  | @ -160,70 +177,110 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi | |||
|    * we will take advantage of the PDO-based API to optimize the query up-front. | ||||
|    */ | ||||
|   protected function initializeIterator() { | ||||
|     $this->prepareQuery(); | ||||
|     // Initialize the batch size.
 | ||||
|     if ($this->batchSize == 0 && isset($this->configuration['batch_size'])) { | ||||
|       // Valid batch sizes are integers >= 0.
 | ||||
|       if (is_int($this->configuration['batch_size']) && ($this->configuration['batch_size']) >= 0) { | ||||
|         $this->batchSize = $this->configuration['batch_size']; | ||||
|       } | ||||
|       else { | ||||
|         throw new MigrateException("batch_size must be greater than or equal to zero"); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // Get the key values, for potential use in joining to the map table.
 | ||||
|     $keys = array(); | ||||
|     // If a batch has run the query is already setup.
 | ||||
|     if ($this->batch == 0) { | ||||
|       $this->prepareQuery(); | ||||
| 
 | ||||
|     // The rules for determining what conditions to add to the query are as
 | ||||
|     // follows (applying first applicable rule):
 | ||||
|     // 1. If the map is joinable, join it. We will want to accept all rows
 | ||||
|     //    which are either not in the map, or marked in the map as NEEDS_UPDATE.
 | ||||
|     //    Note that if high water fields are in play, we want to accept all rows
 | ||||
|     //    above the high water mark in addition to those selected by the map
 | ||||
|     //    conditions, so we need to OR them together (but AND with any existing
 | ||||
|     //    conditions in the query). So, ultimately the SQL condition will look
 | ||||
|     //    like (original conditions) AND (map IS NULL OR map needs update
 | ||||
|     //      OR above high water).
 | ||||
|     $conditions = $this->query->orConditionGroup(); | ||||
|     $condition_added = FALSE; | ||||
|     if (empty($this->configuration['ignore_map']) && $this->mapJoinable()) { | ||||
|       // Build the join to the map table. Because the source key could have
 | ||||
|       // multiple fields, we need to build things up.
 | ||||
|       $count = 1; | ||||
|       $map_join = ''; | ||||
|       $delimiter = ''; | ||||
|       foreach ($this->getIds() as $field_name => $field_schema) { | ||||
|         if (isset($field_schema['alias'])) { | ||||
|           $field_name = $field_schema['alias'] . '.' . $this->query->escapeField($field_name); | ||||
|       // Get the key values, for potential use in joining to the map table.
 | ||||
|       $keys = array(); | ||||
| 
 | ||||
|       // The rules for determining what conditions to add to the query are as
 | ||||
|       // follows (applying first applicable rule):
 | ||||
|       // 1. If the map is joinable, join it. We will want to accept all rows
 | ||||
|       //    which are either not in the map, or marked in the map as NEEDS_UPDATE.
 | ||||
|       //    Note that if high water fields are in play, we want to accept all rows
 | ||||
|       //    above the high water mark in addition to those selected by the map
 | ||||
|       //    conditions, so we need to OR them together (but AND with any existing
 | ||||
|       //    conditions in the query). So, ultimately the SQL condition will look
 | ||||
|       //    like (original conditions) AND (map IS NULL OR map needs update
 | ||||
|       //      OR above high water).
 | ||||
|       $conditions = $this->query->orConditionGroup(); | ||||
|       $condition_added = FALSE; | ||||
|       if (empty($this->configuration['ignore_map']) && $this->mapJoinable()) { | ||||
|         // Build the join to the map table. Because the source key could have
 | ||||
|         // multiple fields, we need to build things up.
 | ||||
|         $count = 1; | ||||
|         $map_join = ''; | ||||
|         $delimiter = ''; | ||||
|         foreach ($this->getIds() as $field_name => $field_schema) { | ||||
|           if (isset($field_schema['alias'])) { | ||||
|             $field_name = $field_schema['alias'] . '.' . $this->query->escapeField($field_name); | ||||
|           } | ||||
|           $map_join .= "$delimiter$field_name = map.sourceid" . $count++; | ||||
|           $delimiter = ' AND '; | ||||
|         } | ||||
|         $map_join .= "$delimiter$field_name = map.sourceid" . $count++; | ||||
|         $delimiter = ' AND '; | ||||
|       } | ||||
| 
 | ||||
|       $alias = $this->query->leftJoin($this->migration->getIdMap()->getQualifiedMapTableName(), 'map', $map_join); | ||||
|       $conditions->isNull($alias . '.sourceid1'); | ||||
|       $conditions->condition($alias . '.source_row_status', MigrateIdMapInterface::STATUS_NEEDS_UPDATE); | ||||
|       $condition_added = TRUE; | ||||
|         $alias = $this->query->leftJoin($this->migration->getIdMap() | ||||
|           ->getQualifiedMapTableName(), 'map', $map_join); | ||||
|         $conditions->isNull($alias . '.sourceid1'); | ||||
|         $conditions->condition($alias . '.source_row_status', MigrateIdMapInterface::STATUS_NEEDS_UPDATE); | ||||
|         $condition_added = TRUE; | ||||
| 
 | ||||
|       // And as long as we have the map table, add its data to the row.
 | ||||
|       $n = count($this->getIds()); | ||||
|       for ($count = 1; $count <= $n; $count++) { | ||||
|         $map_key = 'sourceid' . $count; | ||||
|         $this->query->addField($alias, $map_key, "migrate_map_$map_key"); | ||||
|       } | ||||
|       if ($n = count($this->migration->getDestinationIds())) { | ||||
|         // And as long as we have the map table, add its data to the row.
 | ||||
|         $n = count($this->getIds()); | ||||
|         for ($count = 1; $count <= $n; $count++) { | ||||
|           $map_key = 'destid' . $count++; | ||||
|           $map_key = 'sourceid' . $count; | ||||
|           $this->query->addField($alias, $map_key, "migrate_map_$map_key"); | ||||
|         } | ||||
|         if ($n = count($this->migration->getDestinationIds())) { | ||||
|           for ($count = 1; $count <= $n; $count++) { | ||||
|             $map_key = 'destid' . $count++; | ||||
|             $this->query->addField($alias, $map_key, "migrate_map_$map_key"); | ||||
|           } | ||||
|         } | ||||
|         $this->query->addField($alias, 'source_row_status', 'migrate_map_source_row_status'); | ||||
|       } | ||||
|       // 2. If we are using high water marks, also include rows above the mark.
 | ||||
|       //    But, include all rows if the high water mark is not set.
 | ||||
|       if ($this->getHighWaterProperty() && ($high_water = $this->getHighWater()) !== '') { | ||||
|         $high_water_field = $this->getHighWaterField(); | ||||
|         $conditions->condition($high_water_field, $high_water, '>'); | ||||
|         $this->query->orderBy($high_water_field); | ||||
|       } | ||||
|       if ($condition_added) { | ||||
|         $this->query->condition($conditions); | ||||
|       } | ||||
|       $this->query->addField($alias, 'source_row_status', 'migrate_map_source_row_status'); | ||||
|     } | ||||
|     // 2. If we are using high water marks, also include rows above the mark.
 | ||||
|     //    But, include all rows if the high water mark is not set.
 | ||||
|     if ($this->getHighWaterProperty() && ($high_water = $this->getHighWater()) !== '') { | ||||
|       $high_water_field = $this->getHighWaterField(); | ||||
|       $conditions->condition($high_water_field, $high_water, '>'); | ||||
|       $this->query->orderBy($high_water_field); | ||||
|     } | ||||
|     if ($condition_added) { | ||||
|       $this->query->condition($conditions); | ||||
|     } | ||||
| 
 | ||||
|     // Download data in batches for performance.
 | ||||
|     if (($this->batchSize > 0)) { | ||||
|       $this->query->range($this->batch * $this->batchSize, $this->batchSize); | ||||
|     } | ||||
|     return new \IteratorIterator($this->query->execute()); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Position the iterator to the following row. | ||||
|    */ | ||||
|   protected function fetchNextRow() { | ||||
|     $this->getIterator()->next(); | ||||
|     // We might be out of data entirely, or just out of data in the current
 | ||||
|     // batch. Attempt to fetch the next batch and see.
 | ||||
|     if ($this->batchSize > 0 && !$this->getIterator()->valid()) { | ||||
|       $this->fetchNextBatch(); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Prepares query for the next set of data from the source database. | ||||
|    */ | ||||
|   protected function fetchNextBatch() { | ||||
|     $this->batch++; | ||||
|     unset($this->iterator); | ||||
|     $this->getIterator()->rewind(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @return \Drupal\Core\Database\Query\SelectInterface | ||||
|    */ | ||||
|  | @ -249,6 +306,14 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi | |||
|     if (!$this->getIds()) { | ||||
|       return FALSE; | ||||
|     } | ||||
|     // With batching, we want a later batch to return the same rows that would
 | ||||
|     // have been returned at the same point within a monolithic query. If we
 | ||||
|     // join to the map table, the first batch is writing to the map table and
 | ||||
|     // thus affecting the results of subsequent batches. To be safe, we avoid
 | ||||
|     // joining to the map table when batching.
 | ||||
|     if ($this->batchSize > 0) { | ||||
|       return FALSE; | ||||
|     } | ||||
|     $id_map = $this->migration->getIdMap(); | ||||
|     if (!$id_map instanceof Sql) { | ||||
|       return FALSE; | ||||
|  |  | |||
|  | @ -0,0 +1,7 @@ | |||
| type: module | ||||
| name: Migrate query batch Source test | ||||
| description: 'Provides a database table and records for SQL import with batch testing.' | ||||
| package: Testing | ||||
| core: 8.x | ||||
| dependencies: | ||||
|   - migrate | ||||
|  | @ -0,0 +1,45 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\migrate_query_batch_test\Plugin\migrate\source; | ||||
| 
 | ||||
| use Drupal\migrate\Plugin\migrate\source\SqlBase; | ||||
| 
 | ||||
| /** | ||||
|  * Source plugin for migration high water tests. | ||||
|  * | ||||
|  * @MigrateSource( | ||||
|  *   id = "query_batch_test" | ||||
|  * ) | ||||
|  */ | ||||
| class QueryBatchTest extends SqlBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function query() { | ||||
|     return ($this->select('query_batch_test', 'q')->fields('q')); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function fields() { | ||||
|     $fields = [ | ||||
|       'id' => $this->t('Id'), | ||||
|       'data' => $this->t('data'), | ||||
|     ]; | ||||
|     return $fields; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function getIds() { | ||||
|     return [ | ||||
|       'id' => [ | ||||
|         'type' => 'integer', | ||||
|       ], | ||||
|     ]; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,81 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\migrate\Functional\process; | ||||
| 
 | ||||
| use Drupal\migrate\MigrateExecutable; | ||||
| use Drupal\migrate\MigrateMessage; | ||||
| use Drupal\migrate\Plugin\MigrateIdMapInterface; | ||||
| use Drupal\migrate\Plugin\MigrationInterface; | ||||
| use Drupal\Tests\BrowserTestBase; | ||||
| 
 | ||||
| /** | ||||
|  * Tests the 'download' process plugin. | ||||
|  * | ||||
|  * @group migrate | ||||
|  */ | ||||
| class DownloadFunctionalTest extends BrowserTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = ['migrate', 'file']; | ||||
| 
 | ||||
|   /** | ||||
|    * Tests that an exception is thrown bu migration continues with the next row. | ||||
|    */ | ||||
|   public function testExceptionThrow() { | ||||
|     $invalid_url = "{$this->baseUrl}/not-existent-404"; | ||||
|     $valid_url = "{$this->baseUrl}/core/misc/favicon.ico"; | ||||
| 
 | ||||
|     $definition = [ | ||||
|       'source' => [ | ||||
|         'plugin' => 'embedded_data', | ||||
|         'data_rows' => [ | ||||
|           ['url' => $invalid_url, 'uri' => 'public://first.txt'], | ||||
|           ['url' => $valid_url, 'uri' => 'public://second.ico'], | ||||
|         ], | ||||
|         'ids' => [ | ||||
|           'url' => ['type' => 'string'], | ||||
|         ], | ||||
|       ], | ||||
|       'process' => [ | ||||
|         'uri' => [ | ||||
|           'plugin' => 'download', | ||||
|           'source' => ['url', 'uri'], | ||||
|         ] | ||||
|       ], | ||||
|       'destination' => [ | ||||
|         'plugin' => 'entity:file', | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition); | ||||
| 
 | ||||
|     $executable = new MigrateExecutable($migration, new MigrateMessage()); | ||||
|     $result = $executable->import(); | ||||
| 
 | ||||
|     // Check that the migration has completed.
 | ||||
|     $this->assertEquals($result, MigrationInterface::RESULT_COMPLETED); | ||||
| 
 | ||||
|     /** @var \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map_plugin */ | ||||
|     $id_map_plugin = $migration->getIdMap(); | ||||
| 
 | ||||
|     // Check that the first row was marked as failed in the id map table.
 | ||||
|     $map_row = $id_map_plugin->getRowBySource(['url' => $invalid_url]); | ||||
|     $this->assertEquals(MigrateIdMapInterface::STATUS_FAILED, $map_row['source_row_status']); | ||||
|     $this->assertNull($map_row['destid1']); | ||||
| 
 | ||||
|     // Check that a message with the thrown exception has been logged.
 | ||||
|     $messages = $id_map_plugin->getMessageIterator(['url' => $invalid_url])->fetchAll(); | ||||
|     $this->assertCount(1, $messages); | ||||
|     $message = reset($messages); | ||||
|     $this->assertEquals("Cannot read from non-readable stream ($invalid_url)", $message->message); | ||||
|     $this->assertEquals(MigrationInterface::MESSAGE_ERROR, $message->level); | ||||
| 
 | ||||
|     // Check that the second row was migrated successfully.
 | ||||
|     $map_row = $id_map_plugin->getRowBySource(['url' => $valid_url]); | ||||
|     $this->assertEquals(MigrateIdMapInterface::STATUS_IMPORTED, $map_row['source_row_status']); | ||||
|     $this->assertEquals(1, $map_row['destid1']); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										261
									
								
								core/modules/migrate/tests/src/Kernel/QueryBatchTest.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								core/modules/migrate/tests/src/Kernel/QueryBatchTest.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,261 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\migrate\Kernel; | ||||
| 
 | ||||
| use Drupal\KernelTests\KernelTestBase; | ||||
| use Drupal\migrate\MigrateException; | ||||
| use Drupal\migrate\Plugin\MigrateIdMapInterface; | ||||
| use Drupal\migrate\Plugin\MigrationInterface; | ||||
| use Drupal\Core\Database\Driver\sqlite\Connection; | ||||
| 
 | ||||
| /** | ||||
|  * Tests query batching. | ||||
|  * | ||||
|  * @covers \Drupal\migrate_query_batch_test\Plugin\migrate\source\QueryBatchTest | ||||
|  * @group migrate | ||||
|  */ | ||||
| class QueryBatchTest extends KernelTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * The mocked migration. | ||||
|    * | ||||
|    * @var MigrationInterface|\Prophecy\Prophecy\ObjectProphecy | ||||
|    */ | ||||
|   protected $migration; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = [ | ||||
|     'migrate', | ||||
|     'migrate_query_batch_test', | ||||
|   ]; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
| 
 | ||||
|     // Create a mock migration. This will be injected into the source plugin
 | ||||
|     // under test.
 | ||||
|     $this->migration = $this->prophesize(MigrationInterface::class); | ||||
| 
 | ||||
|     $this->migration->id()->willReturn( | ||||
|       $this->randomMachineName(16) | ||||
|     ); | ||||
|     // Prophesize a useless ID map plugin and an empty set of destination IDs.
 | ||||
|     // Calling code can override these prophecies later and set up different
 | ||||
|     // behaviors.
 | ||||
|     $this->migration->getIdMap()->willReturn( | ||||
|       $this->prophesize(MigrateIdMapInterface::class)->reveal() | ||||
|     ); | ||||
|     $this->migration->getDestinationIds()->willReturn([]); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests a negative batch size throws an exception. | ||||
|    */ | ||||
|   public function testBatchSizeNegative() { | ||||
|     $this->setExpectedException(MigrateException::class, 'batch_size must be greater than or equal to zero'); | ||||
|     $plugin = $this->getPlugin(['batch_size' => -1]); | ||||
|     $plugin->next(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests a non integer batch size throws an exception. | ||||
|    */ | ||||
|   public function testBatchSizeNonInteger() { | ||||
|     $this->setExpectedException(MigrateException::class, 'batch_size must be greater than or equal to zero'); | ||||
|     $plugin = $this->getPlugin(['batch_size' => '1']); | ||||
|     $plugin->next(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function queryDataProvider() { | ||||
|     // Define the parameters for building the data array. The first element is
 | ||||
|     // the number of source data rows, the second is the batch size to set on
 | ||||
|     // the plugin configuration.
 | ||||
|     $test_parameters = [ | ||||
|       // Test when batch size is 0.
 | ||||
|       [200, 0], | ||||
|       // Test when rows mod batch size is 0.
 | ||||
|       [200, 20], | ||||
|       // Test when rows mod batch size is > 0.
 | ||||
|       [200, 30], | ||||
|       // Test when batch size = row count.
 | ||||
|       [200, 200], | ||||
|       // Test when batch size > row count.
 | ||||
|       [200, 300], | ||||
|     ]; | ||||
| 
 | ||||
|     // Build the data provider array. The provider array consists of the source
 | ||||
|     // data rows, the expected result data, the expected count, the plugin
 | ||||
|     // configuration, the expected batch size and the expected batch count.
 | ||||
|     $table = 'query_batch_test'; | ||||
|     $tests = []; | ||||
|     $data_set = 0; | ||||
|     foreach ($test_parameters as $data) { | ||||
|       list($num_rows, $batch_size) = $data; | ||||
|       for ($i = 0; $i < $num_rows; $i++) { | ||||
|         $tests[$data_set]['source_data'][$table][] = [ | ||||
|           'id' => $i, | ||||
|           'data' => $this->randomString(), | ||||
|         ]; | ||||
|       } | ||||
|       $tests[$data_set]['expected_data'] = $tests[$data_set]['source_data'][$table]; | ||||
|       $tests[$data_set][2] = $num_rows; | ||||
|       // Plugin configuration array.
 | ||||
|       $tests[$data_set][3] = ['batch_size' => $batch_size]; | ||||
|       // Expected batch size.
 | ||||
|       $tests[$data_set][4] = $batch_size; | ||||
|       // Expected batch count is 0 unless a batch size is set.
 | ||||
|       $expected_batch_count = 0; | ||||
|       if ($batch_size > 0) { | ||||
|         $expected_batch_count = (int) ($num_rows / $batch_size); | ||||
|         if ($num_rows % $batch_size) { | ||||
|           // If there is a remainder an extra batch is needed to get the
 | ||||
|           // remaining rows.
 | ||||
|           $expected_batch_count++; | ||||
|         } | ||||
|       } | ||||
|       $tests[$data_set][5] = $expected_batch_count; | ||||
|       $data_set++; | ||||
|     } | ||||
|     return $tests; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests query batch size. | ||||
|    * | ||||
|    * @param array $source_data | ||||
|    *   The source data, keyed by table name. Each table is an array containing | ||||
|    *   the rows in that table. | ||||
|    * @param array $expected_data | ||||
|    *   The result rows the plugin is expected to return. | ||||
|    * @param int $num_rows | ||||
|    *   How many rows the source plugin is expected to return. | ||||
|    * @param array $configuration | ||||
|    *   Configuration for the source plugin specifying the batch size. | ||||
|    * @param int $expected_batch_size | ||||
|    *   The expected batch size, will be set to zero for invalid batch sizes. | ||||
|    * @param int $expected_batch_count | ||||
|    *   The total number of batches. | ||||
|    * | ||||
|    * @dataProvider queryDataProvider | ||||
|    */ | ||||
|   public function testQueryBatch($source_data, $expected_data, $num_rows, $configuration, $expected_batch_size, $expected_batch_count) { | ||||
|     $plugin = $this->getPlugin($configuration); | ||||
| 
 | ||||
|     // Since we don't yet inject the database connection, we need to use a
 | ||||
|     // reflection hack to set it in the plugin instance.
 | ||||
|     $reflector = new \ReflectionObject($plugin); | ||||
|     $property = $reflector->getProperty('database'); | ||||
|     $property->setAccessible(TRUE); | ||||
| 
 | ||||
|     $connection = $this->getDatabase($source_data); | ||||
|     $property->setValue($plugin, $connection); | ||||
| 
 | ||||
|     // Test the results.
 | ||||
|     $i = 0; | ||||
|     /** @var \Drupal\migrate\Row $row */ | ||||
|     foreach ($plugin as $row) { | ||||
| 
 | ||||
|       $expected = $expected_data[$i++]; | ||||
|       $actual = $row->getSource(); | ||||
| 
 | ||||
|       foreach ($expected as $key => $value) { | ||||
|         $this->assertArrayHasKey($key, $actual); | ||||
|         $this->assertSame((string) $value, (string) $actual[$key]); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // Test that all rows were retrieved.
 | ||||
|     self::assertSame($num_rows, $i); | ||||
| 
 | ||||
|     // Test the batch size.
 | ||||
|     if (is_null($expected_batch_size)) { | ||||
|       $expected_batch_size = $configuration['batch_size']; | ||||
|     } | ||||
|     $property = $reflector->getProperty('batchSize'); | ||||
|     $property->setAccessible(TRUE); | ||||
|     self::assertSame($expected_batch_size, $property->getValue($plugin)); | ||||
| 
 | ||||
|     // Test the batch count.
 | ||||
|     if (is_null($expected_batch_count)) { | ||||
|       $expected_batch_count = intdiv($num_rows, $expected_batch_size); | ||||
|       if ($num_rows % $configuration['batch_size']) { | ||||
|         $expected_batch_count++; | ||||
|       } | ||||
|     } | ||||
|     $property = $reflector->getProperty('batch'); | ||||
|     $property->setAccessible(TRUE); | ||||
|     self::assertSame($expected_batch_count, $property->getValue($plugin)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Instantiates the source plugin under test. | ||||
|    * | ||||
|    * @param array $configuration | ||||
|    *   The source plugin configuration. | ||||
|    * | ||||
|    * @return \Drupal\migrate\Plugin\MigrateSourceInterface|object | ||||
|    *   The fully configured source plugin. | ||||
|    */ | ||||
|   protected function getPlugin($configuration) { | ||||
|     /** @var \Drupal\migrate\Plugin\MigratePluginManager $plugin_manager */ | ||||
|     $plugin_manager = $this->container->get('plugin.manager.migrate.source'); | ||||
|     $plugin = $plugin_manager->createInstance('query_batch_test', $configuration, $this->migration->reveal()); | ||||
| 
 | ||||
|     $this->migration | ||||
|       ->getSourcePlugin() | ||||
|       ->willReturn($plugin); | ||||
|     return $plugin; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Builds an in-memory SQLite database from a set of source data. | ||||
|    * | ||||
|    * @param array $source_data | ||||
|    *   The source data, keyed by table name. Each table is an array containing | ||||
|    *   the rows in that table. | ||||
|    * | ||||
|    * @return \Drupal\Core\Database\Driver\sqlite\Connection | ||||
|    *   The SQLite database connection. | ||||
|    */ | ||||
|   protected function getDatabase(array $source_data) { | ||||
|     // Create an in-memory SQLite database. Plugins can interact with it like
 | ||||
|     // any other database, and it will cease to exist when the connection is
 | ||||
|     // closed.
 | ||||
|     $connection_options = ['database' => ':memory:']; | ||||
|     $pdo = Connection::open($connection_options); | ||||
|     $connection = new Connection($pdo, $connection_options); | ||||
| 
 | ||||
|     // Create the tables and fill them with data.
 | ||||
|     foreach ($source_data as $table => $rows) { | ||||
|       // Use the biggest row to build the table schema.
 | ||||
|       $counts = array_map('count', $rows); | ||||
|       asort($counts); | ||||
|       end($counts); | ||||
|       $pilot = $rows[key($counts)]; | ||||
| 
 | ||||
|       $connection->schema() | ||||
|         ->createTable($table, [ | ||||
|           // SQLite uses loose affinity typing, so it's OK for every field to
 | ||||
|           // be a text field.
 | ||||
|           'fields' => array_map(function () { | ||||
|             return ['type' => 'text']; | ||||
|           }, $pilot), | ||||
|         ]); | ||||
| 
 | ||||
|       $fields = array_keys($pilot); | ||||
|       $insert = $connection->insert($table)->fields($fields); | ||||
|       array_walk($rows, [$insert, 'values']); | ||||
|       $insert->execute(); | ||||
|     } | ||||
|     return $connection; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -4,6 +4,7 @@ namespace Drupal\Tests\migrate\Kernel\process; | |||
| 
 | ||||
| use Drupal\Core\StreamWrapper\StreamWrapperInterface; | ||||
| use Drupal\KernelTests\Core\File\FileTestBase; | ||||
| use Drupal\migrate\MigrateException; | ||||
| use Drupal\migrate\Plugin\migrate\process\FileCopy; | ||||
| use Drupal\migrate\MigrateExecutableInterface; | ||||
| use Drupal\migrate\Plugin\MigrateProcessInterface; | ||||
|  | @ -12,6 +13,8 @@ use Drupal\migrate\Row; | |||
| /** | ||||
|  * Tests the file_copy process plugin. | ||||
|  * | ||||
|  * @coversDefaultClass \Drupal\migrate\Plugin\migrate\process\FileCopy | ||||
|  * | ||||
|  * @group migrate | ||||
|  */ | ||||
| class FileCopyTest extends FileTestBase { | ||||
|  | @ -120,6 +123,32 @@ class FileCopyTest extends FileTestBase { | |||
|     $this->doTransform($source, 'public://wontmatter.jpg'); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Tests that non-writable destination throw an exception. | ||||
|    * | ||||
|    * @covers ::transform | ||||
|    */ | ||||
|   public function testNonWritableDestination() { | ||||
|     $source = $this->createUri('file.txt', NULL, 'temporary'); | ||||
| 
 | ||||
|     // Create the parent location.
 | ||||
|     $this->createDirectory('public://dir'); | ||||
| 
 | ||||
|     // Copy the file under public://dir/subdir1/.
 | ||||
|     $this->doTransform($source, 'public://dir/subdir1/file.txt'); | ||||
| 
 | ||||
|     // Check that 'subdir1' was created and the file was successfully migrated.
 | ||||
|     $this->assertFileExists('public://dir/subdir1/file.txt'); | ||||
| 
 | ||||
|     // Remove all permissions from public://dir to trigger a failure when
 | ||||
|     // trying to create a subdirectory 'subdir2' inside public://dir.
 | ||||
|     $this->fileSystem->chmod('public://dir', 0); | ||||
| 
 | ||||
|     // Check that the proper exception is raised.
 | ||||
|     $this->setExpectedException(MigrateException::class, "Could not create or write to directory 'public://dir/subdir2'"); | ||||
|     $this->doTransform($source, 'public://dir/subdir2/file.txt'); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Test the 'rename' overwrite mode. | ||||
|    */ | ||||
|  |  | |||
|  | @ -3828,6 +3828,15 @@ $connection->insert('field_config_instance') | |||
|   'data' => 'a:7:{s:5:"label";s:21:"Term Entity Reference";s:6:"widget";a:5:{s:6:"weight";s:2:"18";s:4:"type";s:33:"entityreference_autocomplete_tags";s:6:"module";s:15:"entityreference";s:6:"active";i:1;s:8:"settings";a:3:{s:14:"match_operator";s:8:"CONTAINS";s:4:"size";s:2:"60";s:4:"path";s:0:"";}}s:8:"settings";a:2:{s:9:"behaviors";a:1:{s:14:"taxonomy-index";a:1:{s:6:"status";b:1;}}s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:5:{s:5:"label";s:5:"above";s:4:"type";s:21:"entityreference_label";s:8:"settings";a:1:{s:4:"link";b:0;}s:6:"module";s:15:"entityreference";s:6:"weight";i:17;}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', | ||||
|   'deleted' => '0', | ||||
| )) | ||||
| ->values(array( | ||||
|   'id' => '41', | ||||
|   'field_id' => '20', | ||||
|   'field_name' => 'field_term_reference', | ||||
|   'entity_type' => 'taxonomy_term', | ||||
|   'bundle' => 'test_vocabulary', | ||||
|   'data' => 'a:7:{s:5:"label";s:14:"Term Reference";s:6:"widget";a:5:{s:6:"weight";s:2:"14";s:4:"type";s:21:"taxonomy_autocomplete";s:6:"module";s:8:"taxonomy";s:6:"active";i:0;s:8:"settings";a:2:{s:4:"size";i:60;s:17:"autocomplete_path";s:21:"taxonomy/autocomplete";}}s:8:"settings";a:1:{s:18:"user_register_form";b:0;}s:7:"display";a:1:{s:7:"default";a:4:{s:5:"label";s:5:"above";s:4:"type";s:6:"hidden";s:6:"weight";s:2:"13";s:8:"settings";a:0:{}}}s:8:"required";i:0;s:11:"description";s:0:"";s:13:"default_value";N;}', | ||||
|   'deleted' => '0', | ||||
| )) | ||||
| ->execute(); | ||||
| 
 | ||||
| $connection->schema()->createTable('field_data_body', array( | ||||
|  | @ -4850,6 +4859,16 @@ $connection->insert('field_data_field_integer') | |||
|   'delta' => '0', | ||||
|   'field_integer_value' => '99', | ||||
| )) | ||||
| ->values(array( | ||||
|   'entity_type' => 'taxonomy_term', | ||||
|   'bundle' => 'test_vocabulary', | ||||
|   'deleted' => '0', | ||||
|   'entity_id' => '4', | ||||
|   'revision_id' => '4', | ||||
|   'language' => 'und', | ||||
|   'delta' => '0', | ||||
|   'field_integer_value' => '6', | ||||
| )) | ||||
| ->execute(); | ||||
| 
 | ||||
| $connection->schema()->createTable('field_data_field_integer_list', array( | ||||
|  | @ -5649,6 +5668,16 @@ $connection->insert('field_data_field_term_reference') | |||
|   'delta' => '0', | ||||
|   'field_term_reference_tid' => '4', | ||||
| )) | ||||
| ->values(array( | ||||
|   'entity_type' => 'taxonomy_term', | ||||
|   'bundle' => 'test_vocabulary', | ||||
|   'deleted' => '0', | ||||
|   'entity_id' => '2', | ||||
|   'revision_id' => '2', | ||||
|   'language' => 'und', | ||||
|   'delta' => '0', | ||||
|   'field_term_reference_tid' => '3', | ||||
| )) | ||||
| ->execute(); | ||||
| 
 | ||||
| $connection->schema()->createTable('field_data_field_text', array( | ||||
|  | @ -7023,6 +7052,16 @@ $connection->insert('field_revision_field_integer') | |||
|   'delta' => '0', | ||||
|   'field_integer_value' => '99', | ||||
| )) | ||||
| ->values(array( | ||||
|   'entity_type' => 'taxonomy_term', | ||||
|   'bundle' => 'test_vocabulary', | ||||
|   'deleted' => '0', | ||||
|   'entity_id' => '4', | ||||
|   'revision_id' => '4', | ||||
|   'language' => 'und', | ||||
|   'delta' => '0', | ||||
|   'field_integer_value' => '6', | ||||
| )) | ||||
| ->execute(); | ||||
| 
 | ||||
| $connection->schema()->createTable('field_revision_field_integer_list', array( | ||||
|  | @ -7830,6 +7869,16 @@ $connection->insert('field_revision_field_term_reference') | |||
|   'delta' => '0', | ||||
|   'field_term_reference_tid' => '4', | ||||
| )) | ||||
| ->values(array( | ||||
|   'entity_type' => 'taxonomy_term', | ||||
|   'bundle' => 'test_vocabulary', | ||||
|   'deleted' => '0', | ||||
|   'entity_id' => '2', | ||||
|   'revision_id' => '2', | ||||
|   'language' => 'und', | ||||
|   'delta' => '0', | ||||
|   'field_term_reference_tid' => '3', | ||||
| )) | ||||
| ->execute(); | ||||
| 
 | ||||
| $connection->schema()->createTable('field_revision_field_text', array( | ||||
|  |  | |||
|  | @ -250,6 +250,10 @@ class MigrateUpgradeForm extends ConfirmFormBase { | |||
|       'source_module' => 'filter', | ||||
|       'destination_module' => 'filter', | ||||
|     ], | ||||
|     'd7_filter_settings' => [ | ||||
|       'source_module' => 'filter', | ||||
|       'destination_module' => 'filter', | ||||
|     ], | ||||
|     'd6_forum_settings' => [ | ||||
|       'source_module' => 'forum', | ||||
|       'destination_module' => 'forum', | ||||
|  |  | |||
|  | @ -43,8 +43,8 @@ class MigrateUpgrade7Test extends MigrateUpgradeTestBase { | |||
|       'configurable_language' => 4, | ||||
|       'contact_form' => 3, | ||||
|       'editor' => 2, | ||||
|       'field_config' => 48, | ||||
|       'field_storage_config' => 36, | ||||
|       'field_config' => 49, | ||||
|       'field_storage_config' => 37, | ||||
|       'file' => 1, | ||||
|       'filter_format' => 7, | ||||
|       'image_style' => 6, | ||||
|  |  | |||
|  | @ -72,7 +72,7 @@ class NodePreviewForm extends FormBase { | |||
|   public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $node = NULL) { | ||||
|     $view_mode = $node->preview_view_mode; | ||||
| 
 | ||||
|     $query_options = $node->isNew() ? array('query' => array('uuid' => $node->uuid())) : array(); | ||||
|     $query_options = array('query' => array('uuid' => $node->uuid())); | ||||
|     $form['backlink'] = array( | ||||
|       '#type' => 'link', | ||||
|       '#title' => $this->t('Back to content editing'), | ||||
|  |  | |||
|  | @ -67,31 +67,28 @@ class NodeForm extends ContentEntityForm { | |||
|   public function form(array $form, FormStateInterface $form_state) { | ||||
|     // Try to restore from temp store, this must be done before calling
 | ||||
|     // parent::form().
 | ||||
|     $uuid = $this->entity->uuid(); | ||||
|     $store = $this->tempStoreFactory->get('node_preview'); | ||||
| 
 | ||||
|     // If the user is creating a new node, the UUID is passed in the request.
 | ||||
|     if ($request_uuid = \Drupal::request()->query->get('uuid')) { | ||||
|       $uuid = $request_uuid; | ||||
|     } | ||||
| 
 | ||||
|     if ($preview = $store->get($uuid)) { | ||||
|     // Attempt to load from preview when the uuid is present unless we are
 | ||||
|     // rebuilding the form.
 | ||||
|     $request_uuid = \Drupal::request()->query->get('uuid'); | ||||
|     if (!$form_state->isRebuilding() && $request_uuid && $preview = $store->get($request_uuid)) { | ||||
|       /** @var $preview \Drupal\Core\Form\FormStateInterface */ | ||||
| 
 | ||||
|       foreach ($preview->getValues() as $name => $value) { | ||||
|         $form_state->setValue($name, $value); | ||||
|       } | ||||
|       $form_state->setStorage($preview->getStorage()); | ||||
|       $form_state->setUserInput($preview->getUserInput()); | ||||
| 
 | ||||
|       // Rebuild the form.
 | ||||
|       $form_state->setRebuild(); | ||||
| 
 | ||||
|       // The combination of having user input and rebuilding the form means
 | ||||
|       // that it will attempt to cache the form state which will fail if it is
 | ||||
|       // a GET request.
 | ||||
|       $form_state->setRequestMethod('POST'); | ||||
| 
 | ||||
|       $this->entity = $preview->getFormObject()->getEntity(); | ||||
|       $this->entity->in_preview = NULL; | ||||
| 
 | ||||
|       // Remove the stale temp store entry for existing nodes.
 | ||||
|       if (!$this->entity->isNew()) { | ||||
|         $store->delete($uuid); | ||||
|       } | ||||
| 
 | ||||
|       $this->hasBeenPreviewed = TRUE; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ class PagePreviewTest extends NodeTestBase { | |||
|    * | ||||
|    * @var array | ||||
|    */ | ||||
|   public static $modules = array('node', 'taxonomy', 'comment', 'image', 'file'); | ||||
|   public static $modules = array('node', 'taxonomy', 'comment', 'image', 'file', 'text', 'node_test', 'menu_ui'); | ||||
| 
 | ||||
|   /** | ||||
|    * The name of the created field. | ||||
|  | @ -41,7 +41,7 @@ class PagePreviewTest extends NodeTestBase { | |||
|     parent::setUp(); | ||||
|     $this->addDefaultCommentField('node', 'page'); | ||||
| 
 | ||||
|     $web_user = $this->drupalCreateUser(array('edit own page content', 'create page content')); | ||||
|     $web_user = $this->drupalCreateUser(array('edit own page content', 'create page content', 'administer menu')); | ||||
|     $this->drupalLogin($web_user); | ||||
| 
 | ||||
|     // Add a vocabulary so we can test different view modes.
 | ||||
|  | @ -124,6 +124,34 @@ class PagePreviewTest extends NodeTestBase { | |||
|     entity_get_display('node', 'page', 'default') | ||||
|       ->setComponent('field_image') | ||||
|       ->save(); | ||||
| 
 | ||||
|     // Create a multi-value text field.
 | ||||
|     $field_storage = FieldStorageConfig::create([ | ||||
|       'field_name' => 'field_test_multi', | ||||
|       'entity_type' => 'node', | ||||
|       'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED, | ||||
|       'type' => 'text', | ||||
|       'settings' => [ | ||||
|         'max_length' => 50, | ||||
|       ] | ||||
|     ]); | ||||
|     $field_storage->save(); | ||||
|     FieldConfig::create([ | ||||
|       'field_storage' => $field_storage, | ||||
|       'bundle' => 'page', | ||||
|     ])->save(); | ||||
| 
 | ||||
|     entity_get_form_display('node', 'page', 'default') | ||||
|       ->setComponent('field_test_multi', array( | ||||
|         'type' => 'text_textfield', | ||||
|       )) | ||||
|       ->save(); | ||||
| 
 | ||||
|     entity_get_display('node', 'page', 'default') | ||||
|       ->setComponent('field_test_multi', array( | ||||
|         'type' => 'string', | ||||
|       )) | ||||
|       ->save(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -176,8 +204,11 @@ class PagePreviewTest extends NodeTestBase { | |||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.'); | ||||
|     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.'); | ||||
|     $this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.'); | ||||
|     $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.'); | ||||
|     $this->assertFieldByName('field_image[0][alt]', 'Picture of llamas'); | ||||
|     $this->drupalPostAjaxForm(NULL, array(), array('field_test_multi_add_more' => t('Add another item')), NULL, array(), array(), 'node-page-form'); | ||||
|     $this->assertFieldByName('field_test_multi[0][value]'); | ||||
|     $this->assertFieldByName('field_test_multi[1][value]'); | ||||
| 
 | ||||
|     // Return to page preview to check everything is as expected.
 | ||||
|     $this->drupalPostForm(NULL, array(), t('Preview')); | ||||
|  | @ -191,7 +222,7 @@ class PagePreviewTest extends NodeTestBase { | |||
|     $this->drupalGet('node/add/page', array('query' => array('uuid' => $uuid))); | ||||
|     $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.'); | ||||
|     $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.'); | ||||
|     $this->assertFieldByName($term_key, $edit[$term_key] . ' (' . $this->term->id() . ')', 'Term field displayed.'); | ||||
|     $this->assertFieldByName($term_key, $edit[$term_key], 'Term field displayed.'); | ||||
| 
 | ||||
|     // Save the node - this is a new POST, so we need to upload the image.
 | ||||
|     $this->drupalPostForm('node/add/page', $edit, t('Upload')); | ||||
|  | @ -260,6 +291,80 @@ class PagePreviewTest extends NodeTestBase { | |||
|     $this->drupalPostForm('node/add/page', array($title_key => 'Preview'), t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertRaw('edit-submit'); | ||||
| 
 | ||||
|     // Assert multiple items can be added and are not lost when previewing.
 | ||||
|     $test_image_1 = current($this->drupalGetTestFiles('image', 39325)); | ||||
|     $edit_image_1['files[field_image_0][]'] = drupal_realpath($test_image_1->uri); | ||||
|     $test_image_2 = current($this->drupalGetTestFiles('image', 39325)); | ||||
|     $edit_image_2['files[field_image_1][]'] = drupal_realpath($test_image_2->uri); | ||||
|     $edit['field_image[0][alt]'] = 'Alt 1'; | ||||
| 
 | ||||
|     $this->drupalPostForm('node/add/page', $edit_image_1, t('Upload')); | ||||
|     $this->drupalPostForm(NULL, $edit, t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertFieldByName('files[field_image_1][]'); | ||||
|     $this->drupalPostForm(NULL, $edit_image_2, t('Upload')); | ||||
|     $this->assertNoFieldByName('files[field_image_1][]'); | ||||
| 
 | ||||
|     $title = 'node_test_title'; | ||||
|     $example_text_1 = 'example_text_preview_1'; | ||||
|     $example_text_2 = 'example_text_preview_2'; | ||||
|     $example_text_3 = 'example_text_preview_3'; | ||||
|     $this->drupalGet('node/add/page'); | ||||
|     $edit = [ | ||||
|       'title[0][value]' => $title, | ||||
|       'field_test_multi[0][value]' => $example_text_1, | ||||
|     ]; | ||||
|     $this->assertRaw('Storage is not set'); | ||||
|     $this->drupalPostForm(NULL, $edit, t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertRaw('Storage is set'); | ||||
|     $this->assertFieldByName('field_test_multi[0][value]'); | ||||
|     $this->drupalPostForm(NULL, [], t('Save')); | ||||
|     $this->assertText('Basic page ' . $title . ' has been created.'); | ||||
|     $node = $this->drupalGetNodeByTitle($title); | ||||
|     $this->drupalGet('node/' . $node->id() . '/edit'); | ||||
|     $this->drupalPostAjaxForm(NULL, [], array('field_test_multi_add_more' => t('Add another item'))); | ||||
|     $this->drupalPostAjaxForm(NULL, [], array('field_test_multi_add_more' => t('Add another item'))); | ||||
|     $edit = [ | ||||
|       'field_test_multi[1][value]' => $example_text_2, | ||||
|       'field_test_multi[2][value]' => $example_text_3, | ||||
|     ]; | ||||
|     $this->drupalPostForm(NULL, $edit, t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->drupalPostForm(NULL, $edit, t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertFieldByName('field_test_multi[0][value]', $example_text_1); | ||||
|     $this->assertFieldByName('field_test_multi[1][value]', $example_text_2); | ||||
|     $this->assertFieldByName('field_test_multi[2][value]', $example_text_3); | ||||
| 
 | ||||
|     // Now save the node and make sure all values got saved.
 | ||||
|     $this->drupalPostForm(NULL, [], t('Save')); | ||||
|     $this->assertText($example_text_1); | ||||
|     $this->assertText($example_text_2); | ||||
|     $this->assertText($example_text_3); | ||||
| 
 | ||||
|     // Edit again, change the menu_ui settings and click on preview.
 | ||||
|     $this->drupalGet('node/' . $node->id() . '/edit'); | ||||
|     $edit = [ | ||||
|       'menu[enabled]' => TRUE, | ||||
|       'menu[title]' => 'Changed title', | ||||
|     ]; | ||||
|     $this->drupalPostForm(NULL, $edit, t('Preview')); | ||||
|     $this->clickLink(t('Back to content editing')); | ||||
|     $this->assertFieldChecked('edit-menu-enabled', 'Menu option is still checked'); | ||||
|     $this->assertFieldByName('menu[title]', 'Changed title', 'Menu link title is correct after preview'); | ||||
| 
 | ||||
|     // Save, change the title while saving and make sure that it is correctly
 | ||||
|     // saved.
 | ||||
|     $edit = [ | ||||
|       'menu[enabled]' => TRUE, | ||||
|       'menu[title]' => 'Second title change', | ||||
|     ]; | ||||
|     $this->drupalPostForm(NULL, $edit, t('Save')); | ||||
|     $this->drupalGet('node/' . $node->id() . '/edit'); | ||||
|     $this->assertFieldByName('menu[title]', 'Second title change', 'Menu link title is correct after saving'); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  |  | |||
|  | @ -10,9 +10,11 @@ | |||
| 
 | ||||
| use Drupal\Core\Entity\EntityInterface; | ||||
| use Drupal\Core\Entity\Display\EntityViewDisplayInterface; | ||||
| use Drupal\Core\Form\FormStateInterface; | ||||
| use Drupal\Core\Session\AccountInterface; | ||||
| use Drupal\node\NodeInterface; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Implements hook_ENTITY_TYPE_view() for node entities. | ||||
|  */ | ||||
|  | @ -175,3 +177,16 @@ function node_test_node_insert(NodeInterface $node) { | |||
|     $node->save(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Implements hook_form_alter(). | ||||
|  */ | ||||
| function node_test_form_alter(&$form, FormStateInterface $form_state, $form_id) { | ||||
|   if (!$form_state->get('node_test_form_alter')) { | ||||
|     drupal_set_message('Storage is not set'); | ||||
|     $form_state->set('node_test_form_alter', TRUE); | ||||
|   } | ||||
|   else { | ||||
|     drupal_set_message('Storage is set'); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -49,93 +49,104 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { | |||
| 
 | ||||
|   /** | ||||
|    * Tests opening Offcanvas tray by click blocks and elements in the blocks. | ||||
|    * | ||||
|    * @dataProvider providerTestBlocks | ||||
|    */ | ||||
|   public function testBlocks() { | ||||
|     // @todo: re-enable once https://www.drupal.org/node/2830485 is resolved.
 | ||||
|     $this->markTestSkipped('Test skipped due to random failures in DrupalCI, see https://www.drupal.org/node/2830485'); | ||||
| 
 | ||||
|   public function testBlocks($block_id, $new_page_text, $element_selector, $label_selector, $button_text, $toolbar_item) { | ||||
|     $web_assert = $this->assertSession(); | ||||
|     $page = $this->getSession()->getPage(); | ||||
|     $block_selector = '#' . $block_id; | ||||
|     $this->drupalGet('user'); | ||||
|     if (isset($toolbar_item)) { | ||||
|       // Check that you can open a toolbar tray and it will be closed after
 | ||||
|       // entering edit mode.
 | ||||
|       if ($element = $page->find('css', "#toolbar-administration a.is-active")) { | ||||
|         // If a tray was open from page load close it.
 | ||||
|         $element->click(); | ||||
|         $this->waitForNoElement("#toolbar-administration a.is-active"); | ||||
|       } | ||||
|       $page->find('css', $toolbar_item)->click(); | ||||
|       $this->waitForElement("{$toolbar_item}.is-active"); | ||||
|     } | ||||
|     $this->toggleEditingMode(); | ||||
|     if (isset($toolbar_item)) { | ||||
|       $this->waitForNoElement("{$toolbar_item}.is-active"); | ||||
|     } | ||||
| 
 | ||||
|     $this->openBlockForm($block_selector); | ||||
| 
 | ||||
|     switch ($block_id) { | ||||
|       case 'block-powered': | ||||
|         // Fill out form, save the form.
 | ||||
|         $page->fillField('settings[label]', $new_page_text); | ||||
|         $page->checkField('settings[label_display]'); | ||||
|         break; | ||||
| 
 | ||||
|       case 'block-branding': | ||||
|         // Fill out form, save the form.
 | ||||
|         $page->fillField('settings[site_information][site_name]', $new_page_text); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     if (isset($new_page_text)) { | ||||
|       $page->pressButton($button_text); | ||||
|       // Make sure the changes are present.
 | ||||
|       // @todo Use a wait method that will take into account the form submitting
 | ||||
|       //   and all JavaScript activity. https://www.drupal.org/node/2837676
 | ||||
|       //   The use \Behat\Mink\WebAssert::pageTextContains to check text.
 | ||||
|       $this->assertJsCondition('jQuery("' . $block_selector . ' ' . $label_selector . '").html() == "' . $new_page_text . '"'); | ||||
|     } | ||||
| 
 | ||||
|     $this->openBlockForm($block_selector); | ||||
| 
 | ||||
|     $this->toggleEditingMode(); | ||||
|     // Canvas should close when editing module is closed.
 | ||||
|     $this->waitForOffCanvasToClose(); | ||||
| 
 | ||||
|     // Go into Edit mode again.
 | ||||
|     $this->toggleEditingMode(); | ||||
| 
 | ||||
|     $element_selector = "$block_selector {$element_selector}"; | ||||
|     // Open block form by clicking a element inside the block.
 | ||||
|     // This confirms that default action for links and form elements is
 | ||||
|     // suppressed.
 | ||||
|     $this->openBlockForm($element_selector); | ||||
| 
 | ||||
|     // Exit edit mode.
 | ||||
|     $this->toggleEditingMode(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Dataprovider for testBlocks(). | ||||
|    */ | ||||
|   public function providerTestBlocks() { | ||||
|     $blocks = [ | ||||
|       [ | ||||
|       'block-powered' => [ | ||||
|         'id' => 'block-powered', | ||||
|         'new_page_text' => 'Can you imagine anyone showing the label on this block?', | ||||
|         'element_selector' => '.content a', | ||||
|         'label_selector' => 'h2', | ||||
|         'button_text' => 'Save Powered by Drupal', | ||||
|         'toolbar_item' => '#toolbar-item-user', | ||||
|       ], | ||||
|       [ | ||||
|       'block-branding' => [ | ||||
|         'id' => 'block-branding', | ||||
|         'new_page_text' => 'The site that will live a very short life.', | ||||
|         'element_selector' => 'a[rel="home"]:nth-child(2)', | ||||
|         'label_selector' => '.site-branding__name a', | ||||
|         'button_text' => 'Save Site branding', | ||||
|         'toolbar_item' => '#toolbar-item-administration', | ||||
|       ], | ||||
|       [ | ||||
|       'block-search' => [ | ||||
|         'id' => 'block-search', | ||||
|         'new_page_text' => NULL, | ||||
|         'element_selector' => '#edit-submit', | ||||
|         'label_selector' => 'h2', | ||||
|         'button_text' => 'Save Search form', | ||||
|         'toolbar_item' => NULL, | ||||
|       ], | ||||
|     ]; | ||||
|     $page = $this->getSession()->getPage(); | ||||
|     foreach ($blocks as $block) { | ||||
|       $block_selector = '#' . $block['id']; | ||||
|       $this->drupalGet('user'); | ||||
|       if (isset($block['toolbar_item'])) { | ||||
|         // Check that you can open a toolbar tray and it will be closed after
 | ||||
|         // entering edit mode.
 | ||||
|         if ($element = $page->find('css', "#toolbar-administration a.is-active")) { | ||||
|           // If a tray was open from page load close it.
 | ||||
|           $element->click(); | ||||
|           $this->waitForNoElement("#toolbar-administration a.is-active"); | ||||
|         } | ||||
|         $page->find('css', $block['toolbar_item'])->click(); | ||||
|         $this->waitForElement("{$block['toolbar_item']}.is-active"); | ||||
|       } | ||||
|       $this->toggleEditingMode(); | ||||
|       if (isset($block['toolbar_item'])) { | ||||
|         $this->waitForNoElement("{$block['toolbar_item']}.is-active"); | ||||
|       } | ||||
| 
 | ||||
|       $this->openBlockForm($block_selector); | ||||
| 
 | ||||
|       switch ($block['id']) { | ||||
|         case 'block-powered': | ||||
|           // Fill out form, save the form.
 | ||||
|           $page->fillField('settings[label]', $block['new_page_text']); | ||||
|           $page->checkField('settings[label_display]'); | ||||
|           break; | ||||
| 
 | ||||
|         case 'block-branding': | ||||
|           // Fill out form, save the form.
 | ||||
|           $page->fillField('settings[site_information][site_name]', $block['new_page_text']); | ||||
|           break; | ||||
|       } | ||||
| 
 | ||||
|       if (isset($block['new_page_text'])) { | ||||
|         $page->pressButton($block['button_text']); | ||||
|         // Make sure the changes are present.
 | ||||
|         $this->assertSession()->assertWaitOnAjaxRequest(); | ||||
|         $web_assert->pageTextContains($block['new_page_text']); | ||||
|       } | ||||
| 
 | ||||
|       $this->openBlockForm($block_selector); | ||||
| 
 | ||||
|       $this->toggleEditingMode(); | ||||
|       // Canvas should close when editing module is closed.
 | ||||
|       $this->waitForOffCanvasToClose(); | ||||
| 
 | ||||
|       // Go into Edit mode again.
 | ||||
|       $this->toggleEditingMode(); | ||||
| 
 | ||||
|       $element_selector = "$block_selector {$block['element_selector']}"; | ||||
|       // Open block form by clicking a element inside the block.
 | ||||
|       // This confirms that default action for links and form elements is
 | ||||
|       // suppressed.
 | ||||
|       $this->openBlockForm($element_selector); | ||||
| 
 | ||||
|       // Exit edit mode.
 | ||||
|       $this->toggleEditingMode(); | ||||
|     } | ||||
|     return $blocks; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  |  | |||
|  | @ -9,6 +9,19 @@ use Drupal\FunctionalJavascriptTests\JavascriptTestBase; | |||
|  */ | ||||
| abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   protected function drupalGet($path, array $options = array(), array $headers = array()) { | ||||
|     $return = parent::drupalGet($path, $options, $headers); | ||||
| 
 | ||||
|     // After the page loaded we need to additionally wait until the settings
 | ||||
|     // tray Ajax activity is done.
 | ||||
|     $this->assertSession()->assertWaitOnAjaxRequest(); | ||||
| 
 | ||||
|     return $return; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Enables a theme. | ||||
|    * | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -17,16 +17,6 @@ $connection->insert('key_value') | |||
|     'name' => 'rest', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->fields([ | ||||
|     'collection' => 'system.schema', | ||||
|     'name' => 'serialization', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->fields([ | ||||
|     'collection' => 'system.schema', | ||||
|     'name' => 'basic_auth', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->execute(); | ||||
| 
 | ||||
| // Update core.extension.
 | ||||
|  | @ -37,9 +27,9 @@ $extensions = $connection->select('config') | |||
|   ->execute() | ||||
|   ->fetchField(); | ||||
| $extensions = unserialize($extensions); | ||||
| $extensions['module']['basic_auth'] = 8000; | ||||
| $extensions['module']['rest'] = 8000; | ||||
| $extensions['module']['serialization'] = 8000; | ||||
| $extensions['module']['basic_auth'] = 0; | ||||
| $extensions['module']['rest'] = 0; | ||||
| $extensions['module']['serialization'] = 0; | ||||
| $connection->update('config') | ||||
|   ->fields([ | ||||
|     'data' => serialize($extensions), | ||||
|  | @ -58,7 +48,7 @@ $config = [ | |||
|       ], | ||||
|     ], | ||||
|   ], | ||||
|   'link_domain' => '~', | ||||
|   'link_domain' => NULL, | ||||
| ]; | ||||
| $data = $connection->insert('config') | ||||
|   ->fields([ | ||||
|  |  | |||
|  | @ -17,11 +17,6 @@ $connection->insert('key_value') | |||
|     'name' => 'rest', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->fields([ | ||||
|     'collection' => 'system.schema', | ||||
|     'name' => 'serialization', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->execute(); | ||||
| 
 | ||||
| // Update core.extension.
 | ||||
|  | @ -32,8 +27,8 @@ $extensions = $connection->select('config') | |||
|   ->execute() | ||||
|   ->fetchField(); | ||||
| $extensions = unserialize($extensions); | ||||
| $extensions['module']['rest'] = 8000; | ||||
| $extensions['module']['serialization'] = 8000; | ||||
| $extensions['module']['rest'] = 0; | ||||
| $extensions['module']['serialization'] = 0; | ||||
| $connection->update('config') | ||||
|   ->fields([ | ||||
|     'data' => serialize($extensions), | ||||
|  | @ -52,7 +47,7 @@ $config = [ | |||
|       ], | ||||
|     ], | ||||
|   ], | ||||
|   'link_domain' => '~', | ||||
|   'link_domain' => NULL, | ||||
| ]; | ||||
| $data = $connection->insert('config') | ||||
|   ->fields([ | ||||
|  |  | |||
|  | @ -18,16 +18,6 @@ $connection->insert('key_value') | |||
|     'name' => 'rest', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->fields([ | ||||
|     'collection' => 'system.schema', | ||||
|     'name' => 'serialization', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->fields([ | ||||
|     'collection' => 'system.schema', | ||||
|     'name' => 'basic_auth', | ||||
|     'value' => 'i:8000;', | ||||
|   ]) | ||||
|   ->execute(); | ||||
| 
 | ||||
| // Update core.extension.
 | ||||
|  |  | |||
|  | @ -383,8 +383,11 @@ abstract class EntityResourceTestBase extends ResourceTestBase { | |||
|     $get_headers = $response->getHeaders(); | ||||
| 
 | ||||
|     // Verify that the GET and HEAD responses are the same. The only difference
 | ||||
|     // is that there's no body.
 | ||||
|     $ignored_headers = ['Date', 'Content-Length', 'X-Drupal-Cache', 'X-Drupal-Dynamic-Cache']; | ||||
|     // is that there's no body. For this reason the 'Transfer-Encoding' header
 | ||||
|     // is also added to the list of headers to ignore, as this could be added to
 | ||||
|     // GET requests - depending on web server configuration. This would usually
 | ||||
|     // be 'Transfer-Encoding: chunked'.
 | ||||
|     $ignored_headers = ['Date', 'Content-Length', 'X-Drupal-Cache', 'X-Drupal-Dynamic-Cache', 'Transfer-Encoding']; | ||||
|     foreach ($ignored_headers as $ignored_header) { | ||||
|       unset($head_headers[$ignored_header]); | ||||
|       unset($get_headers[$ignored_header]); | ||||
|  |  | |||
|  | @ -411,6 +411,7 @@ class ModulesListForm extends FormBase { | |||
|     foreach (array_keys($modules['install']) as $module) { | ||||
|       if (!drupal_check_module($module)) { | ||||
|         unset($modules['install'][$module]); | ||||
|         unset($modules['experimental'][$module]); | ||||
|         foreach (array_keys($data[$module]->required_by) as $dependent) { | ||||
|           unset($modules['install'][$dependent]); | ||||
|           unset($modules['dependencies'][$dependent]); | ||||
|  |  | |||
|  | @ -120,6 +120,14 @@ class ExperimentalModuleTest extends WebTestBase { | |||
|     $this->drupalPostForm(NULL, [], 'Continue'); | ||||
|     $this->assertText('2 modules have been enabled: Experimental Test, Experimental Dependency Test'); | ||||
| 
 | ||||
|     // Try to enable an experimental module that can not be due to
 | ||||
|     // hook_requirements().
 | ||||
|     \Drupal::state()->set('experimental_module_requirements_test_requirements', TRUE); | ||||
|     $edit = []; | ||||
|     $edit["modules[Core (Experimental)][experimental_module_requirements_test][enable]"] = TRUE; | ||||
|     $this->drupalPostForm('admin/modules', $edit, 'Install'); | ||||
|     $this->assertUrl('admin/modules', [], 'If the module can not be installed we are not taken to the confirm form.'); | ||||
|     $this->assertText('The Experimental Test Requirements module can not be installed.'); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -192,6 +192,8 @@ abstract class UpdatePathTestBase extends WebTestBase { | |||
|     $this->container = \Drupal::getContainer(); | ||||
| 
 | ||||
|     $this->replaceUser1(); | ||||
| 
 | ||||
|     require_once \Drupal::root() . '/core/includes/update.inc'; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -251,6 +253,28 @@ abstract class UpdatePathTestBase extends WebTestBase { | |||
|     if ($this->checkFailedUpdates) { | ||||
|       $this->assertNoRaw('<strong>' . t('Failed:') . '</strong>'); | ||||
| 
 | ||||
|       // Ensure that there are no pending updates.
 | ||||
|       foreach (['update', 'post_update'] as $update_type) { | ||||
|         switch ($update_type) { | ||||
|           case 'update': | ||||
|             $all_updates = update_get_update_list(); | ||||
|             break; | ||||
|           case 'post_update': | ||||
|             $all_updates = \Drupal::service('update.post_update_registry')->getPendingUpdateInformation(); | ||||
|             break; | ||||
|         } | ||||
|         foreach ($all_updates as $module => $updates) { | ||||
|           if (!empty($updates['pending'])) { | ||||
|             foreach (array_keys($updates['pending']) as $update_name) { | ||||
|               $this->fail("The $update_name() update function from the $module module did not run."); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       // Reset the static cache of drupal_get_installed_schema_version() so that
 | ||||
|       // more complex update path testing works.
 | ||||
|       drupal_static_reset('drupal_get_installed_schema_version'); | ||||
| 
 | ||||
|       // The config schema can be incorrect while the update functions are being
 | ||||
|       // executed. But once the update has been completed, it needs to be valid
 | ||||
|       // again. Assert the schema of all configuration objects now.
 | ||||
|  |  | |||
|  | @ -0,0 +1,6 @@ | |||
| name: 'Experimental Requirements Test' | ||||
| type: module | ||||
| description: 'Module in the experimental package to test hook_requirements() with an experimental module.' | ||||
| package: Core (Experimental) | ||||
| version: VERSION | ||||
| core: 8.x | ||||
|  | @ -0,0 +1,20 @@ | |||
| <?php | ||||
| 
 | ||||
| /** | ||||
|  * @file | ||||
|  * Experimental Test Requirements module to test hook_requirements(). | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * Implements hook_requirements(). | ||||
|  */ | ||||
| function experimental_module_requirements_test_requirements() { | ||||
|   $requirements = []; | ||||
|   if (\Drupal::state()->get('experimental_module_requirements_test_requirements', FALSE)) { | ||||
|     $requirements['experimental_module_requirements_test_requirements'] = [ | ||||
|       'severity' => REQUIREMENT_ERROR, | ||||
|       'description' => t('The Experimental Test Requirements module can not be installed.'), | ||||
|     ]; | ||||
|   } | ||||
|   return $requirements; | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| <?php | ||||
| 
 | ||||
| /** | ||||
|  * @file | ||||
|  * Experimental Test Requirements module to test hook_requirements(). | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * Implements hook_help(). | ||||
|  */ | ||||
| function experimental_module_requirements_test_help($route_name) { | ||||
|   switch ($route_name) { | ||||
|     case 'help.page.experimental_module_requirements_test': | ||||
|       // Make the help text conform to core standards. See | ||||
|       // \Drupal\system\Tests\Module\InstallUninstallTest::assertHelp(). | ||||
|       return t('The Experimental Requirements Test module is not done yet. It may eat your data, but you can read the <a href=":url">online documentation for the Experimental Requirements Test module</a>.', [':url' => 'http://www.example.com']); | ||||
|   } | ||||
| } | ||||
|  | @ -3,7 +3,7 @@ label: Taxonomy terms | |||
| migration_tags: | ||||
|   - Drupal 6 | ||||
| source: | ||||
|   plugin: taxonomy_term | ||||
|   plugin: d6_taxonomy_term | ||||
| process: | ||||
|   # If you are using this file to build a custom migration consider removing | ||||
|   # the tid field to allow incremental migrations. | ||||
|  |  | |||
|  | @ -2,8 +2,9 @@ id: d7_taxonomy_term | |||
| label: Taxonomy terms | ||||
| migration_tags: | ||||
|   - Drupal 7 | ||||
| deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver | ||||
| source: | ||||
|   plugin: taxonomy_term | ||||
|   plugin: d7_taxonomy_term | ||||
| process: | ||||
|   # If you are using this file to build a custom migration consider removing | ||||
|   # the tid field to allow incremental migrations. | ||||
|  | @ -35,3 +36,5 @@ destination: | |||
| migration_dependencies: | ||||
|   required: | ||||
|     - d7_taxonomy_vocabulary | ||||
|   optional: | ||||
|     - d7_field_instance | ||||
|  |  | |||
|  | @ -0,0 +1,130 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\taxonomy\Plugin\migrate; | ||||
| 
 | ||||
| use Drupal\Component\Plugin\Derivative\DeriverBase; | ||||
| use Drupal\Component\Plugin\Exception\PluginNotFoundException; | ||||
| use Drupal\Core\Database\DatabaseExceptionWrapper; | ||||
| use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface; | ||||
| use Drupal\migrate\Exception\RequirementsException; | ||||
| use Drupal\migrate\Plugin\Migration; | ||||
| use Drupal\migrate\Plugin\MigrationDeriverTrait; | ||||
| use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface; | ||||
| use Symfony\Component\DependencyInjection\ContainerInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Deriver for Drupal 7 taxonomy term migrations based on vocabularies. | ||||
|  */ | ||||
| class D7TaxonomyTermDeriver extends DeriverBase implements ContainerDeriverInterface { | ||||
|   use MigrationDeriverTrait; | ||||
| 
 | ||||
|   /** | ||||
|    * The base plugin ID this derivative is for. | ||||
|    * | ||||
|    * @var string | ||||
|    */ | ||||
|   protected $basePluginId; | ||||
| 
 | ||||
|   /** | ||||
|    * Already-instantiated cckfield plugins, keyed by ID. | ||||
|    * | ||||
|    * @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[] | ||||
|    */ | ||||
|   protected $cckPluginCache; | ||||
| 
 | ||||
|   /** | ||||
|    * The CCK plugin manager. | ||||
|    * | ||||
|    * @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface | ||||
|    */ | ||||
|   protected $cckPluginManager; | ||||
| 
 | ||||
|   /** | ||||
|    * D7TaxonomyTermDeriver constructor. | ||||
|    * | ||||
|    * @param string $base_plugin_id | ||||
|    *   The base plugin ID for the plugin ID. | ||||
|    * @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager | ||||
|    *   The CCK plugin manager. | ||||
|    */ | ||||
|   public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager) { | ||||
|     $this->basePluginId = $base_plugin_id; | ||||
|     $this->cckPluginManager = $cck_manager; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static function create(ContainerInterface $container, $base_plugin_id) { | ||||
|     return new static( | ||||
|       $base_plugin_id, | ||||
|       $container->get('plugin.manager.migrate.cckfield') | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function getDerivativeDefinitions($base_plugin_definition) { | ||||
|     $fields = []; | ||||
|     try { | ||||
|       $source_plugin = static::getSourcePlugin('d7_field_instance'); | ||||
|       $source_plugin->checkRequirements(); | ||||
| 
 | ||||
|       // Read all field instance definitions in the source database.
 | ||||
|       foreach ($source_plugin as $row) { | ||||
|         if ($row->getSourceProperty('entity_type') == 'taxonomy_term') { | ||||
|           $fields[$row->getSourceProperty('bundle')][$row->getSourceProperty('field_name')] = $row->getSource(); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     catch (RequirementsException $e) { | ||||
|       // If checkRequirements() failed then the field module did not exist and
 | ||||
|       // we do not have any fields. Therefore, $fields will be empty and below
 | ||||
|       // we'll create a migration just for the node properties.
 | ||||
|     } | ||||
| 
 | ||||
|     try { | ||||
|       foreach (static::getSourcePlugin('d7_taxonomy_vocabulary') as $row) { | ||||
|         $bundle = $row->getSourceProperty('machine_name'); | ||||
|         $values = $base_plugin_definition; | ||||
| 
 | ||||
|         $values['label'] = t('@label (@type)', [ | ||||
|           '@label' => $values['label'], | ||||
|           '@type' => $row->getSourceProperty('name'), | ||||
|         ]); | ||||
|         $values['source']['bundle'] = $bundle; | ||||
|         $values['destination']['default_bundle'] = $bundle; | ||||
| 
 | ||||
|         /** @var Migration $migration */ | ||||
|         $migration = \Drupal::service('plugin.manager.migration')->createStubMigration($values); | ||||
|         if (isset($fields[$bundle])) { | ||||
|           foreach ($fields[$bundle] as $field_name => $info) { | ||||
|             $field_type = $info['type']; | ||||
|             try { | ||||
|               $plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration); | ||||
|               if (!isset($this->cckPluginCache[$field_type])) { | ||||
|                 $this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration); | ||||
|               } | ||||
|               $this->cckPluginCache[$field_type] | ||||
|                 ->processCckFieldValues($migration, $field_name, $info); | ||||
|             } | ||||
|             catch (PluginNotFoundException $ex) { | ||||
|               $migration->setProcessOfProperty($field_name, $field_name); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|         $this->derivatives[$bundle] = $migration->getPluginDefinition(); | ||||
|       } | ||||
|     } | ||||
|     catch (DatabaseExceptionWrapper $e) { | ||||
|       // Once we begin iterating the source plugin it is possible that the
 | ||||
|       // source tables will not exist. This can happen when the
 | ||||
|       // MigrationPluginManager gathers up the migration definitions but we do
 | ||||
|       // not actually have a Drupal 7 source database.
 | ||||
|     } | ||||
| 
 | ||||
|     return $this->derivatives; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -14,6 +14,10 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; | |||
|  *   id = "taxonomy_term", | ||||
|  *   source_provider = "taxonomy" | ||||
|  * ) | ||||
|  * | ||||
|  * @deprecated in Drupal 8.3.0, intended to be removed in Drupal 9.0.0. | ||||
|  *   Use \Drupal\taxonomy\Plugin\migrate\source\d6\Term or | ||||
|  *   \Drupal\taxonomy\Plugin\migrate\source\d7\Term. | ||||
|  */ | ||||
| class Term extends DrupalSqlBase { | ||||
| 
 | ||||
|  | @ -50,7 +54,7 @@ class Term extends DrupalSqlBase { | |||
|       ->orderBy('td.tid'); | ||||
| 
 | ||||
|     if (isset($this->configuration['vocabulary'])) { | ||||
|       $query->condition('td.vid', $this->configuration['vocabulary'], 'IN'); | ||||
|       $query->condition('td.vid', (array) $this->configuration['vocabulary'], 'IN'); | ||||
|     } | ||||
| 
 | ||||
|     return $query; | ||||
|  |  | |||
							
								
								
									
										74
									
								
								core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								core/modules/taxonomy/src/Plugin/migrate/source/d6/Term.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\taxonomy\Plugin\migrate\source\d6; | ||||
| 
 | ||||
| use Drupal\migrate\Row; | ||||
| use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; | ||||
| 
 | ||||
| /** | ||||
|  * Taxonomy term source from database. | ||||
|  * | ||||
|  * @todo Support term_relation, term_synonym table if possible. | ||||
|  * | ||||
|  * @MigrateSource( | ||||
|  *   id = "d6_taxonomy_term", | ||||
|  *   source_provider = "taxonomy" | ||||
|  * ) | ||||
|  */ | ||||
| class Term extends DrupalSqlBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function query() { | ||||
|     $query = $this->select('term_data', 'td') | ||||
|       ->fields('td') | ||||
|       ->distinct() | ||||
|       ->orderBy('td.tid'); | ||||
| 
 | ||||
|     if (isset($this->configuration['bundle'])) { | ||||
|       $query->condition('td.vid', (array) $this->configuration['bundle'], 'IN'); | ||||
|     } | ||||
| 
 | ||||
|     return $query; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function fields() { | ||||
|     $fields = [ | ||||
|       'tid' => $this->t('The term ID.'), | ||||
|       'vid' => $this->t('Existing term VID'), | ||||
|       'name' => $this->t('The name of the term.'), | ||||
|       'description' => $this->t('The term description.'), | ||||
|       'weight' => $this->t('Weight'), | ||||
|       'parent' => $this->t("The Drupal term IDs of the term's parents."), | ||||
|     ]; | ||||
|     return $fields; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function prepareRow(Row $row) { | ||||
|     // Find parents for this row.
 | ||||
|     $parents = $this->select('term_hierarchy', 'th') | ||||
|       ->fields('th', ['parent', 'tid']) | ||||
|       ->condition('tid', $row->getSourceProperty('tid')) | ||||
|       ->execute() | ||||
|       ->fetchCol(); | ||||
|     $row->setSourceProperty('parent', $parents); | ||||
| 
 | ||||
|     return parent::prepareRow($row); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function getIds() { | ||||
|     $ids['tid']['type'] = 'integer'; | ||||
|     return $ids; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										84
									
								
								core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\taxonomy\Plugin\migrate\source\d7; | ||||
| 
 | ||||
| use Drupal\migrate\Row; | ||||
| use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity; | ||||
| 
 | ||||
| /** | ||||
|  * Taxonomy term source from database. | ||||
|  * | ||||
|  * @todo Support term_relation, term_synonym table if possible. | ||||
|  * | ||||
|  * @MigrateSource( | ||||
|  *   id = "d7_taxonomy_term", | ||||
|  *   source_provider = "taxonomy" | ||||
|  * ) | ||||
|  */ | ||||
| class Term extends FieldableEntity { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function query() { | ||||
|     $query = $this->select('taxonomy_term_data', 'td') | ||||
|       ->fields('td') | ||||
|       ->distinct() | ||||
|       ->orderBy('tid'); | ||||
|     $query->leftJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid'); | ||||
|     $query->addField('tv', 'machine_name'); | ||||
| 
 | ||||
|     if (isset($this->configuration['bundle'])) { | ||||
|       $query->condition('tv.machine_name', (array) $this->configuration['bundle'], 'IN'); | ||||
|     } | ||||
| 
 | ||||
|     return $query; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function fields() { | ||||
|     $fields = [ | ||||
|       'tid' => $this->t('The term ID.'), | ||||
|       'vid' => $this->t('Existing term VID'), | ||||
|       'machine_name' => $this->t('Vocabulary machine name'), | ||||
|       'name' => $this->t('The name of the term.'), | ||||
|       'description' => $this->t('The term description.'), | ||||
|       'weight' => $this->t('Weight'), | ||||
|       'parent' => $this->t("The Drupal term IDs of the term's parents."), | ||||
|       'format' => $this->t("Format of the term description."), | ||||
|     ]; | ||||
|     return $fields; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function prepareRow(Row $row) { | ||||
|     // Get Field API field values.
 | ||||
|     foreach (array_keys($this->getFields('taxonomy_term', $row->getSourceProperty('machine_name'))) as $field) { | ||||
|       $tid = $row->getSourceProperty('tid'); | ||||
|       $row->setSourceProperty($field, $this->getFieldValues('taxonomy_term', $field, $tid)); | ||||
|     } | ||||
| 
 | ||||
|     // Find parents for this row.
 | ||||
|     $parents = $this->select('taxonomy_term_hierarchy', 'th') | ||||
|       ->fields('th', ['parent', 'tid']) | ||||
|       ->condition('tid', $row->getSourceProperty('tid')) | ||||
|       ->execute() | ||||
|       ->fetchCol(); | ||||
|     $row->setSourceProperty('parent', $parents); | ||||
| 
 | ||||
|     return parent::prepareRow($row); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function getIds() { | ||||
|     $ids['tid']['type'] = 'integer'; | ||||
|     return $ids; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -13,7 +13,16 @@ use Drupal\taxonomy\TermInterface; | |||
|  */ | ||||
| class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { | ||||
| 
 | ||||
|   public static $modules = array('taxonomy', 'text'); | ||||
|   public static $modules = [ | ||||
|     'comment', | ||||
|     'datetime', | ||||
|     'image', | ||||
|     'link', | ||||
|     'node', | ||||
|     'taxonomy', | ||||
|     'telephone', | ||||
|     'text', | ||||
|   ]; | ||||
| 
 | ||||
|   /** | ||||
|    * The cached taxonomy tree items, keyed by vid and tid. | ||||
|  | @ -28,7 +37,16 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { | |||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
|     $this->installEntitySchema('taxonomy_term'); | ||||
|     $this->executeMigrations(['d7_taxonomy_vocabulary', 'd7_taxonomy_term']); | ||||
|     $this->installConfig(static::$modules); | ||||
| 
 | ||||
|     $this->executeMigrations([ | ||||
|       'd7_node_type', | ||||
|       'd7_comment_type', | ||||
|       'd7_field', | ||||
|       'd7_taxonomy_vocabulary', | ||||
|       'd7_field_instance', | ||||
|       'd7_taxonomy_term' | ||||
|     ]); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -48,8 +66,12 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { | |||
|    *   The weight the migrated entity should have. | ||||
|    * @param array $expected_parents | ||||
|    *   The parent terms the migrated entity should have. | ||||
|    * @param int $expected_field_integer_value | ||||
|    *   The value the migrated entity field should have. | ||||
|    * @param int $expected_term_reference_tid | ||||
|    *   The term reference id the migrated entity field should have. | ||||
|    */ | ||||
|   protected function assertEntity($id, $expected_label, $expected_vid, $expected_description = '', $expected_format = NULL, $expected_weight = 0, $expected_parents = []) { | ||||
|   protected function assertEntity($id, $expected_label, $expected_vid, $expected_description = '', $expected_format = NULL, $expected_weight = 0, $expected_parents = [], $expected_field_integer_value = NULL, $expected_term_reference_tid = NULL) { | ||||
|     /** @var \Drupal\taxonomy\TermInterface $entity */ | ||||
|     $entity = Term::load($id); | ||||
|     $this->assertTrue($entity instanceof TermInterface); | ||||
|  | @ -60,6 +82,14 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { | |||
|     $this->assertEqual($expected_weight, $entity->getWeight()); | ||||
|     $this->assertIdentical($expected_parents, $this->getParentIDs($id)); | ||||
|     $this->assertHierarchy($expected_vid, $id, $expected_parents); | ||||
|     if (!is_null($expected_field_integer_value)) { | ||||
|       $this->assertTrue($entity->hasField('field_integer')); | ||||
|       $this->assertEquals($expected_field_integer_value, $entity->field_integer->value); | ||||
|     } | ||||
|     if (!is_null($expected_term_reference_tid)) { | ||||
|       $this->assertTrue($entity->hasField('field_integer')); | ||||
|       $this->assertEquals($expected_term_reference_tid, $entity->field_term_reference->target_id); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -67,9 +97,9 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase { | |||
|    */ | ||||
|   public function testTaxonomyTerms() { | ||||
|     $this->assertEntity(1, 'General discussion', 'forums', '', NULL, 2); | ||||
|     $this->assertEntity(2, 'Term1', 'test_vocabulary', 'The first term.', 'filtered_html'); | ||||
|     $this->assertEntity(2, 'Term1', 'test_vocabulary', 'The first term.', 'filtered_html', 0, [], NULL, 3); | ||||
|     $this->assertEntity(3, 'Term2', 'test_vocabulary', 'The second term.', 'filtered_html'); | ||||
|     $this->assertEntity(4, 'Term3', 'test_vocabulary', 'The third term.', 'full_html', 0, [3]); | ||||
|     $this->assertEntity(4, 'Term3', 'test_vocabulary', 'The third term.', 'full_html', 0, [3], 6); | ||||
|     $this->assertEntity(5, 'Custom Forum', 'forums', 'Where the cool kids are.', NULL, 3); | ||||
|     $this->assertEntity(6, 'Games', 'forums', '', NULL, 4); | ||||
|     $this->assertEntity(7, 'Minecraft', 'forums', '', NULL, 1, [6]); | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source; | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d6; | ||||
| 
 | ||||
| /** | ||||
|  * Tests the taxonomy term source with vocabulary filter. | ||||
|  * | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\Term | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\d6\Term | ||||
|  * @group taxonomy | ||||
|  */ | ||||
| class TermSourceWithVocabularyFilterTest extends TermTest { | ||||
|  | @ -47,7 +47,7 @@ class TermSourceWithVocabularyFilterTest extends TermTest { | |||
| 
 | ||||
|     // Set up source plugin configuration.
 | ||||
|     $tests[0]['configuration'] = [ | ||||
|       'vocabulary' => [5], | ||||
|       'bundle' => [5], | ||||
|     ]; | ||||
| 
 | ||||
|     return $tests; | ||||
|  | @ -1,13 +1,13 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source; | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d6; | ||||
| 
 | ||||
| use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; | ||||
| 
 | ||||
| /** | ||||
|  * Tests taxonomy term source plugin. | ||||
|  * | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\Term | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\d6\Term | ||||
|  * @group taxonomy | ||||
|  */ | ||||
| class TermTest extends MigrateSqlSourceTestBase { | ||||
|  | @ -67,6 +67,13 @@ class TermTest extends MigrateSqlSourceTestBase { | |||
|         'description' => 'description value 6', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'vid' => 3, | ||||
|         'name' => 'name value 7', | ||||
|         'description' => 'description value 7', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[0]['source_data']['term_hierarchy'] = [ | ||||
|       [ | ||||
|  | @ -97,6 +104,10 @@ class TermTest extends MigrateSqlSourceTestBase { | |||
|         'tid' => 6, | ||||
|         'parent' => 2, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'parent' => 0, | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     // The expected results.
 | ||||
|  | @ -149,8 +160,58 @@ class TermTest extends MigrateSqlSourceTestBase { | |||
|         'weight' => 0, | ||||
|         'parent' => [3, 2], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'vid' => 3, | ||||
|         'name' => 'name value 7', | ||||
|         'description' => 'description value 7', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     $tests[0]['expected_count'] = NULL; | ||||
|     // Empty configuration will return terms for all vocabularies.
 | ||||
|     $tests[0]['configuration'] = []; | ||||
| 
 | ||||
|     // Change configuration to get one vocabulary, 5.
 | ||||
|     $tests[1]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[1]['expected_data'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 1', | ||||
|         'description' => 'description value 1', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 4', | ||||
|         'description' => 'description value 4', | ||||
|         'weight' => 1, | ||||
|         'parent' => [1], | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[1]['expected_count'] = NULL; | ||||
|     $tests[1]['configuration']['bundle'] = ['5']; | ||||
| 
 | ||||
|     // Same as previous test, but with configuration vocabulary as a string
 | ||||
|     // instead of an array.
 | ||||
|     $tests[2]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[2]['expected_data'] = $tests[1]['expected_data']; | ||||
|     $tests[2]['expected_count'] = NULL; | ||||
|     $tests[2]['configuration']['bundle'] = '5'; | ||||
| 
 | ||||
|     // Change configuration to get two vocabularies, 5 and 6.
 | ||||
|     $tests[3]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[3]['expected_data'] = $tests[0]['expected_data']; | ||||
|     // Remove the last element because it is for vid 3.
 | ||||
|     array_pop($tests[3]['expected_data']); | ||||
|     $tests[3]['expected_count'] = NULL; | ||||
|     $tests[3]['configuration']['bundle'] = ['5', '6']; | ||||
| 
 | ||||
|     return $tests; | ||||
|   } | ||||
| 
 | ||||
|  | @ -0,0 +1,56 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d7; | ||||
| 
 | ||||
| /** | ||||
|  * Tests the taxonomy term source with vocabulary filter. | ||||
|  * | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\d7\Term | ||||
|  * @group taxonomy | ||||
|  */ | ||||
| class TermSourceWithVocabularyFilterTest extends TermTest { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = ['taxonomy', 'migrate_drupal']; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function providerSource() { | ||||
|     // Get the source data from parent.
 | ||||
|     $tests = parent::providerSource(); | ||||
| 
 | ||||
|     // The expected results.
 | ||||
|     $tests[0]['expected_data'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 1', | ||||
|         'description' => 'description value 1', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 4', | ||||
|         'description' => 'description value 4', | ||||
|         'weight' => 1, | ||||
|         'parent' => [1], | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     // We know there are two rows with machine_name == 'tags'.
 | ||||
|     $tests[0]['expected_count'] = 2; | ||||
| 
 | ||||
|     // Set up source plugin configuration.
 | ||||
|     $tests[0]['configuration'] = [ | ||||
|       'bundle' => ['tags'], | ||||
|     ]; | ||||
| 
 | ||||
|     return $tests; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,258 @@ | |||
| <?php | ||||
| 
 | ||||
| namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d7; | ||||
| 
 | ||||
| use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; | ||||
| 
 | ||||
| /** | ||||
|  * Tests taxonomy term source plugin. | ||||
|  * | ||||
|  * @covers \Drupal\taxonomy\Plugin\migrate\source\d7\Term | ||||
|  * @group taxonomy | ||||
|  */ | ||||
| class TermTest extends MigrateSqlSourceTestBase { | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public static $modules = ['taxonomy', 'migrate_drupal']; | ||||
| 
 | ||||
|   /** | ||||
|    * {@inheritdoc} | ||||
|    */ | ||||
|   public function providerSource() { | ||||
|     $tests = []; | ||||
| 
 | ||||
|     // The source data.
 | ||||
|     $tests[0]['source_data']['taxonomy_term_data'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 1', | ||||
|         'description' => 'description value 1', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 2, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 2', | ||||
|         'description' => 'description value 2', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 3, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 3', | ||||
|         'description' => 'description value 3', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 4', | ||||
|         'description' => 'description value 4', | ||||
|         'weight' => 1, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 5, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 5', | ||||
|         'description' => 'description value 5', | ||||
|         'weight' => 1, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 6, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 6', | ||||
|         'description' => 'description value 6', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'vid' => 3, | ||||
|         'name' => 'name value 7', | ||||
|         'description' => 'description value 7', | ||||
|         'weight' => 0, | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[0]['source_data']['taxonomy_term_hierarchy'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'parent' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 2, | ||||
|         'parent' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 3, | ||||
|         'parent' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'parent' => 1, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 5, | ||||
|         'parent' => 2, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 6, | ||||
|         'parent' => 3, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 6, | ||||
|         'parent' => 2, | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'parent' => 0, | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[0]['source_data']['taxonomy_vocabulary'] = [ | ||||
|       [ | ||||
|         'vid' => 5, | ||||
|         'machine_name' => 'tags', | ||||
|       ], | ||||
|       [ | ||||
|         'vid' => 6, | ||||
|         'machine_name' => 'categories', | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[0]['source_data']['field_config_instance'] = [ | ||||
|       [ | ||||
|         'field_name' => 'field_term_field', | ||||
|         'entity_type' => 'taxonomy_term', | ||||
|         'bundle' => 'tags', | ||||
|         'deleted' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'field_name' => 'field_term_field', | ||||
|         'entity_type' => 'taxonomy_term', | ||||
|         'bundle' => 'categories', | ||||
|         'deleted' => 0, | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[0]['source_data']['field_data_field_term_field'] = [ | ||||
|       [ | ||||
|         'entity_type' => 'taxonomy_term', | ||||
|         'bundle' => 'tags', | ||||
|         'deleted' => 0, | ||||
|         'entity_id' => 1, | ||||
|         'delta' => 0, | ||||
|       ], | ||||
|       [ | ||||
|         'entity_type' => 'taxonomy_term', | ||||
|         'bundle' => 'categories', | ||||
|         'deleted' => 0, | ||||
|         'entity_id' => 1, | ||||
|         'delta' => 0, | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     // The expected results.
 | ||||
|     $tests[0]['expected_data'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 1', | ||||
|         'description' => 'description value 1', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 2, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 2', | ||||
|         'description' => 'description value 2', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 3, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 3', | ||||
|         'description' => 'description value 3', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 4', | ||||
|         'description' => 'description value 4', | ||||
|         'weight' => 1, | ||||
|         'parent' => [1], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 5, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 5', | ||||
|         'description' => 'description value 5', | ||||
|         'weight' => 1, | ||||
|         'parent' => [2], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 6, | ||||
|         'vid' => 6, | ||||
|         'name' => 'name value 6', | ||||
|         'description' => 'description value 6', | ||||
|         'weight' => 0, | ||||
|         'parent' => [3, 2], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 7, | ||||
|         'vid' => 3, | ||||
|         'name' => 'name value 7', | ||||
|         'description' => 'description value 7', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|     ]; | ||||
| 
 | ||||
|     $tests[0]['expected_count'] = NULL; | ||||
|     // Empty configuration will return terms for all vocabularies.
 | ||||
|     $tests[0]['configuration'] = []; | ||||
| 
 | ||||
|     // Change configuration to get one vocabulary, "tags".
 | ||||
|     $tests[1]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[1]['expected_data'] = [ | ||||
|       [ | ||||
|         'tid' => 1, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 1', | ||||
|         'description' => 'description value 1', | ||||
|         'weight' => 0, | ||||
|         'parent' => [0], | ||||
|       ], | ||||
|       [ | ||||
|         'tid' => 4, | ||||
|         'vid' => 5, | ||||
|         'name' => 'name value 4', | ||||
|         'description' => 'description value 4', | ||||
|         'weight' => 1, | ||||
|         'parent' => [1], | ||||
|       ], | ||||
|     ]; | ||||
|     $tests[1]['expected_count'] = NULL; | ||||
|     $tests[1]['configuration']['bundle'] = ['tags']; | ||||
| 
 | ||||
|     // Same as previous test, but with configuration vocabulary as a string
 | ||||
|     // instead of an array.
 | ||||
|     $tests[2]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[2]['expected_data'] = $tests[1]['expected_data']; | ||||
|     $tests[2]['expected_count'] = NULL; | ||||
|     $tests[2]['configuration']['bundle'] = 'tags'; | ||||
| 
 | ||||
|     // Change configuration to get two vocabularies, "tags" and "categories".
 | ||||
|     $tests[3]['source_data'] = $tests[0]['source_data']; | ||||
|     $tests[3]['expected_data'] = $tests[0]['expected_data']; | ||||
|     // Remove the last element because it is for vid 3.
 | ||||
|     array_pop($tests[3]['expected_data']); | ||||
|     $tests[3]['expected_count'] = NULL; | ||||
|     $tests[3]['configuration']['bundle'] = ['tags', 'categories']; | ||||
| 
 | ||||
|     return $tests; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  | @ -3,12 +3,8 @@ label: Profile values | |||
| class: Drupal\user\Plugin\migrate\ProfileValues | ||||
| migration_tags: | ||||
|   - Drupal 6 | ||||
| builder: | ||||
|   plugin: d6_profile_values | ||||
| source: | ||||
|   plugin: d6_profile_field_values | ||||
| load: | ||||
|   plugin: drupal_entity | ||||
| process: | ||||
|   uid: uid | ||||
| destination: | ||||
|  |  | |||
|  | @ -233,7 +233,7 @@ class UserAuthenticationController extends ControllerBase implements ContainerIn | |||
|   /** | ||||
|    * Logs out a user. | ||||
|    * | ||||
|    * @return \Drupal\rest\ResourceResponse | ||||
|    * @return \Symfony\Component\HttpFoundation\Response | ||||
|    *   The response object. | ||||
|    */ | ||||
|   public function logout() { | ||||
|  |  | |||
|  | @ -1172,7 +1172,7 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend | |||
|    * Moves argument options into their place. | ||||
|    * | ||||
|    * When configuring the default argument behavior, almost each of the radio | ||||
|    * buttons has its own fieldset shown bellow it when the radio button is | ||||
|    * buttons has its own fieldset shown below it when the radio button is | ||||
|    * clicked. That fieldset is created through a custom form process callback. | ||||
|    * Each element that has #argument_option defined and pointing to a default
 | ||||
|    * behavior gets moved to the appropriate fieldset. | ||||
|  |  | |||
|  | @ -206,7 +206,7 @@ class InOperator extends FilterPluginBase { | |||
|       } | ||||
| 
 | ||||
|       if (empty($this->options['expose']['multiple'])) { | ||||
|         if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) { | ||||
|         if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce'])) || isset($this->options['value']['all'])) { | ||||
|           $default_value = 'All'; | ||||
|         } | ||||
|         elseif (empty($default_value)) { | ||||
|  |  | |||
|  | @ -18,19 +18,24 @@ class FilterTest extends PluginTestBase { | |||
|    * | ||||
|    * @var array | ||||
|    */ | ||||
|   public static $testViews = array('test_filter'); | ||||
|   public static $testViews = array('test_filter', 'test_filter_in_operator_ui'); | ||||
| 
 | ||||
|   /** | ||||
|    * Modules to enable. | ||||
|    * | ||||
|    * @var array | ||||
|    */ | ||||
|   public static $modules = array('views_ui'); | ||||
|   public static $modules = array('views_ui', 'node'); | ||||
| 
 | ||||
|   protected function setUp() { | ||||
|     parent::setUp(); | ||||
| 
 | ||||
|     $this->enableViewsTestModule(); | ||||
| 
 | ||||
|     $this->adminUser = $this->drupalCreateUser(array('administer views')); | ||||
|     $this->drupalLogin($this->adminUser); | ||||
|     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); | ||||
|     $this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | @ -138,4 +143,23 @@ class FilterTest extends PluginTestBase { | |||
|     $this->assertEqual(count($view->result), 5, format_string('All @count results returned', array('@count' => count($view->displayHandlers)))); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Test no error message is displayed when all options are selected in an | ||||
|    * exposed filter. | ||||
|    */ | ||||
|   public function testInOperatorSelectAllOptions() { | ||||
|     $view = Views::getView('test_filter_in_operator_ui'); | ||||
|     $row['row[type]'] = 'fields'; | ||||
|     $this->drupalPostForm('admin/structure/views/nojs/display/test_filter_in_operator_ui/default/row', $row, t('Apply')); | ||||
|     $field['name[node_field_data.nid]'] = TRUE; | ||||
|     $this->drupalPostForm('admin/structure/views/nojs/add-handler/test_filter_in_operator_ui/default/field', $field, t('Add and configure fields')); | ||||
|     $this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/field/nid', [], t('Apply')); | ||||
|     $edit['options[value][all]'] = TRUE; | ||||
|     $edit['options[value][article]'] = TRUE; | ||||
|     $edit['options[value][page]'] = TRUE; | ||||
|     $this->drupalPostForm('admin/structure/views/nojs/handler/test_filter_in_operator_ui/default/filter/type', $edit, t('Apply')); | ||||
|     $this->drupalPostForm('admin/structure/views/view/test_filter_in_operator_ui/edit/default', [], t('Save')); | ||||
|     $this->drupalPostForm(NULL, [], t('Update preview')); | ||||
|     $this->assertNoText('An illegal choice has been detected.'); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -61,7 +61,7 @@ class Views { | |||
|   /** | ||||
|    * Returns the views data helper service. | ||||
|    * | ||||
|    * @return \Drupal\views\ViewsData | ||||
|    * @return \Drupal\views\ViewsDataHelper | ||||
|    *   Returns a views data helper object. | ||||
|    */ | ||||
|   public static function viewsDataHelper() { | ||||
|  |  | |||
|  | @ -2,6 +2,10 @@ | |||
| 
 | ||||
| namespace Drupal\FunctionalJavascriptTests; | ||||
| 
 | ||||
| use Behat\Mink\Element\NodeElement; | ||||
| use Behat\Mink\Exception\ElementHtmlException; | ||||
| use Behat\Mink\Exception\ElementNotFoundException; | ||||
| use Behat\Mink\Exception\UnsupportedDriverActionException; | ||||
| use Drupal\Tests\WebAssert; | ||||
| 
 | ||||
| /** | ||||
|  | @ -39,4 +43,199 @@ class JSWebAssert extends WebAssert { | |||
|     $this->assertWaitOnAjaxRequest(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Test that a node, or it's specific corner, is visible in the viewport. | ||||
|    * | ||||
|    * Note: Always set the viewport size. This can be done with a PhantomJS | ||||
|    * startup parameter or in your test with \Behat\Mink\Session->resizeWindow(). | ||||
|    * Drupal CI Javascript tests by default use a viewport of 1024x768px. | ||||
|    * | ||||
|    * @param string $selector_type | ||||
|    *   The element selector type (CSS, XPath). | ||||
|    * @param string|array $selector | ||||
|    *   The element selector. Note: the first found element is used. | ||||
|    * @param bool|string $corner | ||||
|    *   (Optional) The corner to test: | ||||
|    *   topLeft, topRight, bottomRight, bottomLeft. | ||||
|    *   Or FALSE to check the complete element (default). | ||||
|    * @param string $message | ||||
|    *   (optional) A message for the exception. | ||||
|    * | ||||
|    * @throws \Behat\Mink\Exception\ElementHtmlException | ||||
|    *   When the element doesn't exist. | ||||
|    * @throws \Behat\Mink\Exception\ElementNotFoundException | ||||
|    *   When the element is not visible in the viewport. | ||||
|    */ | ||||
|   public function assertVisibleInViewport($selector_type, $selector, $corner = FALSE, $message = 'Element is not visible in the viewport.') { | ||||
|     $node = $this->session->getPage()->find($selector_type, $selector); | ||||
|     if ($node === NULL) { | ||||
|       if (is_array($selector)) { | ||||
|         $selector = implode(' ', $selector); | ||||
|       } | ||||
|       throw new ElementNotFoundException($this->session->getDriver(), 'element', $selector_type, $selector); | ||||
|     } | ||||
| 
 | ||||
|     // Check if the node is visible on the page, which is a prerequisite of
 | ||||
|     // being visible in the viewport.
 | ||||
|     if (!$node->isVisible()) { | ||||
|       throw new ElementHtmlException($message, $this->session->getDriver(), $node); | ||||
|     } | ||||
| 
 | ||||
|     $result = $this->checkNodeVisibilityInViewport($node, $corner); | ||||
| 
 | ||||
|     if (!$result) { | ||||
|       throw new ElementHtmlException($message, $this->session->getDriver(), $node); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Test that a node, or its specific corner, is not visible in the viewport. | ||||
|    * | ||||
|    * Note: the node should exist in the page, otherwise this assertion fails. | ||||
|    * | ||||
|    * @param string $selector_type | ||||
|    *   The element selector type (CSS, XPath). | ||||
|    * @param string|array $selector | ||||
|    *   The element selector. Note: the first found element is used. | ||||
|    * @param bool|string $corner | ||||
|    *   (Optional) Corner to test: topLeft, topRight, bottomRight, bottomLeft. | ||||
|    *   Or FALSE to check the complete element (default). | ||||
|    * @param string $message | ||||
|    *   (optional) A message for the exception. | ||||
|    * | ||||
|    * @throws \Behat\Mink\Exception\ElementHtmlException | ||||
|    *   When the element doesn't exist. | ||||
|    * @throws \Behat\Mink\Exception\ElementNotFoundException | ||||
|    *   When the element is not visible in the viewport. | ||||
|    * | ||||
|    * @see \Drupal\FunctionalJavascriptTests\JSWebAssert::assertVisibleInViewport() | ||||
|    */ | ||||
|   public function assertNotVisibleInViewport($selector_type, $selector, $corner = FALSE, $message = 'Element is visible in the viewport.') { | ||||
|     $node = $this->session->getPage()->find($selector_type, $selector); | ||||
|     if ($node === NULL) { | ||||
|       if (is_array($selector)) { | ||||
|         $selector = implode(' ', $selector); | ||||
|       } | ||||
|       throw new ElementNotFoundException($this->session->getDriver(), 'element', $selector_type, $selector); | ||||
|     } | ||||
| 
 | ||||
|     $result = $this->checkNodeVisibilityInViewport($node, $corner); | ||||
| 
 | ||||
|     if ($result) { | ||||
|       throw new ElementHtmlException($message, $this->session->getDriver(), $node); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Check the visibility of a node, or it's specific corner. | ||||
|    * | ||||
|    * @param \Behat\Mink\Element\NodeElement $node | ||||
|    *   A valid node. | ||||
|    * @param bool|string $corner | ||||
|    *   (Optional) Corner to test: topLeft, topRight, bottomRight, bottomLeft. | ||||
|    *   Or FALSE to check the complete element (default). | ||||
|    * | ||||
|    * @return bool | ||||
|    *   Returns TRUE if the node is visible in the viewport, FALSE otherwise. | ||||
|    * | ||||
|    * @throws \Behat\Mink\Exception\UnsupportedDriverActionException | ||||
|    *   When an invalid corner specification is given. | ||||
|    */ | ||||
|   private function checkNodeVisibilityInViewport(NodeElement $node, $corner = FALSE) { | ||||
|     $xpath = $node->getXpath(); | ||||
| 
 | ||||
|     // Build the Javascript to test if the complete element or a specific corner
 | ||||
|     // is in the viewport.
 | ||||
|     switch ($corner) { | ||||
|       case 'topLeft': | ||||
|         $test_javascript_function = <<<JS | ||||
|           function t(r, lx, ly) { | ||||
|             return ( | ||||
|               r.top >= 0 && | ||||
|               r.top <= ly && | ||||
|               r.left >= 0 && | ||||
|               r.left <= lx | ||||
|             ) | ||||
|           } | ||||
| JS; | ||||
|         break; | ||||
| 
 | ||||
|       case 'topRight': | ||||
|         $test_javascript_function = <<<JS | ||||
|           function t(r, lx, ly) { | ||||
|             return ( | ||||
|               r.top >= 0 && | ||||
|               r.top <= ly && | ||||
|               r.right >= 0 && | ||||
|               r.right <= lx | ||||
|             ); | ||||
|           } | ||||
| JS; | ||||
|         break; | ||||
| 
 | ||||
|       case 'bottomRight': | ||||
|         $test_javascript_function = <<<JS | ||||
|           function t(r, lx, ly) { | ||||
|             return ( | ||||
|               r.bottom >= 0 && | ||||
|               r.bottom <= ly && | ||||
|               r.right >= 0 && | ||||
|               r.right <= lx | ||||
|             ); | ||||
|           } | ||||
| JS; | ||||
|         break; | ||||
| 
 | ||||
|       case 'bottomLeft': | ||||
|         $test_javascript_function = <<<JS | ||||
|           function t(r, lx, ly) { | ||||
|             return ( | ||||
|               r.bottom >= 0 && | ||||
|               r.bottom <= ly && | ||||
|               r.left >= 0 && | ||||
|               r.left <= lx | ||||
|             ); | ||||
|           } | ||||
| JS; | ||||
|         break; | ||||
| 
 | ||||
|       case FALSE: | ||||
|         $test_javascript_function = <<<JS | ||||
|           function t(r, lx, ly) { | ||||
|             return ( | ||||
|               r.top >= 0 && | ||||
|               r.left >= 0 && | ||||
|               r.bottom <= ly && | ||||
|               r.right <= lx | ||||
|             ); | ||||
|           } | ||||
| JS; | ||||
|         break; | ||||
| 
 | ||||
|       // Throw an exception if an invalid corner parameter is given.
 | ||||
|       default: | ||||
|         throw new UnsupportedDriverActionException($corner, $this->session->getDriver()); | ||||
|     } | ||||
| 
 | ||||
|     // Build the full Javascript test. The shared logic gets the corner
 | ||||
|     // specific test logic injected.
 | ||||
|     $full_javascript_visibility_test = <<<JS | ||||
|       (function(t){ | ||||
|         var w = window, | ||||
|         d = document, | ||||
|         e = d.documentElement, | ||||
|         n = d.evaluate("$xpath", d, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue, | ||||
|         r = n.getBoundingClientRect(), | ||||
|         lx = (w.innerWidth || e.clientWidth), | ||||
|         ly = (w.innerHeight || e.clientHeight); | ||||
| 
 | ||||
|         return t(r, lx, ly); | ||||
|       }($test_javascript_function)); | ||||
| JS; | ||||
| 
 | ||||
|     // Check the visibility by injecting and executing the full Javascript test
 | ||||
|     // script in the page.
 | ||||
|     return $this->session->evaluateScript($full_javascript_visibility_test); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ abstract class KernelTestBase extends \PHPUnit_Framework_TestCase implements Ser | |||
|    * | ||||
|    * @var array | ||||
|    */ | ||||
|   public static $modules = array(); | ||||
|   protected static $modules = array(); | ||||
| 
 | ||||
|   /** | ||||
|    * The virtual filesystem root directory. | ||||
|  |  | |||
|  | @ -175,7 +175,7 @@ abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase { | |||
|    * | ||||
|    * @see \Drupal\Tests\BrowserTestBase::installDrupal() | ||||
|    */ | ||||
|   public static $modules = []; | ||||
|   protected static $modules = []; | ||||
| 
 | ||||
|   /** | ||||
|    * An array of config object names that are excluded from schema checking. | ||||
|  |  | |||
|  | @ -762,13 +762,7 @@ if (file_exists(__DIR__ . '/settings.pantheon.php')) { | |||
|  * | ||||
|  * Keep this code block at the end of this file to take full effect. | ||||
|  */ | ||||
| <<<<<<< HEAD | ||||
| if (file_exists(__DIR__ . '/settings.local.php')) { | ||||
|   include __DIR__ . '/settings.local.php'; | ||||
| } | ||||
| ======= | ||||
| #
 | ||||
| # if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
 | ||||
| #   include $app_root . '/' . $site_path . '/settings.local.php';
 | ||||
| # }
 | ||||
| >>>>>>> b96f629ea4b63fb16b11b89c0a88fb8524e82359 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								vendor/autoload.php
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/autoload.php
									
										
									
									
										vendored
									
									
								
							|  | @ -2,6 +2,6 @@ | |||
| 
 | ||||
| // autoload.php @generated by Composer
 | ||||
| 
 | ||||
| require_once __DIR__ . '/composer' . '/autoload_real.php'; | ||||
| require_once __DIR__ . '/composer/autoload_real.php'; | ||||
| 
 | ||||
| return ComposerAutoloaderInitDrupal8::getLoader(); | ||||
|  |  | |||
							
								
								
									
										48
									
								
								vendor/composer/ClassLoader.php
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								vendor/composer/ClassLoader.php
									
										
									
									
										vendored
									
									
								
							|  | @ -53,8 +53,9 @@ class ClassLoader | |||
| 
 | ||||
|     private $useIncludePath = false; | ||||
|     private $classMap = array(); | ||||
| 
 | ||||
|     private $classMapAuthoritative = false; | ||||
|     private $missingClasses = array(); | ||||
|     private $apcuPrefix; | ||||
| 
 | ||||
|     public function getPrefixes() | ||||
|     { | ||||
|  | @ -271,6 +272,26 @@ class ClassLoader | |||
|         return $this->classMapAuthoritative; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * APCu prefix to use to cache found/not-found classes, if the extension is enabled. | ||||
|      * | ||||
|      * @param string|null $apcuPrefix | ||||
|      */ | ||||
|     public function setApcuPrefix($apcuPrefix) | ||||
|     { | ||||
|         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The APCu prefix in use, or null if APCu caching is not enabled. | ||||
|      * | ||||
|      * @return string|null | ||||
|      */ | ||||
|     public function getApcuPrefix() | ||||
|     { | ||||
|         return $this->apcuPrefix; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Registers this instance as an autoloader. | ||||
|      * | ||||
|  | @ -313,29 +334,34 @@ class ClassLoader | |||
|      */ | ||||
|     public function findFile($class) | ||||
|     { | ||||
|         // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
 | ||||
|         if ('\\' == $class[0]) { | ||||
|             $class = substr($class, 1); | ||||
|         } | ||||
| 
 | ||||
|         // class map lookup
 | ||||
|         if (isset($this->classMap[$class])) { | ||||
|             return $this->classMap[$class]; | ||||
|         } | ||||
|         if ($this->classMapAuthoritative) { | ||||
|         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { | ||||
|             return false; | ||||
|         } | ||||
|         if (null !== $this->apcuPrefix) { | ||||
|             $file = apcu_fetch($this->apcuPrefix.$class, $hit); | ||||
|             if ($hit) { | ||||
|                 return $file; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         $file = $this->findFileWithExtension($class, '.php'); | ||||
| 
 | ||||
|         // Search for Hack files if we are running on HHVM
 | ||||
|         if ($file === null && defined('HHVM_VERSION')) { | ||||
|         if (false === $file && defined('HHVM_VERSION')) { | ||||
|             $file = $this->findFileWithExtension($class, '.hh'); | ||||
|         } | ||||
| 
 | ||||
|         if ($file === null) { | ||||
|         if (null !== $this->apcuPrefix) { | ||||
|             apcu_add($this->apcuPrefix.$class, $file); | ||||
|         } | ||||
| 
 | ||||
|         if (false === $file) { | ||||
|             // Remember that this class does not exist.
 | ||||
|             return $this->classMap[$class] = false; | ||||
|             $this->missingClasses[$class] = true; | ||||
|         } | ||||
| 
 | ||||
|         return $file; | ||||
|  | @ -399,6 +425,8 @@ class ClassLoader | |||
|         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { | ||||
|             return $file; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								vendor/composer/LICENSE
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/composer/LICENSE
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,4 @@ | |||
| 
 | ||||
| Copyright (c) 2016 Nils Adermann, Jordi Boggiano | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  | @ -17,3 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								vendor/composer/autoload_real.php
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/composer/autoload_real.php
									
										
									
									
										vendored
									
									
								
							|  | @ -23,7 +23,7 @@ class ComposerAutoloaderInitDrupal8 | |||
|         self::$loader = $loader = new \Composer\Autoload\ClassLoader(); | ||||
|         spl_autoload_unregister(array('ComposerAutoloaderInitDrupal8', 'loadClassLoader')); | ||||
| 
 | ||||
|         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION'); | ||||
|         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); | ||||
|         if ($useStaticLoader) { | ||||
|             require_once __DIR__ . '/autoload_static.php'; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										148
									
								
								vendor/composer/installed.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										148
									
								
								vendor/composer/installed.json
									
										
									
									
										vendored
									
									
								
							|  | @ -22,7 +22,7 @@ | |||
|             "composer/composer": "1.0.*@dev", | ||||
|             "phpunit/phpunit": "4.1.*" | ||||
|         }, | ||||
|         "time": "2015-02-18 17:17:01", | ||||
|         "time": "2015-02-18T17:17:01+00:00", | ||||
|         "type": "composer-installer", | ||||
|         "extra": { | ||||
|             "class": "Composer\\Installers\\Installer", | ||||
|  | @ -121,7 +121,7 @@ | |||
|             "phpunit/phpunit": "~4.8|~5.0", | ||||
|             "squizlabs/php_codesniffer": "~2.1.0" | ||||
|         }, | ||||
|         "time": "2016-03-08 17:11:37", | ||||
|         "time": "2016-03-08T17:11:37+00:00", | ||||
|         "type": "composer-plugin", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -165,7 +165,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "4.*" | ||||
|         }, | ||||
|         "time": "2014-11-20 16:49:30", | ||||
|         "time": "2014-11-20T16:49:30+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -210,7 +210,7 @@ | |||
|             "ircmaxell/password-compat": "~1.0", | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2016-01-20 09:13:37", | ||||
|         "time": "2016-01-20T09:13:37+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -267,7 +267,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2016-01-20 09:13:37", | ||||
|         "time": "2016-01-20T09:13:37+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -330,7 +330,7 @@ | |||
|         "suggest": { | ||||
|             "ext-mbstring": "For best performance" | ||||
|         }, | ||||
|         "time": "2016-01-20 09:13:37", | ||||
|         "time": "2016-01-20T09:13:37+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -394,7 +394,7 @@ | |||
|         "require-dev": { | ||||
|             "symfony/expression-language": "~2.4|~3.0.0" | ||||
|         }, | ||||
|         "time": "2016-03-27 12:57:53", | ||||
|         "time": "2016-03-27T12:57:53+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -456,7 +456,7 @@ | |||
|             "symfony/dependency-injection": "", | ||||
|             "symfony/http-kernel": "" | ||||
|         }, | ||||
|         "time": "2016-03-07 14:04:32", | ||||
|         "time": "2016-03-07T14:04:32+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -504,7 +504,7 @@ | |||
|             "reference": "1.0.0", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "time": "2012-12-21 11:40:51", | ||||
|         "time": "2012-12-21T11:40:51+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -555,7 +555,7 @@ | |||
|             "symfony/class-loader": "~2.2", | ||||
|             "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2" | ||||
|         }, | ||||
|         "time": "2015-10-11 09:39:48", | ||||
|         "time": "2015-10-11T09:39:48+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -636,7 +636,7 @@ | |||
|             "symfony/finder": "", | ||||
|             "symfony/var-dumper": "" | ||||
|         }, | ||||
|         "time": "2016-03-25 01:40:30", | ||||
|         "time": "2016-03-25T01:40:30+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -689,7 +689,7 @@ | |||
|             "symfony/http-foundation": "~2.1|~3.0", | ||||
|             "symfony/http-kernel": "~2.1|~3.0" | ||||
|         }, | ||||
|         "time": "2016-08-01 12:05:04", | ||||
|         "time": "2016-08-01T12:05:04+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -736,7 +736,7 @@ | |||
|             "phpunit/phpunit": "~4.5", | ||||
|             "phpunit/phpunit-mock-objects": "~2.3" | ||||
|         }, | ||||
|         "time": "2015-09-21 09:42:36", | ||||
|         "time": "2015-09-21T09:42:36+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -795,7 +795,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.2" | ||||
|         }, | ||||
|         "time": "2014-09-09 13:34:57", | ||||
|         "time": "2014-09-09T13:34:57+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -854,7 +854,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "4.*" | ||||
|         }, | ||||
|         "time": "2014-12-20 21:24:13", | ||||
|         "time": "2014-12-20T21:24:13+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -923,7 +923,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.0" | ||||
|         }, | ||||
|         "time": "2015-04-14 22:21:58", | ||||
|         "time": "2015-04-14T22:21:58+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -996,7 +996,7 @@ | |||
|             "predis/predis": "~1.0", | ||||
|             "satooshi/php-coveralls": "~0.6" | ||||
|         }, | ||||
|         "time": "2015-08-31 12:36:41", | ||||
|         "time": "2015-08-31T12:36:41+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1065,7 +1065,7 @@ | |||
|             "doctrine/cache": "1.*", | ||||
|             "phpunit/phpunit": "4.*" | ||||
|         }, | ||||
|         "time": "2015-08-31 12:32:49", | ||||
|         "time": "2015-08-31T12:32:49+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1138,7 +1138,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~3.7" | ||||
|         }, | ||||
|         "time": "2015-08-31 13:00:22", | ||||
|         "time": "2015-08-31T13:00:22+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1215,7 +1215,7 @@ | |||
|         "suggest": { | ||||
|             "ml/json-ld": "~1.0" | ||||
|         }, | ||||
|         "time": "2015-02-27 09:45:49", | ||||
|         "time": "2015-02-27T09:45:49+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -1274,7 +1274,7 @@ | |||
|             "phpunit/phpunit": "~4.4", | ||||
|             "satooshi/php-coveralls": "dev-master" | ||||
|         }, | ||||
|         "time": "2015-06-22 21:07:51", | ||||
|         "time": "2015-06-22T21:07:51+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1327,7 +1327,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.0" | ||||
|         }, | ||||
|         "time": "2016-05-18 16:56:05", | ||||
|         "time": "2016-05-18T16:56:05+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1377,7 +1377,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.0" | ||||
|         }, | ||||
|         "time": "2015-05-04 20:22:00", | ||||
|         "time": "2015-05-04T20:22:00+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1435,7 +1435,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.0" | ||||
|         }, | ||||
|         "time": "2016-06-24 23:00:38", | ||||
|         "time": "2016-06-24T23:00:38+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1494,7 +1494,7 @@ | |||
|             "sami/sami": "~2.0", | ||||
|             "satooshi/php-coveralls": "1.0.*" | ||||
|         }, | ||||
|         "time": "2016-05-10 14:11:45", | ||||
|         "time": "2016-05-10T14:11:45+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1561,7 +1561,7 @@ | |||
|         "suggest": { | ||||
|             "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." | ||||
|         }, | ||||
|         "time": "2015-12-01 02:52:15", | ||||
|         "time": "2015-12-01T02:52:15+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -1610,7 +1610,7 @@ | |||
|         "require-dev": { | ||||
|             "silex/silex": "~1.0" | ||||
|         }, | ||||
|         "time": "2016-06-02 06:58:42", | ||||
|         "time": "2016-06-02T06:58:42+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1676,7 +1676,7 @@ | |||
|             "symfony/http-foundation": "For using a Symfony Request object", | ||||
|             "symfony/yaml": "For using the YAML loader" | ||||
|         }, | ||||
|         "time": "2016-03-23 13:11:46", | ||||
|         "time": "2016-03-23T13:11:46+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1746,7 +1746,7 @@ | |||
|         "suggest": { | ||||
|             "symfony/event-dispatcher": "DynamicRouter can optionally trigger an event at the start of matching. Minimal version (~2.1)" | ||||
|         }, | ||||
|         "time": "2016-03-31 09:11:39", | ||||
|         "time": "2016-03-31T09:11:39+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1794,7 +1794,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2016-03-03 16:49:40", | ||||
|         "time": "2016-03-03T16:49:40+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1853,7 +1853,7 @@ | |||
|         "require-dev": { | ||||
|             "symfony/finder": "~2.0,>=2.0.5|~3.0.0" | ||||
|         }, | ||||
|         "time": "2016-03-10 19:33:53", | ||||
|         "time": "2016-03-10T19:33:53+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1915,7 +1915,7 @@ | |||
|             "symfony/event-dispatcher": "", | ||||
|             "symfony/process": "" | ||||
|         }, | ||||
|         "time": "2016-03-17 09:19:04", | ||||
|         "time": "2016-03-17T09:19:04+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -1979,7 +1979,7 @@ | |||
|             "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", | ||||
|             "symfony/yaml": "" | ||||
|         }, | ||||
|         "time": "2016-03-21 07:27:21", | ||||
|         "time": "2016-03-21T07:27:21+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2033,7 +2033,7 @@ | |||
|         "suggest": { | ||||
|             "ext-iconv": "For best performance" | ||||
|         }, | ||||
|         "time": "2016-02-26 11:31:02", | ||||
|         "time": "2016-02-26T11:31:02+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2091,7 +2091,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.9" | ||||
|         }, | ||||
|         "time": "2016-03-23 13:11:46", | ||||
|         "time": "2016-03-23T13:11:46+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2150,7 +2150,7 @@ | |||
|         "suggest": { | ||||
|             "zendframework/zend-diactoros": "To use the Zend Diactoros factory" | ||||
|         }, | ||||
|         "time": "2015-05-29 17:57:12", | ||||
|         "time": "2015-05-29T17:57:12+00:00", | ||||
|         "type": "symfony-bridge", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -2213,7 +2213,7 @@ | |||
|             "symfony/property-access": "For using the ObjectNormalizer.", | ||||
|             "symfony/yaml": "For using the default YAML mapping loader." | ||||
|         }, | ||||
|         "time": "2016-03-07 14:04:32", | ||||
|         "time": "2016-03-07T14:04:32+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2279,7 +2279,7 @@ | |||
|             "symfony/config": "", | ||||
|             "symfony/yaml": "" | ||||
|         }, | ||||
|         "time": "2016-03-25 01:40:30", | ||||
|         "time": "2016-03-25T01:40:30+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2353,7 +2353,7 @@ | |||
|             "symfony/property-access": "For using the 2.4 Validator API", | ||||
|             "symfony/yaml": "" | ||||
|         }, | ||||
|         "time": "2016-03-27 12:57:53", | ||||
|         "time": "2016-03-27T12:57:53+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2412,7 +2412,7 @@ | |||
|             "phpunit/phpunit": "~4.6", | ||||
|             "squizlabs/php_codesniffer": "^2.3.1" | ||||
|         }, | ||||
|         "time": "2015-08-10 20:04:20", | ||||
|         "time": "2015-08-10T20:04:20+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2474,7 +2474,7 @@ | |||
|             "zendframework/zend-serializer": "Zend\\Serializer component", | ||||
|             "zendframework/zend-servicemanager": "To support hydrator plugin manager usage" | ||||
|         }, | ||||
|         "time": "2015-09-25 04:06:33", | ||||
|         "time": "2015-09-25T04:06:33+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2532,7 +2532,7 @@ | |||
|             "zendframework/zend-serializer": "^2.5.1, to use the SerializableStrategy", | ||||
|             "zendframework/zend-servicemanager": "^2.5.1, to support hydrator plugin manager usage" | ||||
|         }, | ||||
|         "time": "2015-09-17 14:06:43", | ||||
|         "time": "2015-09-17T14:06:43+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2578,7 +2578,7 @@ | |||
|             "fabpot/php-cs-fixer": "1.7.*", | ||||
|             "phpunit/phpunit": "~4.0" | ||||
|         }, | ||||
|         "time": "2015-06-03 14:05:37", | ||||
|         "time": "2015-06-03T14:05:37+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2638,7 +2638,7 @@ | |||
|             "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for default/recommended ExtensionManager implementations", | ||||
|             "zendframework/zend-validator": "Zend\\Validator component" | ||||
|         }, | ||||
|         "time": "2015-08-04 21:39:18", | ||||
|         "time": "2015-08-04T21:39:18+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2687,7 +2687,7 @@ | |||
|         "suggest": { | ||||
|             "symfony/css-selector": "" | ||||
|         }, | ||||
|         "time": "2015-10-11 09:39:48", | ||||
|         "time": "2015-10-11T09:39:48+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2735,7 +2735,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.9" | ||||
|         }, | ||||
|         "time": "2016-03-04 07:54:35", | ||||
|         "time": "2016-03-04T07:54:35+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2798,7 +2798,7 @@ | |||
|         "suggest": { | ||||
|             "symfony/process": "" | ||||
|         }, | ||||
|         "time": "2015-10-23 14:47:27", | ||||
|         "time": "2015-10-23T14:47:27+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2853,7 +2853,7 @@ | |||
|             "phpunit/phpunit": "^4.0", | ||||
|             "psr/log": "^1.0" | ||||
|         }, | ||||
|         "time": "2016-07-15 17:22:37", | ||||
|         "time": "2016-07-15T17:22:37+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2914,7 +2914,7 @@ | |||
|             "symfony/css-selector": "~2.1|~3.0", | ||||
|             "symfony/dom-crawler": "~2.1|~3.0" | ||||
|         }, | ||||
|         "time": "2015-11-05 12:58:44", | ||||
|         "time": "2015-11-05T12:58:44+00:00", | ||||
|         "type": "application", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -2971,7 +2971,7 @@ | |||
|             "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", | ||||
|             "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" | ||||
|         }, | ||||
|         "time": "2016-03-05 08:26:18", | ||||
|         "time": "2016-03-05T08:26:18+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3028,7 +3028,7 @@ | |||
|             "silex/silex": "~1.2", | ||||
|             "symfony/phpunit-bridge": "~2.7|~3.0" | ||||
|         }, | ||||
|         "time": "2016-03-05 08:59:47", | ||||
|         "time": "2016-03-05T08:59:47+00:00", | ||||
|         "type": "mink-driver", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3085,7 +3085,7 @@ | |||
|         "require-dev": { | ||||
|             "symfony/phpunit-bridge": "~2.7|~3.0" | ||||
|         }, | ||||
|         "time": "2016-03-05 09:04:22", | ||||
|         "time": "2016-03-05T09:04:22+00:00", | ||||
|         "type": "mink-driver", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3140,7 +3140,7 @@ | |||
|             "symfony/debug": "~2.7", | ||||
|             "symfony/phpunit-bridge": "~2.7" | ||||
|         }, | ||||
|         "time": "2016-01-25 21:22:18", | ||||
|         "time": "2016-01-25T21:22:18+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3206,7 +3206,7 @@ | |||
|             "symfony/phpunit-bridge": "~2.7", | ||||
|             "symfony/process": "~2.1" | ||||
|         }, | ||||
|         "time": "2016-01-18 09:21:03", | ||||
|         "time": "2016-01-18T09:21:03+00:00", | ||||
|         "type": "phantomjs-api", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3268,7 +3268,7 @@ | |||
|             "symfony/phpunit-bridge": "~2.7", | ||||
|             "symfony/process": "~2.3" | ||||
|         }, | ||||
|         "time": "2015-12-04 13:55:02", | ||||
|         "time": "2015-12-04T13:55:02+00:00", | ||||
|         "type": "mink-driver", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3324,7 +3324,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.5" | ||||
|         }, | ||||
|         "time": "2015-10-06 16:59:57", | ||||
|         "time": "2015-10-06T16:59:57+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3376,7 +3376,7 @@ | |||
|             "dflydev/markdown": "~1.0", | ||||
|             "erusev/parsedown": "~1.0" | ||||
|         }, | ||||
|         "time": "2015-02-03 12:10:50", | ||||
|         "time": "2015-02-03T12:10:50+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3424,7 +3424,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.2" | ||||
|         }, | ||||
|         "time": "2015-09-15 10:49:45", | ||||
|         "time": "2015-09-15T10:49:45+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3471,7 +3471,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.9" | ||||
|         }, | ||||
|         "time": "2016-03-04 07:54:35", | ||||
|         "time": "2016-03-04T07:54:35+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3519,7 +3519,7 @@ | |||
|             "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", | ||||
|             "shasum": "" | ||||
|         }, | ||||
|         "time": "2015-06-21 13:59:46", | ||||
|         "time": "2015-06-21T13:59:46+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -3565,7 +3565,7 @@ | |||
|         "suggest": { | ||||
|             "ext-uopz": "*" | ||||
|         }, | ||||
|         "time": "2014-10-06 09:23:50", | ||||
|         "time": "2014-10-06T09:23:50+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3615,7 +3615,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.4" | ||||
|         }, | ||||
|         "time": "2015-06-21 08:04:50", | ||||
|         "time": "2015-06-21T08:04:50+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3671,7 +3671,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.4" | ||||
|         }, | ||||
|         "time": "2015-06-21 07:55:53", | ||||
|         "time": "2015-06-21T07:55:53+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3738,7 +3738,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.4" | ||||
|         }, | ||||
|         "time": "2015-08-03 06:14:51", | ||||
|         "time": "2015-08-03T06:14:51+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3790,7 +3790,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.2" | ||||
|         }, | ||||
|         "time": "2015-02-22 15:13:53", | ||||
|         "time": "2015-02-22T15:13:53+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3846,7 +3846,7 @@ | |||
|         "require-dev": { | ||||
|             "phpunit/phpunit": "~4.4" | ||||
|         }, | ||||
|         "time": "2015-07-26 15:48:44", | ||||
|         "time": "2015-07-26T15:48:44+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -3907,7 +3907,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2015-06-21 13:50:34", | ||||
|         "time": "2015-06-21T13:50:34+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -3957,7 +3957,7 @@ | |||
|             "phpunit/phpunit": "~4.0", | ||||
|             "squizlabs/php_codesniffer": "~2.0" | ||||
|         }, | ||||
|         "time": "2015-06-14 21:17:01", | ||||
|         "time": "2015-06-14T21:17:01+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -4015,7 +4015,7 @@ | |||
|         "suggest": { | ||||
|             "ext-soap": "*" | ||||
|         }, | ||||
|         "time": "2015-10-02 06:51:40", | ||||
|         "time": "2015-10-02T06:51:40+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -4064,7 +4064,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2015-06-21 08:01:12", | ||||
|         "time": "2015-06-21T08:01:12+00:00", | ||||
|         "type": "library", | ||||
|         "installation-source": "dist", | ||||
|         "autoload": { | ||||
|  | @ -4107,7 +4107,7 @@ | |||
|         "require": { | ||||
|             "php": ">=5.3.3" | ||||
|         }, | ||||
|         "time": "2015-06-21 13:08:43", | ||||
|         "time": "2015-06-21T13:08:43+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -4170,7 +4170,7 @@ | |||
|             "ext-xdebug": ">=2.2.1", | ||||
|             "ext-xmlwriter": "*" | ||||
|         }, | ||||
|         "time": "2015-10-06 15:47:00", | ||||
|         "time": "2015-10-06T15:47:00+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -4225,7 +4225,7 @@ | |||
|         "require-dev": { | ||||
|             "phpspec/phpspec": "~2.0" | ||||
|         }, | ||||
|         "time": "2015-08-13 10:07:40", | ||||
|         "time": "2015-08-13T10:07:40+00:00", | ||||
|         "type": "library", | ||||
|         "extra": { | ||||
|             "branch-alias": { | ||||
|  | @ -4303,7 +4303,7 @@ | |||
|         "suggest": { | ||||
|             "phpunit/php-invoker": "~1.1" | ||||
|         }, | ||||
|         "time": "2016-07-21 06:48:14", | ||||
|         "time": "2016-07-21T06:48:14+00:00", | ||||
|         "bin": [ | ||||
|             "phpunit" | ||||
|         ], | ||||
|  |  | |||
		Reference in a new issue
	
	 Pantheon Automation
						Pantheon Automation