diff -u b/core/modules/breakpoint/breakpoint.module b/core/modules/breakpoint/breakpoint.module --- b/core/modules/breakpoint/breakpoint.module +++ b/core/modules/breakpoint/breakpoint.module @@ -33,30 +33,8 @@ $themes = list_themes(); foreach ($theme_list as $theme_key) { if ($themes[$theme_key]->status) { - $theme_breakpoints = breakpoint_get_theme_breakpoint_list($theme_key); - if (!empty($theme_breakpoints)) { - if ($breakpoint_group = _breakpoint_import_breakpoints($themes[$theme_key]->info['name'], $theme_key, Breakpoint::SOURCE_TYPE_THEME, $theme_breakpoints)) { - $breakpoint_group->save(); - $uri = $breakpoint_group->uri(); - if ($uri) { - $uri_options = $uri; - unset($uri_options['path']); - $uri = $uri['path']; - } - $message = t('The breakpoints from theme %theme are imported.', array( - '%theme' => check_plain($themes[$theme_key]->info['name']), - )); - if (module_exists('breakpoint_ui') && $uri) { - $message .= '

' . l(t('A new breakpoint group is created for theme %theme.', array( - '%theme' => check_plain($themes[$theme_key]->info['name']), - )), $uri, $uri_options); - } - drupal_set_message($message, 'status'); - } - } - - // Import custom groups. - _breakpoint_import_breakpoint_groups($theme_key, Breakpoint::SOURCE_TYPE_THEME); + $media_queries = breakpoint_get_theme_media_queries($theme_key); + _breakpoint_import_media_queries($theme_key, $themes[$theme_key]->info['name'], Breakpoint::SOURCE_TYPE_THEME, $media_queries); } } } @@ -83,30 +61,8 @@ */ function breakpoint_modules_enabled($modules) { foreach ($modules as $module) { - $module_breakpoints = breakpoint_get_module_breakpoint_list($module); - if (!empty($module_breakpoints)) { - if ($breakpoint_group = _breakpoint_import_breakpoints($module, $module, Breakpoint::SOURCE_TYPE_MODULE, $module_breakpoints)) { - $breakpoint_group->save(); - $uri = $breakpoint_group->uri(); - if ($uri) { - $uri_options = $uri; - unset($uri_options['path']); - $uri = $uri['path']; - } - $message = t('The breakpoints from module %module are imported.', array( - '%module' => $module, - )); - if (module_exists('breakpoint_ui') && $uri) { - $message .= '

' . l(t('A new breakpoint group is created for module %module.', array( - '%module' => $module, - )), $uri, $uri_options); - } - drupal_set_message($message, 'status'); - } - } - - // Import custom groups. - _breakpoint_import_breakpoint_groups($module, Breakpoint::SOURCE_TYPE_MODULE); + $media_queries = breakpoint_get_module_media_queries($module); + _breakpoint_import_media_queries($module, $module, Breakpoint::SOURCE_TYPE_MODULE, $media_queries); } } @@ -123,64 +79,41 @@ } /** - * Import breakpoints from theme or module. + * Import media queries from a theme or module and create a default group. * - * @param string $label - * Name of the breakpoint group. * @param string $id - * Id of the breakpoint group. + * Name of the breakpoint group. + * @param string $label + * Human readable name of the breakpoint group. * @param string $sourceType * Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE. * @param array $media_queries * Array of media queries keyed by id. - * - * @return Drupal\breakpoint\BreakpointGroup|false - * Returns the new breakpoint group if one is created. */ -function _breakpoint_import_breakpoints($label, $id, $source_type, $media_queries) { +function _breakpoint_import_media_queries($id, $label, $source_type, $media_queries) { if (!empty($media_queries)) { - $weight = 0; - // Use the existing breakpoint group if it exists. - $breakpoint_group = entity_load('breakpoint_group', $source_type . '.' . $id); - if (!$breakpoint_group) { - // Build a new breakpoint group. - $breakpoint_group = new BreakpointGroup(); - $breakpoint_group->id = $id; - $breakpoint_group->label = $label; - $breakpoint_group->source = $id; - $breakpoint_group->sourceType = $source_type; - } - else { - // Reset label. - $breakpoint_group->label = $label; - } - foreach ($media_queries as $name => $media_query) { - // Use the existing breakpoint if it exists. - $breakpoint = entity_load('breakpoint', $source_type . '.' . $id . '.' . $name); - if (!$breakpoint) { - // Build a new breakpoint. - $breakpoint = new Breakpoint; - $breakpoint->name = $name; - $breakpoint->label = drupal_ucfirst($name); - $breakpoint->mediaQuery = $media_query; - $breakpoint->source = $id; - $breakpoint->sourceType = $source_type; - $breakpoint->status = TRUE; - $breakpoint->weight = $weight++; - $breakpoint->save(); + if ($breakpoint_group = BreakpointGroup::ImportMediaQueries($id, $label, $source_type, $media_queries)) { + $breakpoint_group->save(); + $uri = $breakpoint_group->uri(); + if ($uri) { + $uri_options = $uri; + unset($uri_options['path']); + $uri = $uri['path']; } - else { - // Reset name, label, weight and media query. - $breakpoint->name = $name; - $breakpoint->label = drupal_ucfirst($name); - $breakpoint->mediaQuery = $media_query; - $breakpoint->weight = $weight++; + $message = t('The breakpoints from %label are imported.', array( + '%label' => $label, + )); + if (module_exists('breakpoint_ui') && $uri) { + $message .= '

' . l(t('A new breakpoint group is created for %label.', array( + '%label' => $label, + )), $uri, $uri_options); } - $breakpoint_group->breakpoints[$breakpoint->id()] = $breakpoint; + drupal_set_message($message, 'status'); } - return $breakpoint_group; } - return FALSE; + + // Import custom groups. + _breakpoint_import_breakpoint_groups($id, $source_type); } /** @@ -193,67 +126,14 @@ * * @return boolean */ -function _breakpoint_import_breakpoint_groups($group_id, $source_type) { - $breakpoint_groups = config($group_id . '.breakpoint_groups'); +function _breakpoint_import_breakpoint_groups($source, $source_type) { + $breakpoint_groups = config($source . '.breakpoint_groups'); if ($breakpoint_groups) { foreach ($breakpoint_groups->get() as $id => $data) { - // Breakpoints is mandatory. + // Breakpoints is mandatory, extra check since this is coming from config. if (isset($data['breakpoints']) && !empty($data['breakpoints'])) { - // Use the existing breakpoint group if it exists. - $breakpoint_group = entity_load('breakpoint_group', $source_type . '.' . $id); - if (!$breakpoint_group) { - $breakpoint_group = new BreakpointGroup(); - $breakpoint_group->sourceType = $source_type; - $breakpoint_group->source = $group_id; - $breakpoint_group->id = $id; - if (isset($data['label']) && !empty($data['label'])) { - $breakpoint_group->label = $data['label']; - } - else { - $breakpoint_group->label = drupal_ucfirst($data['label']); - } - } - else { - // Reset label. - if (isset($data['label']) && !empty($data['label'])) { - $breakpoint_group->label = $data['label']; - } - else { - $breakpoint_group->label = drupal_ucfirst($data['label']); - } - } - foreach ($data['breakpoints'] as $breakpoint_id => $multipliers) { - // Check if breakpoint exists, assume short name. - $breakpoint = entity_load('breakpoint', $source_type . '.' . $group_id . '.' . $breakpoint_id); - // If the breakpoint doesn't exist, try using the full name. - if (!$breakpoint) { - $breakpoint = entity_load('breakpoint', $breakpoint_id); - } - if ($breakpoint) { - // Check if the multipliers are set, if not set them now. - if (is_array($multipliers) && !empty($multipliers)) { - // Check settings first. - $settings = breakpoint_settings(); - $defined_multipliers = $settings->multipliers; - $new_multipliers = array_diff($multipliers, $defined_multipliers); - if (!empty($new_multipliers)) { - $defined_multipliers = array_merge($defined_multipliers, $new_multipliers); - breakpoint_settings_save_multipliers($defined_multipliers); - } - - // Check breakpoint multipliers. - $multipliers = drupal_map_assoc(array_values($multipliers)); - $new_multipliers = array_diff($multipliers, $breakpoint->multipliers); - if (!empty($new_multipliers)) { - $breakpoint->multipliers += $new_multipliers; - $breakpoint->save(); - } - } - - // Add breakpoint to group. - $breakpoint_group->breakpoints[$breakpoint->id()] = $breakpoint; - $breakpoint_group->save(); - } + if ($breakpoint_group = BreakpointGroup::ImportBreakpointGroup($source, $source_type, $id, isset($data['label']) ? $data['label'] : drupal_ucfirst($data[$id]), $data['breakpoints'])) { + $breakpoint_group->save(); } } } @@ -262,6 +142,8 @@ /** * Remove breakpoints from all disabled themes or uninstalled modules. + * The source type has to match the original source type, otherwise the group + * will not be deleted. * * @param array $ids * Id's of the breakpoint group. @@ -273,18 +155,20 @@ $breakpoint_groups = entity_load_multiple('breakpoint_group', $ids); foreach ($breakpoint_groups as $breakpoint_group) { if ($breakpoint_group->sourceType == $source_type) { - // delete the default group. + // Delete the automatically created breakpoint group. $breakpoint_group->delete(); - // delete all breakpoints defined by this theme/module. + // Get all breakpoints defined by this theme/module. $names = drupal_container()->get('config.storage')->listAll('breakpoint.breakpoint.' . $source_type . '.' . $breakpoint_group->id() . '.'); $entity_info = entity_get_info('breakpoint'); + // Remove the breakpoint.breakpoint part of the names, before loading. foreach ($names as &$name) { $name = drupal_substr($name, drupal_strlen($entity_info['config prefix']) + 1); } $breakpoints = entity_load_multiple('breakpoint', $names); + // Make sure we only delete breakpoints defined by this theme/module. foreach ($breakpoints as $breakpoint) { if ($breakpoint->sourceType == $source_type && $breakpoint->source = $breakpoint_group->id) { $breakpoint->delete(); @@ -292,10 +176,11 @@ } } } - // Deletet groups defined by a module/theme even if that module/theme didn't + + // Delete groups defined by a module/theme even if that module/theme didn't // define any breakpoints. foreach ($ids as $id) { - // delete all breakpoint groups defined by the theme or module. + // Delete all breakpoint groups defined by the theme or module. _breakpoint_delete_breakpoint_groups($id, $source_type); } } @@ -319,32 +204,6 @@ } /** - * Load general settings. - * - * @return array - * array containing general breakpoint settings. - */ -function breakpoint_settings() { - $config = config('breakpoint'); - if ($config->isNew()) { - return FALSE; - } - return (object)$config->get(); -} - -/** - * Save multipliers to settings. - * - * @param array $multipliers - * array containing multipliers. - */ -function breakpoint_settings_save_multipliers($multipliers) { - $config = config('breakpoint'); - $config->set('multipliers', $multipliers); - $config->save(); -} - -/** * Reload breakpoint groups as they were defined in the theme. * * @param string $theme_key @@ -360,9 +219,9 @@ $themes = list_themes(); if (isset($themes[$theme_key]) && $themes[$theme_key]->status) { - $theme_breakpoints = breakpoint_get_theme_breakpoint_list($theme_key); + $theme_breakpoints = breakpoint_get_theme_media_queries($theme_key); if (!empty($theme_breakpoints)) { - return _breakpoint_import_breakpoints($themes[$theme_key]->info['name'], $theme_key, Breakpoint::SOURCE_TYPE_THEME, $theme_breakpoints); + return BreakpointGroup::ImportMediaQueries($theme_key, $themes[$theme_key]->info['name'], Breakpoint::SOURCE_TYPE_THEME, $theme_breakpoints); } } return FALSE; @@ -377,7 +236,7 @@ * @return array * An array of breakpoints in the form $breakpoint['name'] = 'media query'. */ -function breakpoint_get_theme_breakpoint_list($theme_key) { +function breakpoint_get_theme_media_queries($theme_key) { $themes = list_themes(); if (!isset($themes[$theme_key])) { return array(); @@ -399,7 +258,7 @@ * @return array * An array of breakpoints in the form $breakpoint['name'] = 'media query'. */ -function breakpoint_get_module_breakpoint_list($module) { +function breakpoint_get_module_media_queries($module) { if (!module_exists($module)) { return array(); } @@ -485,7 +344,7 @@ * @return array * An array containing breakpoint group labels indexed by their ids. */ -function breakpoint_group_select_options() { +function breakpoint_group_labels() { $options = array(); $breakpoint_groups = entity_load_multiple('breakpoint_group'); foreach ($breakpoint_groups as $breakpoint_group) { @@ -501,7 +360,7 @@ * @return array * An array containing breakpoints indexed by their ids. */ -function breakpoint_select_options() { +function breakpoint_labels() { $options = array(); $breakpoints = entity_load_multiple('breakpoint'); foreach ($breakpoints as $breakpoint) { diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php @@ -8,8 +8,11 @@ namespace Drupal\breakpoint; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Component\Uuid\Uuid; -use Exception; +use Drupal\breakpoint\InvalidBreakpointException; +use Drupal\breakpoint\InvalidBreakpointNameException; +use Drupal\breakpoint\InvalidBreakpointSourceException; +use Drupal\breakpoint\InvalidBreakpointSourceTypeException; +use Drupal\breakpoint\InvalidBreakpointMediaQueryException; /** * Defines the Breakpoint entity. @@ -60,6 +63,8 @@ /** * The original media query. + * This is tracked separately, because a user can override a single breakpoint + * and reloading the media query from the theme/module is expensive. * * @var string */ @@ -116,10 +121,6 @@ */ public function __construct(array $values = array(), $entity_type = 'breakpoint') { parent::__construct($values, $entity_type); - if (!isset($this->uuid)) { - $uuid = new Uuid(); - $this->uuid = $uuid->generate(); - } } /** @@ -127,20 +128,20 @@ */ public function save() { if (empty($this->id)) { - $this->id = $this->buildConfigName(); + $this->id = $this->getConfigName(); } if (empty($this->label)) { $this->label = drupal_ucfirst($this->name); } - // Check the media query. + // Check if everything is valid. if (!$this->isValid()) { - throw new Exception(t('Invalid media query detected.')); + throw new InvalidBreakpointException('Invalid data detected.'); } // Remove ununsed multipliers. $this->multipliers = array_filter($this->multipliers); - // Add '1x' multiplier. + // Always add '1x' multiplier. if (!array_key_exists('1x', $this->multipliers)) { $this->multipliers = array('1x' => '1x') + $this->multipliers; } @@ -151,44 +152,7 @@ * Get config name. */ public function getConfigName() { - return $this->sourceType - . '.' . $this->source - . '.' . $this->name; - } - - /** - * Build config name. - */ - protected function buildConfigName() { - // Check for illegal values in breakpoint source type. - if (!in_array($this->sourceType, array( - Breakpoint::SOURCE_TYPE_CUSTOM, - Breakpoint::SOURCE_TYPE_MODULE, - Breakpoint::SOURCE_TYPE_THEME) - )) { - throw new Exception( - t( - "Expected one of '@custom', '@module' or '@theme' for breakpoint sourceType property but got '@sourcetype'.", - array( - '@custom' => Breakpoint::SOURCE_TYPE_CUSTOM, - '@module' => Breakpoint::SOURCE_TYPE_MODULE, - '@theme' => Breakpoint::SOURCE_TYPE_THEME, - '@sourcetype' => $this->sourceType, - ) - ) - ); - } - // Check for illegal characters in breakpoint source. - if (preg_match('/[^a-z_]+/', $this->source)) { - throw new Exception(t("Invalid value '@source' for breakpoint source property. Breakpoint source property can only contain lowercase letters and underscores.", array('@source' => $this->source))); - } - // Check for illegal characters in breakpoint names. - if (preg_match('/[^0-9a-z_\-]/', $this->name)) { - throw new Exception(t("Invalid value '@name' for breakpoint name property. Breakpoint name property can only contain lowercase alphanumeric characters, underscores (_), and hyphens (-).", array('@name' => $this->name))); - } - return $this->sourceType - . '.' . $this->source - . '.' . $this->name; + return $this->sourceType . '.' . $this->source . '.' . $this->name; } /** @@ -222,9 +186,9 @@ * */ public function duplicate() { - $duplicate = new Breakpoint; - $duplicate->mediaQuery = $this->mediaQuery; - return $duplicate; + return entity_create('breakpoint', array( + 'mediaQuery' => $this->mediaQuery, + )); } /** @@ -252,11 +216,29 @@ } /** - * Check if the mediaQuery is valid. + * Check if the breakpoint is valid. * * @see isValidMediaQuery() */ public function isValid() { + // Check for illegal values in breakpoint source type. + if (!in_array($this->sourceType, array( + Breakpoint::SOURCE_TYPE_CUSTOM, + Breakpoint::SOURCE_TYPE_MODULE, + Breakpoint::SOURCE_TYPE_THEME) + )) { + throw new InvalidBreakpointSourceTypeException(format_string('Invalid source type @source_type', array( + '@source_type' => $this->sourceType, + ))); + } + // Check for illegal characters in breakpoint source. + if (preg_match('/[^a-z_]+/', $this->source)) { + throw new InvalidBreakpointSourceException(format_string("Invalid value '@source' for breakpoint source property. Breakpoint source property can only contain lowercase letters and underscores.", array('@source' => $this->source))); + } + // Check for illegal characters in breakpoint names. + if (preg_match('/[^0-9a-z_\-]/', $this->name)) { + throw new InvalidBreakpointNameException(format_string("Invalid value '@name' for breakpoint name property. Breakpoint name property can only contain lowercase alphanumeric characters, underscores (_), and hyphens (-).", array('@name' => $this->name))); + } return $this::isValidMediaQuery($this->mediaQuery); } @@ -317,19 +299,19 @@ // Single expression. if (isset($matches[1]) && !isset($matches[2])) { if (!array_key_exists($matches[1], $media_features)) { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Invalid media feature detected.'); } } // Full expression. elseif (isset($matches[3]) && !isset($matches[4])) { $value = trim($matches[3]); if (!array_key_exists($matches[1], $media_features)) { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Invalid media feature detected.'); } if (is_array($media_features[$matches[1]])) { // Check if value is allowed. if (!array_key_exists($value, $media_features[$matches[1]])) { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Value is not allowed.'); } } else { @@ -339,15 +321,15 @@ if (preg_match('/^(\-)?(\d+)?((?:|em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|dpi|dpcm))$/i', trim($value), $length_matches)) { // Only -0 is allowed. if ($length_matches[1] === '-' && $length_matches[2] !== '0') { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Invalid length detected.'); } // If there's a unit, a number is needed as well. if ($length_matches[2] === '' && $length_matches[3] !== '') { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Unit found, value is missing.'); } } else { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Invalid unit detected.'); } break; } @@ -359,16 +341,16 @@ elseif (preg_match('/^((?:only|not)?\s?)([\w\-]+)$/i', trim($query_part), $matches)) { if ($media_type_found) { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Only one media type is allowed.'); } $media_type_found = TRUE; } else { - return FALSE; + throw new InvalidBreakpointMediaQueryException('Invalid media query detected.'); } } } return TRUE; } - return FALSE; + throw new InvalidBreakpointMediaQueryException('Media query is empty.'); } } diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroup.php b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroup.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroup.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointGroup.php @@ -8,7 +8,8 @@ namespace Drupal\breakpoint; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Component\Uuid\Uuid; +use Drupal\breakpoint\InvalidBreakpointSourceException; +use Drupal\breakpoint\InvalidBreakpointSourceTypeException; /** * Defines the BreakpointGroup entity. @@ -78,11 +79,6 @@ */ public function __construct(array $values = array(), $entity_type = 'breakpoint_group') { parent::__construct($values, $entity_type); - // Assign a new UUID if there is none yet. - if (!isset($this->uuid)) { - $uuid = new Uuid(); - $this->uuid = $uuid->generate(); - } $this->loadAllBreakpoints(); } @@ -90,6 +86,10 @@ * Overrides Drupal\Core\Entity::save(). */ public function save() { + // Check if everything is valid. + if (!$this->isValid()) { + throw new Exception('Invalid data detected.'); + } // Only save the keys, but return the full objects. $this->breakpoints = array_keys($this->breakpoints); parent::save(); @@ -97,6 +97,27 @@ } /** + * Check if the breakpoint group is valid. + */ + public function isValid() { + // Check for illegal values in breakpoint group source type. + if (!in_array($this->sourceType, array( + Breakpoint::SOURCE_TYPE_CUSTOM, + Breakpoint::SOURCE_TYPE_MODULE, + Breakpoint::SOURCE_TYPE_THEME) + )) { + throw new InvalidBreakpointSourceTypeException(format_string('Invalid source type @source_type', array( + '@source_type' => $this->sourceType, + ))); + } + // Check for illegal characters in breakpoint source. + if (preg_match('/[^a-z_]+/', $this->source)) { + throw new InvalidBreakpointSourceException(format_string("Invalid value '@source' for breakpoint source property. Breakpoint source property can only contain lowercase letters and underscores.", array('@source' => $this->source))); + } + return TRUE; + } + + /** * Override a breakpoint group. */ public function override() { @@ -143,9 +164,9 @@ * */ public function duplicate() { - $duplicate = new BreakpointGroup; - $duplicate->breakpoints = $this->breakpoints; - return $duplicate; + return entity_create('breakpoint_group', array( + 'breakpoints' => $this->breakpoints, + )); } /** @@ -164,6 +185,127 @@ } /** + * Add a breakpoint using a name and a media query. + * + * @param string $name + * The name of the breakpoint. + * @param string $media_query + * Media query. + */ + public function addBreakpointFromMediaQuery($name, $media_query) { + // Use the existing breakpoint if it exists. + $breakpoint = entity_load('breakpoint', $this->sourceType . '.' . $this->id . '.' . $name); + if (!$breakpoint) { + // Build a new breakpoint. + $breakpoint = entity_create('breakpoint', array( + 'name' => $name, + 'label' => drupal_ucfirst($name), + 'mediaQuery' => $media_query, + 'source' => $this->id, + 'sourceType' => $this->sourceType, + 'weight' => count($this->breakpoints), + )); + $breakpoint->save(); + } + else { + // Reset name, label, weight and media query. + $breakpoint->name = $name; + $breakpoint->label = drupal_ucfirst($name); + $breakpoint->mediaQuery = $media_query; + $breakpoint->weight = count($this->breakpoints); + } + $this->breakpoints[$breakpoint->id()] = $breakpoint; + } + + /** + * Load breakpoints from a theme/module and build a default group. + * + * @param string $id + * Name of the breakpoint group. + * @param string $label + * Human readable name of the breakpoint group. + * @param string $sourceType + * Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE. + * @param array $media_queries + * Array of media queries keyed by id. + * + * @return \Drupal\breakpoint\BreakpointGroup|false + * Return the new breakpoint group containing all breakpoints. + */ + public static function ImportMediaQueries($id, $label, $source_type, $media_queries) { + $breakpoint_group = entity_load('breakpoint_group', $source_type . '.' . $id); + /* @var $breakpoint_group \Drupal\breakpoint\BreakpointGroup */ + if (!$breakpoint_group) { + // Build a new breakpoint group. + $breakpoint_group = entity_create('breakpoint_group', array( + 'id' => $id, + 'label' => $label, + 'source' => $id, + 'sourceType' => $source_type, + )); + } + else { + // Reset label. + $breakpoint_group->label = $label; + } + + foreach ($media_queries as $name => $media_query) { + $breakpoint_group->addBreakpointFromMediaQuery($name, $media_query); + } + return $breakpoint_group; + } + + /** + * Import breakpoint groups from theme or module. + * + * @param string $source + * Source of the breakpoint group, theme_key or module name. + * @param string $sourceType + * Either Breakpoint::SOURCE_TYPE_THEME or Breakpoint::SOURCE_TYPE_MODULE. + * @param string $name + * Name of the breakpoint group. + * @param string $label + * Human readable name of the breakpoint group. + * @param array $breakpoints + * Array of breakpoints, using either the short name or the full name. + * + * @return \Drupal\breakpoint\BreakpointGroup|false + * Return the new breakpoint group containing all breakpoints. + */ + public static function ImportBreakpointGroup($source, $source_type, $name, $label, $breakpoints) { + // Use the existing breakpoint group if it exists. + $breakpoint_group = entity_load('breakpoint_group', $source_type . '.' . $name); + /* @var $breakpoint_group \Drupal\breakpoint\BreakpointGroup */ + if (!$breakpoint_group) { + $breakpoint_group = entity_create('breakpoint_group', array( + 'id' => $name, + 'label' => !empty($label) ? $label : $name, + 'source' => $source, + 'sourceType' => $source_type, + )); + } + else { + // Reset label. + $breakpoint_group->label = !empty($label) ? $label : $name; + } + + // Add breakpoints to the group. + foreach ($breakpoints as $breakpoint_name) { + // Check if breakpoint exists, assume short name. + $breakpoint = entity_load('breakpoint', $source_type . '.' . $source . '.' . $breakpoint_name); + // If the breakpoint doesn't exist, try using the full name. + if (!$breakpoint) { + $breakpoint = entity_load('breakpoint', $breakpoint_name); + } + if ($breakpoint) { + // Add breakpoint to group. + $breakpoint_group->breakpoints[$breakpoint->id()] = $breakpoint; + } + } + return $breakpoint_group; + } + + /** * Load all breakpoints, remove non-existing ones. */ protected function loadAllBreakpoints() { reverted: --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointApiTest.php +++ /dev/null @@ -1,90 +0,0 @@ - 'Breakpoint general API functions', - 'description' => 'Test general API functions of the breakpoint module.', - 'group' => 'Breakpoint', - ); - } - - /** - * Test Breakpoint::buildConfigName(). - */ - public function testConfigName() { - $breakpoint = new Breakpoint( - array( - 'label' => drupal_strtolower($this->randomName()), - 'source' => 'custom_module', - // Try an invalid sourceType. - 'sourceType' => 'oops', - ) - ); - - try { - $breakpoint->save(); - } - catch (Exception $e) { - $exception = TRUE; - } - $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid sourceType is entered.')); - $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_config_name: No id is set when an invalid sourceType is entered.')); - - // Try an invalid source. - $breakpoint->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM; - $breakpoint->source = 'custom*_module source'; - $exception = FALSE; - try { - $breakpoint->save(); - } - catch (Exception $e) { - $exception = TRUE; - } - $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid source is entered.')); - $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_config_name: No id is set when an invalid sourceType is entered.')); - - // Try an invalid name (make sure there is at least once capital letter). - $breakpoint->source = 'custom_module'; - $breakpoint->name = drupal_ucfirst($this->randomName()); - $exception = FALSE; - try { - $breakpoint->save(); - } - catch (Exception $e) { - $exception = TRUE; - } - $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid name is entered.')); - $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_config_name: No id is set when an invalid sourceType is entered.')); - - // Try a valid breakpoint. - $breakpoint->name = drupal_strtolower($this->randomName()); - $breakpoint->mediaQuery = 'all'; - $exception = FALSE; - try { - $breakpoint->save(); - } - catch (Exception $e) { - $exception = TRUE; - } - $this->assertFalse($exception, t('breakpoint_config_name: No exception is thrown when a valid breakpoint is passed.')); - $this->assertEqual($breakpoint->id(), Breakpoint::SOURCE_TYPE_CUSTOM . '.custom_module.' . $breakpoint->name, t('breakpoint_config_name: A id is set when a valid breakpoint is passed.')); - } -} diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php @@ -30,12 +30,10 @@ */ public function testBreakpointCrud() { // Add a breakpoint with minimum data only. - $values = array( + $breakpoint = entity_create('breakpoint', array( 'label' => drupal_strtolower($this->randomName()), 'mediaQuery' => '(min-width: 600px)', - ); - - $breakpoint = new Breakpoint($values); + )); $breakpoint->save(); $this->verifyBreakpoint($breakpoint); diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointGroupCrudTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointGroupCrudTest.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointGroupCrudTest.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointGroupCrudTest.php @@ -34,23 +34,21 @@ $breakpoints = array(); for ($i = 0; $i <= 3; $i++) { $width = ($i + 1) * 200; - $values = array( + $breakpoint = entity_create('breakpoint', array( 'name' => drupal_strtolower($this->randomName()), 'weight' => $i, 'mediaQuery' => "(min-width: {$width}px)", - ); - $breakpoint = new Breakpoint($values); + )); $breakpoint->save(); $breakpoints[$breakpoint->id()] = $breakpoint; } // Add a breakpoint group with minimum data only. $label = $this->randomName(); - $values = array( + + $group = entity_create('breakpoint_group', array( 'label' => $label, 'id' => drupal_strtolower($label), - ); - - $group = new BreakpointGroup($values); + )); $group->save(); $this->verifyBreakpointGroup($group); @@ -60,8 +58,9 @@ $this->verifyBreakpointGroup($group); // Duplicate the breakpoint group. - $new_set = new BreakpointGroup(); - $new_set->breakpoints = $group->breakpoints; + $new_set = entity_create('breakpoint_group', array( + 'breakpoints' => $group->breakpoints, + )); $duplicated_set = $group->duplicate(); $this->verifyBreakpointGroup($duplicated_set, $new_set); diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php @@ -8,7 +8,7 @@ use Drupal\simpletest\UnitTestBase; use Drupal\breakpoint\Breakpoint; -use Exception; +use Drupal\breakpoint\InvalidBreakpointMediaQueryException; /** * Tests for media queries in a breakpoint. @@ -63,7 +63,7 @@ try { $this->assertTrue(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is valid.'); } - catch (Exception $e) { + catch (InvalidBreakpointMediaQueryException $e) { $this->assertTrue(FALSE, $media_query . ' is valid.'); } } @@ -74,6 +74,7 @@ */ public function testInvalidMediaQueries() { $media_queries = array( + '', 'not (orientation)', 'only (orientation)', 'all and not all', @@ -117,7 +118,7 @@ try { $this->assertFalse(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is not valid.'); } - catch (Exception $e) { + catch (InvalidBreakpointMediaQueryException $e) { $this->assertTrue(TRUE, $media_query . ' is not valid.'); } } diff -u b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php --- b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php @@ -27,7 +27,7 @@ */ public static function getInfo() { return array( - 'name' => 'Breakpoint Theme functionality', + 'name' => 'Breakpoint theme functionality', 'description' => 'Thoroughly test the breakpoints provided by a theme.', 'group' => 'Breakpoint', ); @@ -46,17 +46,18 @@ */ public function testThemeBreakpoints() { // Verify the breakpoint group for breakpoint_test_theme was created. - $breakpoint_group_obj = new BreakpointGroup(); - $breakpoint_group_obj->label = 'Breakpoint test theme'; - $breakpoint_group_obj->id = 'breakpoint_test_theme'; - $breakpoint_group_obj->sourceType = Breakpoint::SOURCE_TYPE_THEME; + $breakpoint_group_obj = entity_create('breakpoint_group', array( + 'label' => 'Breakpoint test theme', + 'id' => 'breakpoint_test_theme', + 'sourceType' => Breakpoint::SOURCE_TYPE_THEME, + 'overridden' => FALSE, + )); $breakpoint_group_obj->breakpoints = array( 'theme.breakpoint_test_theme.mobile' => array(), 'theme.breakpoint_test_theme.narrow' => array(), 'theme.breakpoint_test_theme.wide' => array(), 'theme.breakpoint_test_theme.tv' => array(), ); - $breakpoint_group_obj->overridden = 0; // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); @@ -93,17 +94,18 @@ */ public function testThemeBreakpointGroup() { // Verify the breakpoint group 'test' was created by breakpoint_test_theme. - $breakpoint_group_obj = new BreakpointGroup(); - $breakpoint_group_obj->label = 'Test'; - $breakpoint_group_obj->id = 'test'; - $breakpoint_group_obj->sourceType = Breakpoint::SOURCE_TYPE_THEME; - $breakpoint_group_obj->source = 'breakpoint_test_theme'; + $breakpoint_group_obj = entity_create('breakpoint_group', array( + 'label' => 'Test', + 'id' => 'test', + 'sourceType' => Breakpoint::SOURCE_TYPE_THEME, + 'source' => 'breakpoint_test_theme', + 'overridden' => FALSE, + )); $breakpoint_group_obj->breakpoints = array( 'theme.breakpoint_test_theme.mobile' => array('1.5x', '2.x'), 'theme.breakpoint_test_theme.narrow' => array(), 'theme.breakpoint_test_theme.wide' => array(), ); - $breakpoint_group_obj->overridden = 0; // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); @@ -123,32 +125,22 @@ // Verify the breakpoint group 'module_test' was created by // breakpoint_theme_test module. - $breakpoint_group_obj = new BreakpointGroup(); - $breakpoint_group_obj->label = 'Test Module'; - $breakpoint_group_obj->id = 'module_test'; - $breakpoint_group_obj->sourceType = Breakpoint::SOURCE_TYPE_MODULE; - $breakpoint_group_obj->source = 'breakpoint_theme_test'; + $breakpoint_group_obj = entity_create('breakpoint_group', array( + 'label' => 'Test Module', + 'id' => 'module_test', + 'sourceType' => Breakpoint::SOURCE_TYPE_MODULE, + 'source' => 'breakpoint_theme_test', + 'overridden' => FALSE, + )); $breakpoint_group_obj->breakpoints = array( 'theme.breakpoint_test_theme.mobile' => array(), - 'theme.breakpoint_test_theme.narrow' => array('3.x', '4.x'), + 'theme.breakpoint_test_theme.narrow' => array(), 'theme.breakpoint_test_theme.wide' => array(), ); - $breakpoint_group_obj->overridden = 0; // Verify we can load this breakpoint defined by the theme. $this->verifyBreakpointGroup($breakpoint_group_obj); - // Check that the multipliers are added to the settings. - $settings = breakpoint_settings(); - $expected_settings = array( - 0 => '1x', - 1 => '1.5x', - 2 => '2x', - 3 => '3x', - 4 => '4x', - ); - $this->assertEqual($settings->multipliers, $expected_settings, 'Multipliers are added to settings.'); - // Disable the test theme and verify the breakpoint group still exists. theme_disable(array('breakpoint_test_theme')); $this->assertTrue(entity_load('breakpoint_group', 'module_test'), 'Breakpoint group still exists if theme is disabled.'); diff -u b/core/modules/breakpoint/tests/config/breakpoint_theme_test.breakpoint_groups.yml b/core/modules/breakpoint/tests/config/breakpoint_theme_test.breakpoint_groups.yml --- b/core/modules/breakpoint/tests/config/breakpoint_theme_test.breakpoint_groups.yml +++ b/core/modules/breakpoint/tests/config/breakpoint_theme_test.breakpoint_groups.yml @@ -4,3 +4,3 @@ - theme.breakpoint_test_theme.mobile: [] - theme.breakpoint_test_theme.narrow: ['3x', '4x'] - theme.breakpoint_test_theme.wide: + - theme.breakpoint_test_theme.mobile + - theme.breakpoint_test_theme.narrow + - theme.breakpoint_test_theme.wide diff -u b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info --- b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info +++ b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info @@ -5 +5 @@ -hidden = FALSE +hidden = TRUE diff -u b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoint_groups.yml b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoint_groups.yml --- b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoint_groups.yml +++ b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoint_groups.yml @@ -4,3 +4,3 @@ - mobile: ['1.5x', '2x'] - narrow: - wide: + - mobile + - narrow + - wide only in patch2: unchanged: --- /dev/null +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/InvalidBreakpointException.php @@ -0,0 +1,15 @@ + 'Breakpoint general API functions', + 'description' => 'Test general API functions of the breakpoint module.', + 'group' => 'Breakpoint', + ); + } + + /** + * Test Breakpoint::buildConfigName(). + */ + public function testConfigName() { + // Try an invalid sourceType. + $breakpoint = entity_create('breakpoint', array( + 'label' => drupal_strtolower($this->randomName()), + 'source' => 'custom_module', + 'sourceType' => 'oops', + )); + + $exception = FALSE; + try { + $breakpoint->save(); + } + catch (InvalidBreakpointSourceTypeException $e) { + $exception = TRUE; + } + $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid sourceType is entered.')); + + // Try an invalid source. + $breakpoint->id = ''; + $breakpoint->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM; + $breakpoint->source = 'custom*_module source'; + + $exception = FALSE; + try { + $breakpoint->save(); + } + catch (InvalidBreakpointSourceException $e) { + $exception = TRUE; + } + $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid source is entered.')); + + // Try an invalid name (make sure there is at least once capital letter). + $breakpoint->id = ''; + $breakpoint->source = 'custom_module'; + $breakpoint->name = drupal_ucfirst($this->randomName()); + + $exception = FALSE; + try { + $breakpoint->save(); + } + catch (InvalidBreakpointNameException $e) { + $exception = TRUE; + } + $this->assertTrue($exception, t('breakpoint_config_name: An exception is thrown when an invalid name is entered.')); + + // Try a valid breakpoint. + $breakpoint->id = ''; + $breakpoint->name = drupal_strtolower($this->randomName()); + $breakpoint->mediaQuery = 'all'; + + $exception = FALSE; + try { + $breakpoint->save(); + } + catch (\Exception $e) { + $exception = TRUE; + } + $this->assertFalse($exception, t('breakpoint_config_name: No exception is thrown when a valid breakpoint is passed.')); + $this->assertEqual($breakpoint->id(), Breakpoint::SOURCE_TYPE_CUSTOM . '.custom_module.' . $breakpoint->name, t('breakpoint_config_name: A id is set when a valid breakpoint is passed.')); + } +} only in patch2: unchanged: --- /dev/null +++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointGroupAPITest.php @@ -0,0 +1,79 @@ + 'Breakpoint group general API functions', + 'description' => 'Test general API functions of the breakpoint module.', + 'group' => 'Breakpoint', + ); + } + + /** + * Test Breakpoint::buildConfigName(). + */ + public function testConfigName() { + // Try an invalid sourceType. + $breakpoint_group = entity_create('breakpoint_group', array( + 'label' => drupal_strtolower($this->randomName()), + 'source' => 'custom_module', + 'sourceType' => 'oops', + )); + + $exception = FALSE; + try { + $breakpoint_group->save(); + } + catch (InvalidBreakpointSourceTypeException $e) { + $exception = TRUE; + } + $this->assertTrue($exception, t('An exception is thrown when an invalid sourceType is entered.')); + + // Try an invalid source. + $breakpoint_group->id = ''; + $breakpoint_group->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM; + $breakpoint_group->source = 'custom*_module source'; + + $exception = FALSE; + try { + $breakpoint_group->save(); + } + catch (InvalidBreakpointSourceException $e) { + $exception = TRUE; + } + $this->assertTrue($exception, t('An exception is thrown when an invalid source is entered.')); + + // Try a valid breakpoint_group. + $breakpoint_group->id = 'test'; + $breakpoint_group->source = 'custom_module_source'; + + $exception = FALSE; + try { + $breakpoint_group->save(); + } + catch (\Exception $e) { + $exception = TRUE; + } + $this->assertFalse($exception, t('No exception is thrown when a valid data is passed.')); + } +}