only in patch2: unchanged: --- a/.editorconfig +++ b/.editorconfig @@ -13,5 +13,5 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[composer.{json,lock}] +[composer.json] indent_size = 4 only in patch2: unchanged: --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "wikimedia/composer-merge-plugin": "~1.3" }, "replace": { - "drupal/core": "~8.4" + "drupal/core": "~8.3" }, "minimum-stability": "dev", "prefer-stable": true, only in patch2: unchanged: --- a/composer.lock +++ b/composer.lock @@ -4,40 +4,31 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "47cf4b2b460c00b55b2533e8caa6df19", + "content-hash": "fb766841005ecf4b3ec4ecd8b4c98df4", "packages": [ { "name": "asm89/stack-cors", - "version": "1.1.0", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/asm89/stack-cors.git", - "reference": "65ccbd455370f043c2e3b93482a3813603d68731" + "reference": "3ae8ef219bb4c9a6caf857421719aa07fa7776cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/65ccbd455370f043c2e3b93482a3813603d68731", - "reference": "65ccbd455370f043c2e3b93482a3813603d68731", + "url": "https://api.github.com/repos/asm89/stack-cors/zipball/3ae8ef219bb4c9a6caf857421719aa07fa7776cc", + "reference": "3ae8ef219bb4c9a6caf857421719aa07fa7776cc", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/http-foundation": "~2.7|~3.0", - "symfony/http-kernel": "~2.7|~3.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.0 || ^4.8.10", - "squizlabs/php_codesniffer": "^2.3" + "php": ">=5.3.2", + "symfony/http-foundation": "~2.1|~3.0", + "symfony/http-kernel": "~2.1|~3.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { - "psr-4": { - "Asm89\\Stack\\": "src/Asm89/Stack/" + "psr-0": { + "Asm89\\Stack": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -56,7 +47,7 @@ "cors", "stack" ], - "time": "2017-04-11T20:03:41+00:00" + "time": "2016-08-01T12:05:04+00:00" }, { "name": "composer/installers", @@ -2429,30 +2420,29 @@ }, { "name": "twig/twig", - "version": "v1.32.0", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "9935b662e24d6e634da88901ab534cc12e8c728f" + "reference": "f16a634ab08d87e520da5671ec52153d627f10f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9935b662e24d6e634da88901ab534cc12e8c728f", - "reference": "9935b662e24d6e634da88901ab534cc12e8c728f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/f16a634ab08d87e520da5671ec52153d627f10f6", + "reference": "f16a634ab08d87e520da5671ec52153d627f10f6", "shasum": "" }, "require": { "php": ">=5.2.7" }, "require-dev": { - "psr/container": "^1.0", "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.2" + "symfony/phpunit-bridge": "~2.7" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.32-dev" + "dev-master": "1.25-dev" } }, "autoload": { @@ -2487,7 +2477,7 @@ "keywords": [ "templating" ], - "time": "2017-02-27T00:07:03+00:00" + "time": "2016-09-21T23:05:12+00:00" }, { "name": "wikimedia/composer-merge-plugin", only in patch2: unchanged: --- a/core/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Ignore node_modules folder created when installing core's JavaScript -# dependencies. -node_modules - -# Ignore overrides of core's phpcs.xml.dist and phpunit.xml.dist. -phpcs.xml -phpunit.xml only in patch2: unchanged: --- a/core/CHANGELOG.txt +++ b/core/CHANGELOG.txt @@ -1,3 +1,7 @@ +Drupal 8.3.1, 2017-04-19 +------------------------ +- Fixed security issues. See SA-CORE-2017-002. + Drupal 8.3.0, 2017-04-05 ------------------------ - Added modules: only in patch2: unchanged: --- a/core/composer.json +++ b/core/composer.json @@ -32,7 +32,7 @@ "zendframework/zend-diactoros": "~1.1", "composer/semver": "~1.0", "paragonie/random_compat": "^1.0|^2.0", - "asm89/stack-cors": "~1.1" + "asm89/stack-cors": "~1.0" }, "conflict": { "drush/drush": "<8.1.10" @@ -44,7 +44,7 @@ "jcalderonzumba/gastonjs": "~1.0.2", "jcalderonzumba/mink-phantomjs-driver": "~0.3.1", "mikey179/vfsStream": "~1.2", - "phpunit/phpunit": ">=4.8.35 <5", + "phpunit/phpunit": ">=4.8.28 <5", "symfony/browser-kit": ">=2.8.13 <3.0", "symfony/css-selector": "~2.8" }, only in patch2: unchanged: --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -46,7 +46,7 @@ mapping: sequence: label: Sequence class: '\Drupal\Core\Config\Schema\Sequence' - definition_class: '\Drupal\Core\Config\Schema\SequenceDataDefinition' + definition_class: '\Drupal\Core\TypedData\ListDataDefinition' # Simple extended data types: only in patch2: unchanged: --- a/core/core.link_relation_types.yml +++ b/core/core.link_relation_types.yml @@ -79,9 +79,6 @@ create-form: current: description: "Refers to a resource containing the most recent item(s) in a collection of resources." reference: '[RFC5005]' -customize-form: - description: "The target URI points to a resource where a submission form for customizing associated resource can be obtained." - reference: '[RFC6861]' derivedfrom: description: 'The target IRI points to a resource from which this material was derived.' reference: '[draft-hoffman-xml2rfc]' only in patch2: unchanged: --- a/core/core.services.yml +++ b/core/core.services.yml @@ -331,11 +331,9 @@ services: arguments: ['@config.storage', 'config/schema', '', true, '%install_profile%'] config.typed: class: Drupal\Core\Config\TypedConfigManager - arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler', '@class_resolver'] + arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler'] tags: - { name: plugin_manager_cache_clear } - calls: - - [setValidationConstraintManager, ['@validation.constraint']] context.handler: class: Drupal\Core\Plugin\Context\ContextHandler arguments: ['@typed_data_manager'] @@ -1232,8 +1230,8 @@ services: tags: - { name: event_subscriber } arguments: ['@http_kernel', '@logger.channel.php', '@redirect.destination', '@router.no_access_checks'] - exception.final: - class: Drupal\Core\EventSubscriber\FinalExceptionSubscriber + exception.default: + class: Drupal\Core\EventSubscriber\DefaultExceptionSubscriber tags: - { name: event_subscriber } arguments: ['@config.factory'] only in patch2: unchanged: --- a/core/includes/schema.inc +++ b/core/includes/schema.inc @@ -119,7 +119,7 @@ function drupal_install_schema($module) { _drupal_schema_initialize($schema, $module, FALSE); foreach ($schema as $name => $table) { - \Drupal::database()->schema()->createTable($name, $table); + db_create_table($name, $table); } } only in patch2: unchanged: --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -240,7 +240,8 @@ function drupal_find_theme_templates($cache, $extension, $path) { // Match templates based on the 'template' filename. foreach ($cache as $hook => $info) { if (isset($info['template'])) { - if ($template === $info['template']) { + $template_candidates = [$info['template'], str_replace($info['theme path'] . '/templates/', '', $info['template'])]; + if (in_array($template, $template_candidates)) { $implementations[$hook] = [ 'template' => $template, 'path' => dirname($file->uri), only in patch2: unchanged: --- a/core/lib/Drupal.php +++ b/core/lib/Drupal.php @@ -81,7 +81,7 @@ class Drupal { /** * The current system version. */ - const VERSION = '8.4.0-dev'; + const VERSION = '8.3.2-dev'; /** * Core API compatibility. only in patch2: unchanged: --- a/core/lib/Drupal/Core/Action/ConfigurableActionBase.php +++ b/core/lib/Drupal/Core/Action/ConfigurableActionBase.php @@ -17,7 +17,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->setConfiguration($configuration); + $this->configuration += $this->defaultConfiguration(); } /** @@ -38,7 +38,7 @@ public function getConfiguration() { * {@inheritdoc} */ public function setConfiguration(array $configuration) { - $this->configuration = $configuration + $this->defaultConfiguration(); + $this->configuration = $configuration; } /** only in patch2: unchanged: --- a/core/lib/Drupal/Core/Config/Schema/ArrayElement.php +++ b/core/lib/Drupal/Core/Config/Schema/ArrayElement.php @@ -2,12 +2,10 @@ namespace Drupal\Core\Config\Schema; -use Drupal\Core\TypedData\ComplexDataInterface; - /** * Defines a generic configuration element that contains multiple properties. */ -abstract class ArrayElement extends Element implements \IteratorAggregate, TypedConfigInterface, ComplexDataInterface { +abstract class ArrayElement extends Element implements \IteratorAggregate, TypedConfigInterface { /** * Parsed elements. @@ -163,25 +161,4 @@ public function isNullable() { return isset($this->definition['nullable']) && $this->definition['nullable'] == TRUE; } - /** - * {@inheritdoc} - */ - public function set($property_name, $value, $notify = TRUE) { - $this->value[$property_name] = $value; - // Config schema elements do not make use of notifications. Thus, we skip - // notifying parents. - return $this; - } - - /** - * {@inheritdoc} - */ - public function getProperties($include_computed = FALSE) { - $properties = []; - foreach (array_keys($this->value) as $name) { - $properties[$name] = $this->get($name); - } - return $properties; - } - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Config/Schema/Sequence.php +++ b/core/lib/Drupal/Core/Config/Schema/Sequence.php @@ -10,12 +10,6 @@ * * Read https://www.drupal.org/node/1905070 for more details about configuration * schema, types and type resolution. - * - * Note that sequences implement the typed data ComplexDataInterface (via the - * parent ArrayElement) rather than the ListInterface. This is because sequences - * may have named keys, which is not supported by ListInterface. From the typed - * data API perspective sequences are handled as ordered mappings without - * metadata about existing properties. */ class Sequence extends ArrayElement { only in patch2: unchanged: --- a/core/lib/Drupal/Core/Config/Schema/SequenceDataDefinition.php +++ /dev/null @@ -1,28 +0,0 @@ -definition['orderby']) ? $this->definition['orderby'] : NULL; - } - -} only in patch2: unchanged: --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -3,8 +3,6 @@ namespace Drupal\Core\Config; use Drupal\Core\Config\Schema\Ignore; -use Drupal\Core\Config\Schema\Sequence; -use Drupal\Core\Config\Schema\SequenceDataDefinition; use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\TypedData\Type\FloatInterface; use Drupal\Core\TypedData\Type\IntegerInterface; @@ -212,29 +210,6 @@ protected function castValue($key, $value) { foreach ($value as $nested_value_key => $nested_value) { $value[$nested_value_key] = $this->castValue($key . '.' . $nested_value_key, $nested_value); } - - if ($element instanceof Sequence) { - $data_definition = $element->getDataDefinition(); - if ($data_definition instanceof SequenceDataDefinition) { - // Apply any sorting defined on the schema. - switch ($data_definition->getOrderBy()) { - case 'key': - ksort($value); - break; - - case 'value': - // The PHP documentation notes that "Be careful when sorting - // arrays with mixed types values because sort() can produce - // unpredictable results". There is no risk here because - // \Drupal\Core\Config\StorableConfigBase::castValue() has - // already cast all values to the same type using the - // configuration schema. - sort($value); - break; - - } - } - } } return $value; } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -6,7 +6,6 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\Schema\ConfigSchemaAlterException; use Drupal\Core\Config\Schema\ConfigSchemaDiscovery; -use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Config\Schema\Undefined; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\TypedData\TypedDataManager; @@ -46,18 +45,13 @@ class TypedConfigManager extends TypedDataManager implements TypedConfigManagerI * The storage object to use for reading schema data * @param \Drupal\Core\Cache\CacheBackendInterface $cache * The cache backend to use for caching the definitions. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler. - * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver - * (optional) The class resolver. */ - public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, CacheBackendInterface $cache, ModuleHandlerInterface $module_handler, ClassResolverInterface $class_resolver = NULL) { + public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, CacheBackendInterface $cache, ModuleHandlerInterface $module_handler) { $this->configStorage = $configStorage; $this->schemaStorage = $schemaStorage; $this->setCacheBackend($cache, 'typed_config_definitions'); $this->alterInfo('config_schema_info'); $this->moduleHandler = $module_handler; - $this->classResolver = $class_resolver ?: \Drupal::service('class_resolver'); } /** @@ -190,7 +184,6 @@ protected function getDefinitionWithReplacements($base_plugin_id, array $replace $definition += [ 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', 'type' => $type, - 'unwrap_for_canonical_representation' => TRUE, ]; return $definition; } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Database/database.api.php +++ b/core/lib/Drupal/Core/Database/database.api.php @@ -5,8 +5,6 @@ * Hooks related to the Database system and the Schema API. */ -use Drupal\Core\Database\Query\Condition; - /** * @defgroup database Database abstraction layer * @{ @@ -434,11 +432,11 @@ function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $que if (!\Drupal::currentUser()->hasPermission('bypass node access')) { // The node_access table has the access grants for any given node. $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid'); - $or = new Condition('OR'); + $or = db_or(); // If any grant exists for the specified user, then user has access to the node for the specified operation. foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) { foreach ($gids as $gid) { - $or->condition((new Condition('AND')) + $or->condition(db_and() ->condition($access_alias . '.gid', $gid) ->condition($access_alias . '.realm', $realm) ); only in patch2: unchanged: --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -410,7 +410,7 @@ public static function findSitePath(Request $request, $require_settings = TRUE, * {@inheritdoc} */ public function setSitePath($path) { - if ($this->booted && $path !== $this->sitePath) { + if ($this->booted) { throw new \LogicException('Site path cannot be changed after calling boot()'); } $this->sitePath = $path; only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -1285,15 +1285,20 @@ public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, * An array of field names. */ protected function getFieldsToSkipFromTranslationChangesCheck() { - /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */ - $entity_type = $this->getEntityType(); // A list of known revision metadata fields which should be skipped from // the comparision. + // @todo Replace the hard coded list of revision metadata fields with the + // solution from https://www.drupal.org/node/2615016. $fields = [ - $entity_type->getKey('revision'), + $this->getEntityType()->getKey('revision'), 'revision_translation_affected', + 'revision_uid', + 'revision_user', + 'revision_timestamp', + 'revision_created', + 'revision_log', + 'revision_log_message', ]; - $fields = array_merge($fields, array_values($entity_type->getRevisionMetadataKeys())); return $fields; } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/ContentEntityType.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityType.php @@ -8,13 +8,6 @@ class ContentEntityType extends EntityType implements ContentEntityTypeInterface { /** - * An array of entity revision metadata keys. - * - * @var array - */ - protected $revision_metadata_keys = []; - - /** * {@inheritdoc} */ public function __construct($definition) { @@ -48,44 +41,4 @@ protected function checkStorageClass($class) { } } - /** - * {@inheritdoc} - */ - public function getRevisionMetadataKeys($include_backwards_compatibility_field_names = TRUE) { - // Provide backwards compatibility in case the revision metadata keys are - // not defined in the entity annotation. - if (!$this->revision_metadata_keys && $include_backwards_compatibility_field_names) { - $base_fields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($this->id()); - if ((isset($base_fields['revision_uid']) && $revision_user = 'revision_uid') || (isset($base_fields['revision_user']) && $revision_user = 'revision_user')) { - @trigger_error('The revision_user revision metadata key is not set.', E_USER_DEPRECATED); - $this->revision_metadata_keys['revision_user'] = $revision_user; - } - if ((isset($base_fields['revision_timestamp']) && $revision_timestamp = 'revision_timestamp') || (isset($base_fields['revision_created'])) && $revision_timestamp = 'revision_created') { - @trigger_error('The revision_created revision metadata key is not set.', E_USER_DEPRECATED); - $this->revision_metadata_keys['revision_created'] = $revision_timestamp; - } - if ((isset($base_fields['revision_log']) && $revision_log = 'revision_log') || (isset($base_fields['revision_log_message']) && $revision_log = 'revision_log_message')) { - @trigger_error('The revision_log_message revision metadata key is not set.', E_USER_DEPRECATED); - $this->revision_metadata_keys['revision_log_message'] = $revision_log; - } - } - return $this->revision_metadata_keys; - } - - /** - * {@inheritdoc} - */ - public function getRevisionMetadataKey($key) { - $keys = $this->getRevisionMetadataKeys(); - return isset($keys[$key]) ? $keys[$key] : FALSE; - } - - /** - * {@inheritdoc} - */ - public function hasRevisionMetadataKey($key) { - $keys = $this->getRevisionMetadataKeys(); - return isset($keys[$key]); - } - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/ContentEntityTypeInterface.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityTypeInterface.php @@ -6,50 +6,4 @@ * Provides an interface for a content entity type and its metadata. */ interface ContentEntityTypeInterface extends EntityTypeInterface { - - /** - * Gets an array of entity revision metadata keys. - * - * @param bool $include_backwards_compatibility_field_names - * (optional and deprecated) Whether to provide the revision keys on a - * best-effort basis by looking at the base fields defined by the entity - * type. Note that this parameter will be removed in Drupal 9.0.0. Defaults - * to TRUE. - * - * @return array - * An array describing how the Field API can extract revision metadata - * information of this entity type: - * - revision_log_message: The name of the property that contains description - * of the changes that were made in the current revision. - * - revision_user: The name of the property that contains the user ID of - * the author of the current revision. - * - revision_created: The name of the property that contains the timestamp - * of the current revision. - */ - public function getRevisionMetadataKeys($include_backwards_compatibility_field_names = TRUE); - - /** - * Gets a specific entity revision metadata key. - * - * @param string $key - * The name of the entity revision metadata key to return. - * - * @return string|bool - * The entity revision metadata key, or FALSE if it does not exist. - * - * @see self::getRevisionMetadataKeys() - */ - public function getRevisionMetadataKey($key); - - /** - * Indicates if a given entity revision metadata key exists. - * - * @param string $key - * The name of the entity revision metadata key to check. - * - * @return bool - * TRUE if a given entity revision metadata key exists, FALSE otherwise. - */ - public function hasRevisionMetadataKey($key); - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/EditorialContentEntityBase.php +++ /dev/null @@ -1,31 +0,0 @@ -setLabel(t('Revision create time')) ->setDescription(t('The time that the current revision was created.')) ->setRevisionable(TRUE); - $fields[static::getRevisionMetadataKey($entity_type, 'revision_user')] = BaseFieldDefinition::create('entity_reference') + $fields['revision_user'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Revision user')) ->setDescription(t('The user ID of the author of the current revision.')) ->setSetting('target_type', 'user') ->setRevisionable(TRUE); - $fields[static::getRevisionMetadataKey($entity_type, 'revision_log_message')] = BaseFieldDefinition::create('string_long') + $fields['revision_log_message'] = BaseFieldDefinition::create('string_long') ->setLabel(t('Revision log message')) ->setDescription(t('Briefly describe the changes you have made.')) ->setRevisionable(TRUE) @@ -56,14 +56,14 @@ public static function revisionLogBaseFieldDefinitions(EntityTypeInterface $enti * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionCreationTime(). */ public function getRevisionCreationTime() { - return $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_created')}->value; + return $this->revision_created->value; } /** * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionCreationTime(). */ public function setRevisionCreationTime($timestamp) { - $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_created')}->value = $timestamp; + $this->revision_created->value = $timestamp; return $this; } @@ -71,14 +71,14 @@ public function setRevisionCreationTime($timestamp) { * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUser(). */ public function getRevisionUser() { - return $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_user')}->entity; + return $this->revision_user->entity; } /** * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUser(). */ public function setRevisionUser(UserInterface $account) { - $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_user')}->entity = $account; + $this->revision_user->entity = $account; return $this; } @@ -86,14 +86,14 @@ public function setRevisionUser(UserInterface $account) { * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionUserId(). */ public function getRevisionUserId() { - return $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_user')}->target_id; + return $this->revision_user->target_id; } /** * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionUserId(). */ public function setRevisionUserId($user_id) { - $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_user')}->target_id = $user_id; + $this->revision_user->target_id = $user_id; return $this; } @@ -101,41 +101,15 @@ public function setRevisionUserId($user_id) { * Implements \Drupal\Core\Entity\RevisionLogInterface::getRevisionLogMessage(). */ public function getRevisionLogMessage() { - return $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_log_message')}->value; + return $this->revision_log_message->value; } /** * Implements \Drupal\Core\Entity\RevisionLogInterface::setRevisionLogMessage(). */ public function setRevisionLogMessage($revision_log_message) { - $this->{static::getRevisionMetadataKey($this->getEntityType(), 'revision_log_message')}->value = $revision_log_message; + $this->revision_log_message->value = $revision_log_message; return $this; } - /** - * Gets the name of a revision metadata field. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * A content entity type definition. - * @param string $key - * The revision metadata key to get, must be one of 'revision_created', - * 'revision_user' or 'revision_log_message'. - * - * @return string - * The name of the field for the specified $key. - */ - protected static function getRevisionMetadataKey(EntityTypeInterface $entity_type, $key) { - // We need to prevent ContentEntityType::getRevisionMetadataKey() from - // providing fallback as that requires fetching the entity type's field - // definition leading to an infinite recursion. - /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */ - $revision_metadata_keys = $entity_type->getRevisionMetadataKeys(FALSE) + [ - 'revision_created' => 'revision_created', - 'revision_user' => 'revision_user', - 'revision_log_message' => 'revision_log_message', - ]; - - return $revision_metadata_keys[$key]; - } - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php +++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php @@ -294,11 +294,17 @@ public function getTableMapping(array $storage_definitions = NULL) { // Make sure the key fields come first in the list of fields. $all_fields = array_merge($key_fields, array_diff($all_fields, $key_fields)); - // If the entity is revisionable, gather the fields that need to be put - // in the revision table. - $revisionable = $this->entityType->isRevisionable(); - $revision_metadata_fields = $revisionable ? array_values($this->entityType->getRevisionMetadataKeys()) : []; + // Nodes have all three of these fields, while custom blocks only have + // log. + // @todo Provide automatic definitions for revision metadata fields in + // https://www.drupal.org/node/2248983. + $revision_metadata_fields = array_intersect([ + 'revision_timestamp', + 'revision_uid', + 'revision_log', + ], $all_fields); + $revisionable = $this->entityType->isRevisionable(); $translatable = $this->entityType->isTranslatable(); if (!$revisionable && !$translatable) { // The base layout stores all the base field values in the base table. only in patch2: unchanged: --- a/core/lib/Drupal/Core/Entity/entity.api.php +++ b/core/lib/Drupal/Core/Entity/entity.api.php @@ -271,11 +271,6 @@ * either \Drupal\Core\Config\Entity\ConfigEntityBase or * \Drupal\Core\Entity\ContentEntityBase, with annotation for * \@ConfigEntityType or \@ContentEntityType in its documentation block. - * If you are defining a content entity type, it is recommended to extend the - * \Drupal\Core\Entity\EditorialContentEntityBase base class in order to get - * out-of-the-box support for Entity API's revisioning and publishing - * features, which will allow your entity type to be used with Drupal's - * editorial workflow provided by the Content Moderation module. * - The 'id' annotation gives the entity type ID, and the 'label' annotation * gives the human-readable name of the entity type. If you are defining a * content entity type that uses bundles, the 'bundle_label' annotation gives only in patch2: unchanged: --- /dev/null +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php @@ -0,0 +1,245 @@ +configFactory = $config_factory; + } + + /** + * Gets the configured error level. + * + * @return string + */ + protected function getErrorLevel() { + if (!isset($this->errorLevel)) { + $this->errorLevel = $this->configFactory->get('system.logging')->get('error_level'); + } + return $this->errorLevel; + } + + /** + * Handles any exception as a generic error page for HTML. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + protected function onHtml(GetResponseForExceptionEvent $event) { + $exception = $event->getException(); + $error = Error::decodeException($exception); + + // Display the message if the current error reporting level allows this type + // of message to be displayed, and unconditionally in update.php. + $message = ''; + if (error_displayable($error)) { + // If error type is 'User notice' then treat it as debug information + // instead of an error message. + // @see debug() + if ($error['%type'] == 'User notice') { + $error['%type'] = 'Debug'; + } + + // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path + // in the message. This does not happen for (false) security. + $root_length = strlen(DRUPAL_ROOT); + if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { + $error['%file'] = substr($error['%file'], $root_length + 1); + } + + unset($error['backtrace']); + + if ($this->getErrorLevel() != ERROR_REPORTING_DISPLAY_VERBOSE) { + // Without verbose logging, use a simple message. + + // We call SafeMarkup::format directly here, rather than use t() since + // we are in the middle of error handling, and we don't want t() to + // cause further errors. + $message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error); + } + else { + // With verbose logging, we will also include a backtrace. + + $backtrace_exception = $exception; + while ($backtrace_exception->getPrevious()) { + $backtrace_exception = $backtrace_exception->getPrevious(); + } + $backtrace = $backtrace_exception->getTrace(); + // First trace is the error itself, already contained in the message. + // While the second trace is the error source and also contained in the + // message, the message doesn't contain argument values, so we output it + // once more in the backtrace. + array_shift($backtrace); + + // Generate a backtrace containing only scalar argument values. + $error['@backtrace'] = Error::formatBacktrace($backtrace); + $message = SafeMarkup::format('%type: @message in %function (line %line of %file).
@backtrace
', $error); + } + } + + $content = $this->t('The website encountered an unexpected error. Please try again later.'); + $content .= $message ? '

' . $message : ''; + $response = new Response($content, 500); + + if ($exception instanceof HttpExceptionInterface) { + $response->setStatusCode($exception->getStatusCode()); + $response->headers->add($exception->getHeaders()); + } + else { + $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)'); + } + + $event->setResponse($response); + } + + /** + * Handles any exception as a generic error page for JSON. + * + * @todo This should probably check the error reporting level. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + protected function onJson(GetResponseForExceptionEvent $event) { + $exception = $event->getException(); + $error = Error::decodeException($exception); + + // Display the message if the current error reporting level allows this type + // of message to be displayed, + $data = NULL; + if (error_displayable($error) && $message = $exception->getMessage()) { + $data = ['message' => sprintf('A fatal error occurred: %s', $message)]; + } + + $response = new JsonResponse($data, Response::HTTP_INTERNAL_SERVER_ERROR); + if ($exception instanceof HttpExceptionInterface) { + $response->setStatusCode($exception->getStatusCode()); + $response->headers->add($exception->getHeaders()); + } + + $event->setResponse($response); + } + + /** + * Handles an HttpExceptionInterface exception for unknown formats. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + protected function onFormatUnknown(GetResponseForExceptionEvent $event) { + /** @var \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface|\Exception $exception */ + $exception = $event->getException(); + + $response = new Response($exception->getMessage(), $exception->getStatusCode(), $exception->getHeaders()); + $event->setResponse($response); + } + + /** + * Handles errors for this subscriber. + * + * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event + * The event to process. + */ + public function onException(GetResponseForExceptionEvent $event) { + $format = $this->getFormat($event->getRequest()); + $exception = $event->getException(); + + $method = 'on' . $format; + if (!method_exists($this, $method)) { + if ($exception instanceof HttpExceptionInterface) { + $this->onFormatUnknown($event); + $response = $event->getResponse(); + $response->headers->set('Content-Type', 'text/plain'); + } + else { + $this->onHtml($event); + } + } + else { + $this->$method($event); + } + } + + /** + * Gets the error-relevant format from the request. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object. + * + * @return string + * The format as which to treat the exception. + */ + protected function getFormat(Request $request) { + $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat()); + + // These are all JSON errors for our purposes. Any special handling for + // them can/should happen in earlier listeners if desired. + if (in_array($format, ['drupal_modal', 'drupal_dialog', 'drupal_ajax'])) { + $format = 'json'; + } + + // Make an educated guess that any Accept header type that includes "json" + // can probably handle a generic JSON response for errors. As above, for + // any format this doesn't catch or that wants custom handling should + // register its own exception listener. + foreach ($request->getAcceptableContentTypes() as $mime) { + if (strpos($mime, 'html') === FALSE && strpos($mime, 'json') !== FALSE) { + $format = 'json'; + } + } + + return $format; + } + + /** + * Registers the methods in this class that should be listeners. + * + * @return array + * An array of event listener definitions. + */ + public static function getSubscribedEvents() { + $events[KernelEvents::EXCEPTION][] = ['onException', -256]; + return $events; + } + +} only in patch2: unchanged: --- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php @@ -14,7 +14,7 @@ class ExceptionJsonSubscriber extends HttpExceptionSubscriberBase { * {@inheritdoc} */ protected function getHandledFormats() { - return ['json', 'drupal_modal', 'drupal_dialog', 'drupal_ajax']; + return ['json']; } /** only in patch2: unchanged: --- a/core/lib/Drupal/Core/EventSubscriber/FinalExceptionSubscriber.php +++ /dev/null @@ -1,195 +0,0 @@ -configFactory = $config_factory; - } - - /** - * Gets the configured error level. - * - * @return string - */ - protected function getErrorLevel() { - if (!isset($this->errorLevel)) { - $this->errorLevel = $this->configFactory->get('system.logging')->get('error_level'); - } - return $this->errorLevel; - } - - /** - * Handles exceptions for this subscriber. - * - * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event - * The event to process. - */ - public function onException(GetResponseForExceptionEvent $event) { - $exception = $event->getException(); - $error = Error::decodeException($exception); - - // Display the message if the current error reporting level allows this type - // of message to be displayed, and unconditionally in update.php. - $message = ''; - if ($this->isErrorDisplayable($error)) { - // If error type is 'User notice' then treat it as debug information - // instead of an error message. - // @see debug() - if ($error['%type'] == 'User notice') { - $error['%type'] = 'Debug'; - } - - $error = $this->simplifyFileInError($error); - - unset($error['backtrace']); - - if (!$this->isErrorLevelVerbose()) { - // Without verbose logging, use a simple message. - - // We call SafeMarkup::format directly here, rather than use t() since - // we are in the middle of error handling, and we don't want t() to - // cause further errors. - $message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error); - } - else { - // With verbose logging, we will also include a backtrace. - - $backtrace_exception = $exception; - while ($backtrace_exception->getPrevious()) { - $backtrace_exception = $backtrace_exception->getPrevious(); - } - $backtrace = $backtrace_exception->getTrace(); - // First trace is the error itself, already contained in the message. - // While the second trace is the error source and also contained in the - // message, the message doesn't contain argument values, so we output it - // once more in the backtrace. - array_shift($backtrace); - - // Generate a backtrace containing only scalar argument values. - $error['@backtrace'] = Error::formatBacktrace($backtrace); - $message = SafeMarkup::format('%type: @message in %function (line %line of %file).
@backtrace
', $error); - } - } - - $content = $this->t('The website encountered an unexpected error. Please try again later.'); - $content .= $message ? '

' . $message : ''; - $response = new Response($content, 500, ['Content-Type' => 'text/plain']); - - if ($exception instanceof HttpExceptionInterface) { - $response->setStatusCode($exception->getStatusCode()); - $response->headers->add($exception->getHeaders()); - } - else { - $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR, '500 Service unavailable (with message)'); - } - - $event->setResponse($response); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() { - // Run as the final (very late) KernelEvents::EXCEPTION subscriber. - $events[KernelEvents::EXCEPTION][] = ['onException', -256]; - return $events; - } - - /** - * Checks whether the error level is verbose or not. - * - * @return bool - */ - protected function isErrorLevelVerbose() { - return $this->getErrorLevel() === ERROR_REPORTING_DISPLAY_VERBOSE; - } - - /** - * Wrapper for error_displayable(). - * - * @param $error - * Optional error to examine for ERROR_REPORTING_DISPLAY_SOME. - * - * @return bool - * - * @see \error_displayable - */ - protected function isErrorDisplayable($error) { - return error_displayable($error); - } - - /** - * Attempts to reduce error verbosity in the error message's file path. - * - * Attempts to reduce verbosity by removing DRUPAL_ROOT from the file path in - * the message. This does not happen for (false) security. - * - * @param $error - * Optional error to examine for ERROR_REPORTING_DISPLAY_SOME. - * - * @return - * The updated $error. - */ - protected function simplifyFileInError($error) { - // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path - // in the message. This does not happen for (false) security. - $root_length = strlen(DRUPAL_ROOT); - if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) { - $error['%file'] = substr($error['%file'], $root_length + 1); - } - return $error; - } - -} only in patch2: unchanged: --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -216,16 +216,10 @@ public function addTheme(Extension $theme) { * {@inheritdoc} */ public function refreshInfo() { + $this->reset(); $extension_config = $this->configFactory->get('core.extension'); $installed = $extension_config->get('theme'); - // Only refresh the info if a theme has been installed. Modules are - // installed before themes by the installer and this method is called during - // module installation. - if (empty($installed) && empty($this->list)) { - return; - } - $this->reset(); // @todo Avoid re-scanning all themes by retaining the original (unaltered) // theme info somewhere. $list = $this->rebuildThemeData(); only in patch2: unchanged: --- a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php +++ b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php @@ -89,6 +89,7 @@ public static function createFromFieldStorageDefinition(FieldStorageDefinitionIn ->setLabel($definition->getLabel()) ->setName($definition->getName()) ->setProvider($definition->getProvider()) + ->setQueryable($definition->isQueryable()) ->setRevisionable($definition->isRevisionable()) ->setSettings($definition->getSettings()) ->setTargetEntityTypeId($definition->getTargetEntityTypeId()) @@ -286,8 +287,7 @@ public function isMultiple() { * {@inheritdoc} */ public function isQueryable() { - @trigger_error('BaseFieldDefinition::isQueryable() is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Field\BaseFieldDefinition::hasCustomStorage(). See https://www.drupal.org/node/2856563.', E_USER_DEPRECATED); - return !$this->hasCustomStorage(); + return isset($this->definition['queryable']) ? $this->definition['queryable'] : !$this->isComputed(); } /** @@ -298,14 +298,8 @@ public function isQueryable() { * * @return static * The object itself for chaining. - * - * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use - * \Drupal\Core\Field\BaseFieldDefinition::setCustomStorage() instead. - * - * @see https://www.drupal.org/node/2856563 */ public function setQueryable($queryable) { - @trigger_error('BaseFieldDefinition::setQueryable() is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, you should use \Drupal\Core\Field\BaseFieldDefinition::setCustomStorage(). See https://www.drupal.org/node/2856563.', E_USER_DEPRECATED); $this->definition['queryable'] = $queryable; return $this; } @@ -585,7 +579,7 @@ protected function getFieldItemClass() { public function __sleep() { // Do not serialize the statically cached property definitions. $vars = get_object_vars($this); - unset($vars['propertyDefinitions'], $vars['typedDataManager']); + unset($vars['propertyDefinitions']); return array_keys($vars); } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php +++ b/core/lib/Drupal/Core/Field/FieldStorageDefinitionInterface.php @@ -109,12 +109,6 @@ public function isRevisionable(); * * @return bool * TRUE if the field is queryable. - * - * @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Use - * \Drupal\Core\Field\FieldStorageDefinitionInterface::hasCustomStorage() - * instead. - * - * @see https://www.drupal.org/node/2856563 */ public function isQueryable(); only in patch2: unchanged: --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/TimestampItem.php @@ -2,9 +2,8 @@ namespace Drupal\Core\Field\Plugin\Field\FieldType; -use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\Core\Field\FieldItemBase; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\Field\FieldItemBase; use Drupal\Core\TypedData\DataDefinition; /** @@ -54,14 +53,4 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) ]; } - /** - * {@inheritdoc} - */ - public static function generateSampleValue(FieldDefinitionInterface $field_definition) { - // Pick a random timestamp in the past year. - $timestamp = \Drupal::time()->getRequestTime() - mt_rand(0, 86400 * 365); - $values['value'] = $timestamp; - return $values; - } - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/LanguageSelectWidget.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/LanguageSelectWidget.php @@ -27,32 +27,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element['value'] = $element + [ '#type' => 'language_select', '#default_value' => $items[$delta]->value, - '#languages' => $this->getSetting('include_locked') ? LanguageInterface::STATE_ALL : LanguageInterface::STATE_CONFIGURABLE, - ]; - - return $element; - } - - /** - * {@inheritdoc} - */ - public static function defaultSettings() { - $settings = parent::defaultSettings(); - $settings['include_locked'] = TRUE; - - return $settings; - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, FormStateInterface $form_state) { - $element = parent::settingsForm($form, $form_state); - - $element['include_locked'] = [ - '#type' => 'checkbox', - '#title' => $this->t('Include locked languages such as Not specified and Not applicable'), - '#default_value' => $this->getSetting('include_locked'), + '#languages' => LanguageInterface::STATE_ALL, ]; return $element; only in patch2: unchanged: --- a/core/lib/Drupal/Core/FileTransfer/FTPExtension.php +++ b/core/lib/Drupal/Core/FileTransfer/FTPExtension.php @@ -45,7 +45,7 @@ protected function createDirectoryJailed($directory) { protected function removeDirectoryJailed($directory) { $pwd = ftp_pwd($this->connection); if (!ftp_chdir($this->connection, $directory)) { - throw new FileTransferException("Unable to change the current directory to @directory", NULL, ['@directory' => $directory]); + throw new FileTransferException("Unable to change to directory @directory", NULL, ['@directory' => $directory]); } $list = @ftp_nlist($this->connection, '.'); if (!$list) { @@ -65,7 +65,7 @@ protected function removeDirectoryJailed($directory) { } ftp_chdir($this->connection, $pwd); if (!ftp_rmdir($this->connection, $directory)) { - throw new FileTransferException("Unable to remove the directory @directory", NULL, ['@directory' => $directory]); + throw new FileTransferException("Unable to remove to directory @directory", NULL, ['@directory' => $directory]); } } @@ -74,7 +74,7 @@ protected function removeDirectoryJailed($directory) { */ protected function removeFileJailed($destination) { if (!ftp_delete($this->connection, $destination)) { - throw new FileTransferException("Unable to remove the file @file", NULL, ['@file' => $destination]); + throw new FileTransferException("Unable to remove to file @file", NULL, ['@file' => $destination]); } } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Form/FormValidator.php +++ b/core/lib/Drupal/Core/Form/FormValidator.php @@ -229,12 +229,8 @@ protected function finalizeValidation(&$form, FormStateInterface &$form_state, $ * theming, and hook_form_alter functions. */ protected function doValidateForm(&$elements, FormStateInterface &$form_state, $form_id = NULL) { - // Recurse through all children, sorting the elements so that the order of - // error messages displayed to the user matches the order of elements in - // the form. Use a copy of $elements so that it is not modified by the - // sorting itself. - $elements_sorted = $elements; - foreach (Element::children($elements_sorted, TRUE) as $key) { + // Recurse through all children. + foreach (Element::children($elements) as $key) { if (isset($elements[$key]) && $elements[$key]) { $this->doValidateForm($elements[$key], $form_state); } only in patch2: unchanged: --- a/core/lib/Drupal/Core/Layout/LayoutPluginManager.php +++ b/core/lib/Drupal/Core/Layout/LayoutPluginManager.php @@ -3,13 +3,13 @@ namespace Drupal\Core\Layout; use Drupal\Component\Annotation\Plugin\Discovery\AnnotationBridgeDecorator; +use Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator; use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; -use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; use Drupal\Core\Plugin\Discovery\YamlDiscoveryDecorator; use Drupal\Core\Layout\Annotation\Layout; @@ -66,7 +66,7 @@ protected function getDiscovery() { $discovery = new AnnotatedClassDiscovery($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces); $discovery = new YamlDiscoveryDecorator($discovery, 'layouts', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories()); $discovery = new AnnotationBridgeDecorator($discovery, $this->pluginDefinitionAnnotationName); - $discovery = new ContainerDerivativeDiscoveryDecorator($discovery); + $discovery = new DerivativeDiscoveryDecorator($discovery); $this->discovery = $discovery; } return $this->discovery; only in patch2: unchanged: --- a/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php +++ b/core/lib/Drupal/Core/Plugin/DefaultSingleLazyPluginCollection.php @@ -52,7 +52,10 @@ class DefaultSingleLazyPluginCollection extends LazyPluginCollection { */ public function __construct(PluginManagerInterface $manager, $instance_id, array $configuration) { $this->manager = $manager; - $this->addInstanceId($instance_id, $configuration); + $this->instanceId = $instance_id; + // This is still needed by the parent LazyPluginCollection class. + $this->instanceIDs = [$instance_id => $instance_id]; + $this->configuration = $configuration; } /** @@ -92,8 +95,6 @@ public function setConfiguration($configuration) { */ public function addInstanceId($id, $configuration = NULL) { $this->instanceId = $id; - // Reset the list of instance IDs since there can be only one. - $this->instanceIDs = []; parent::addInstanceId($id, $configuration); if ($configuration !== NULL) { $this->setConfiguration($configuration); only in patch2: unchanged: --- a/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionBase.php +++ b/core/lib/Drupal/Core/TypedData/ComplexDataDefinitionBase.php @@ -42,7 +42,7 @@ public function getMainPropertyName() { public function __sleep() { // Do not serialize the cached property definitions. $vars = get_object_vars($this); - unset($vars['propertyDefinitions'], $vars['typedDataManager']); + unset($vars['propertyDefinitions']); return array_keys($vars); } only in patch2: unchanged: --- a/core/lib/Drupal/Core/TypedData/DataDefinition.php +++ b/core/lib/Drupal/Core/TypedData/DataDefinition.php @@ -7,8 +7,6 @@ */ class DataDefinition implements DataDefinitionInterface, \ArrayAccess { - use TypedDataTrait; - /** * The array holding values for all definition keys. * @@ -260,7 +258,7 @@ public function setSetting($setting_name, $value) { */ public function getConstraints() { $constraints = isset($this->definition['constraints']) ? $this->definition['constraints'] : []; - $constraints += $this->getTypedDataManager()->getDefaultConstraints($this); + $constraints += \Drupal::typedDataManager()->getDefaultConstraints($this); return $constraints; } @@ -342,14 +340,4 @@ public function toArray() { return $this->definition; } - /** - * {@inheritdoc} - */ - public function __sleep() { - // Never serialize the typed data manager. - $vars = get_object_vars($this); - unset($vars['typedDataManager']); - return array_keys($vars); - } - } only in patch2: unchanged: --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -117,13 +117,7 @@ public function createDataDefinition($data_type) { throw new \InvalidArgumentException("Invalid data type '$data_type' has been given"); } $class = $type_definition['definition_class']; - $data_definition = $class::createFromDataType($data_type); - - if (method_exists($data_definition, 'setTypedDataManager')) { - $data_definition->setTypedDataManager($this); - } - - return $data_definition; + return $class::createFromDataType($data_type); } /** only in patch2: unchanged: --- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php +++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php @@ -286,7 +286,7 @@ public function testBlockEmptyRendering() { $this->drupalGet($url); $this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]'))); - // Ensure that the view cacheability metadata is propagated even, for an + // Ensure that the view cachability metadata is propagated even, for an // empty block. $this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered'])); $this->assertCacheContexts(['url.query_args:_wrapper_format']); only in patch2: unchanged: --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -52,11 +52,6 @@ * "langcode" = "langcode", * "uuid" = "uuid" * }, - * revision_metadata_keys = { - * "revision_user" = "revision_user", - * "revision_created" = "revision_created", - * "revision_log_message" = "revision_log" - * }, * bundle_entity_type = "block_content_type", * field_ui_base_route = "entity.block_content_type.edit_form", * render_cache = FALSE, only in patch2: unchanged: --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -353,7 +353,8 @@ function comment_entity_storage_load($entities, $entity_type) { if (!\Drupal::entityManager()->getDefinition($entity_type)->entityClassImplements(FieldableEntityInterface::class)) { return; } - if (!\Drupal::service('comment.manager')->getFields($entity_type)) { + // @todo Investigate in https://www.drupal.org/node/2527866 why we need that. + if (!\Drupal::hasService('comment.manager') || !\Drupal::service('comment.manager')->getFields($entity_type)) { // Do not query database when entity has no comment fields. return; } only in patch2: unchanged: --- a/core/modules/comment/src/Plugin/views/argument/UserUid.php +++ b/core/modules/comment/src/Plugin/views/argument/UserUid.php @@ -3,7 +3,6 @@ namespace Drupal\comment\Plugin\views\argument; use Drupal\Core\Database\Connection; -use Drupal\Core\Database\Query\Condition; use Drupal\views\Plugin\views\argument\ArgumentPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -91,7 +90,7 @@ public function query($group_by = FALSE) { $subselect->where("c.entity_id = $this->tableAlias.$entity_id"); $subselect->condition('c.entity_type', $entity_type); - $condition = (new Condition('OR')) + $condition = db_or() ->condition("$this->tableAlias.uid", $this->argument, '=') ->exists($subselect); only in patch2: unchanged: --- a/core/modules/comment/src/Plugin/views/filter/UserUid.php +++ b/core/modules/comment/src/Plugin/views/filter/UserUid.php @@ -2,7 +2,6 @@ namespace Drupal\comment\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\views\Plugin\views\filter\FilterPluginBase; /** @@ -27,7 +26,7 @@ public function query() { $subselect->where("c.entity_id = $this->tableAlias.$entity_id"); $subselect->condition('c.entity_type', $entity_type); - $condition = (new Condition('OR')) + $condition = db_or() ->condition("$this->tableAlias.uid", $this->value, $this->operator) ->exists($subselect); only in patch2: unchanged: --- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml +++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml @@ -297,41 +297,3 @@ test.double_brackets.breed: mapping: breed: type: string - -config_schema_test.schema_sequence_sort: - type: config_object - mapping: - keyed_sort: - type: sequence - orderby: key - sequence: - - type: string - value_sort: - type: sequence - orderby: value - sequence: - - type: string - no_sort: - type: sequence - sequence: - - type: string - complex_sort_value: - type: sequence - orderby: value - sequence: - - type: mapping - mapping: - foo: - type: string - bar: - type: string - complex_sort_key: - type: sequence - orderby: key - sequence: - - type: mapping - mapping: - foo: - type: string - bar: - type: string only in patch2: unchanged: --- a/core/modules/config/tests/config_test/config/install/config_test.validation.yml +++ /dev/null @@ -1,7 +0,0 @@ -llama: llama -cat: - type: kitten - count: 2 -giraffe: - hum1: hum1 - hum2: hum2 only in patch2: unchanged: --- a/core/modules/config/tests/config_test/config/schema/config_test.schema.yml +++ b/core/modules/config/tests/config_test/config/schema/config_test.schema.yml @@ -158,39 +158,3 @@ config_test.foo: config_test.bar: type: config_test.foo - -config_test.validation: - type: config_object - label: 'Configuration type' - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateMapping] - mapping: - llama: - type: string - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateLlama] - cat: - type: mapping - mapping: - type: - type: string - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateCats] - count: - type: integer - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateCatCount] - giraffe: - type: sequence - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateSequence] - sequence: - type: string - constraints: - Callback: - callback: [\Drupal\config_test\ConfigValidation, validateGiraffes] only in patch2: unchanged: --- a/core/modules/config/tests/config_test/src/ConfigValidation.php +++ /dev/null @@ -1,96 +0,0 @@ -addViolation('no valid llama'); - } - } - - /** - * Validates cats. - * - * @param string $string - * The string to validate. - * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context - * The validation execution context. - */ - public static function validateCats($string, ExecutionContextInterface $context) { - if (!in_array($string, ['kitten', 'cats', 'nyans'])) { - $context->addViolation('no valid cat'); - } - } - - /** - * Validates a number. - * - * @param int $count - * The integer to validate. - * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context - * The validation execution context. - */ - public static function validateCatCount($count, ExecutionContextInterface $context) { - if ($count <= 1) { - $context->addViolation('no enough cats'); - } - } - - /** - * Validates giraffes. - * - * @param string $string - * The string to validate. - * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context - * The validation execution context. - */ - public static function validateGiraffes($string, ExecutionContextInterface $context) { - if (strpos($string, 'hum') !== 0) { - $context->addViolation('Giraffes just hum'); - } - } - - /** - * Validates a mapping. - * - * @param array $mapping - * The data to validate. - * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context - * The validation execution context. - */ - public static function validateMapping($mapping, ExecutionContextInterface $context) { - if ($diff = array_diff(array_keys($mapping), ['llama', 'cat', 'giraffe', '_core'])) { - $context->addViolation('Missing giraffe.'); - } - } - - /** - * Validates a sequence. - * - * @param array $sequence - * The data to validate. - * @param \Symfony\Component\Validator\Context\ExecutionContextInterface $context - * The validation execution context. - */ - public static function validateSequence($sequence, ExecutionContextInterface $context) { - if (isset($sequence['invalid-key'])) { - $context->addViolation('Invalid giraffe key.'); - } - } - -} only in patch2: unchanged: --- a/core/modules/content_moderation/tests/src/Unit/ContentPreprocessTest.php +++ b/core/modules/content_moderation/tests/src/Unit/ContentPreprocessTest.php @@ -5,14 +5,13 @@ use Drupal\content_moderation\ContentPreprocess; use Drupal\Core\Routing\CurrentRouteMatch; use Drupal\node\Entity\Node; -use Drupal\Tests\UnitTestCase; /** * @coversDefaultClass \Drupal\content_moderation\ContentPreprocess * * @group content_moderation */ -class ContentPreprocessTest extends UnitTestCase { +class ContentPreprocessTest extends \PHPUnit_Framework_TestCase { /** * @covers ::isLatestVersionPage only in patch2: unchanged: --- a/core/modules/content_moderation/tests/src/Unit/LatestRevisionCheckTest.php +++ b/core/modules/content_moderation/tests/src/Unit/LatestRevisionCheckTest.php @@ -9,14 +9,13 @@ use Drupal\node\Entity\Node; use Drupal\content_moderation\Access\LatestRevisionCheck; use Drupal\content_moderation\ModerationInformation; -use Drupal\Tests\UnitTestCase; use Symfony\Component\Routing\Route; /** * @coversDefaultClass \Drupal\content_moderation\Access\LatestRevisionCheck * @group content_moderation */ -class LatestRevisionCheckTest extends UnitTestCase { +class LatestRevisionCheckTest extends \PHPUnit_Framework_TestCase { /** * Test the access check of the LatestRevisionCheck service. only in patch2: unchanged: --- a/core/modules/content_moderation/tests/src/Unit/ModerationInformationTest.php +++ b/core/modules/content_moderation/tests/src/Unit/ModerationInformationTest.php @@ -10,14 +10,13 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\content_moderation\ModerationInformation; -use Drupal\Tests\UnitTestCase; use Drupal\workflows\WorkflowInterface; /** * @coversDefaultClass \Drupal\content_moderation\ModerationInformation * @group content_moderation */ -class ModerationInformationTest extends UnitTestCase { +class ModerationInformationTest extends \PHPUnit_Framework_TestCase { /** * Builds a mock user. only in patch2: unchanged: --- a/core/modules/content_moderation/tests/src/Unit/StateTransitionValidationTest.php +++ b/core/modules/content_moderation/tests/src/Unit/StateTransitionValidationTest.php @@ -7,7 +7,6 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Session\AccountInterface; use Drupal\content_moderation\StateTransitionValidation; -use Drupal\Tests\UnitTestCase; use Drupal\workflows\Entity\Workflow; use Drupal\workflows\WorkflowTypeInterface; use Drupal\workflows\WorkflowTypeManager; @@ -17,7 +16,7 @@ * @coversDefaultClass \Drupal\content_moderation\StateTransitionValidation * @group content_moderation */ -class StateTransitionValidationTest extends UnitTestCase { +class StateTransitionValidationTest extends \PHPUnit_Framework_TestCase { /** * Verifies user-aware transition validation. @@ -63,9 +62,6 @@ protected function setUpModerationInformation(ContentEntityInterface $entity) { // mocked. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_manager = $this->prophesize(WorkflowTypeManager::class); only in patch2: unchanged: --- a/core/modules/contextual/contextual.module +++ b/core/modules/contextual/contextual.module @@ -36,7 +36,6 @@ function contextual_toolbar() { '#attributes' => [ 'class' => ['toolbar-icon', 'toolbar-icon-edit'], 'aria-pressed' => 'false', - 'type' => 'button', ], ], '#wrapper_attributes' => [ only in patch2: unchanged: --- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php +++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeCustomFormatter.php @@ -32,18 +32,30 @@ public static function defaultSettings() { * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { - // @todo Evaluate removing this method in - // https://www.drupal.org/node/2793143 to determine if the behavior and - // markup in the base class implementation can be used instead. $elements = []; foreach ($items as $delta => $item) { + $output = ''; if (!empty($item->date)) { /** @var \Drupal\Core\Datetime\DrupalDateTime $date */ $date = $item->date; - $elements[$delta] = $this->buildDate($date); + if ($this->getFieldSetting('datetime_type') == 'date') { + // A date without time will pick up the current time, use the default. + datetime_date_default_time($date); + } + $this->setTimeZone($date); + + $output = $this->formatDate($date); } + $elements[$delta] = [ + '#markup' => $output, + '#cache' => [ + 'contexts' => [ + 'timezone', + ], + ], + ]; } return $elements; only in patch2: unchanged: --- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php +++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeDefaultFormatter.php @@ -3,6 +3,7 @@ namespace Drupal\datetime\Plugin\Field\FieldFormatter; use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; /** @@ -30,6 +31,59 @@ public static function defaultSettings() { /** * {@inheritdoc} */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + + foreach ($items as $delta => $item) { + $output = ''; + $iso_date = ''; + + if ($item->date) { + /** @var \Drupal\Core\Datetime\DrupalDateTime $date */ + $date = $item->date; + + if ($this->getFieldSetting('datetime_type') == 'date') { + // A date without time will pick up the current time, use the default. + datetime_date_default_time($date); + } + + // Create the ISO date in Universal Time. + $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z'; + + $this->setTimeZone($date); + + $output = $this->formatDate($date); + } + + // Display the date using theme datetime. + $elements[$delta] = [ + '#cache' => [ + 'contexts' => [ + 'timezone', + ], + ], + '#theme' => 'time', + '#text' => $output, + '#html' => FALSE, + '#attributes' => [ + 'datetime' => $iso_date, + ], + ]; + if (!empty($item->_attributes)) { + $elements[$delta]['#attributes'] += $item->_attributes; + // Unset field item attributes since they have been included in the + // formatter output and should not be rendered in the field template. + unset($item->_attributes); + } + } + + return $elements; + + } + + /** + * {@inheritdoc} + */ protected function formatDate($date) { $format_type = $this->getSetting('format_type'); $timezone = $this->getSetting('timezone_override') ?: $date->getTimezone()->getName(); only in patch2: unchanged: --- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php +++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimeFormatterBase.php @@ -6,7 +6,6 @@ use Drupal\Core\Datetime\DrupalDateTime; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FormatterBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; @@ -119,30 +118,6 @@ public function settingsSummary() { } /** - * {@inheritdoc} - */ - public function viewElements(FieldItemListInterface $items, $langcode) { - $elements = []; - - foreach ($items as $delta => $item) { - if ($item->date) { - /** @var \Drupal\Core\Datetime\DrupalDateTime $date */ - $date = $item->date; - $elements[$delta] = $this->buildDateWithIsoAttribute($date); - - if (!empty($item->_attributes)) { - $elements[$delta]['#attributes'] += $item->_attributes; - // Unset field item attributes since they have been included in the - // formatter output and should not be rendered in the field template. - unset($item->_attributes); - } - } - } - - return $elements; - } - - /** * Creates a formatted date value as a string. * * @param object $date @@ -192,69 +167,4 @@ protected function getFormatSettings() { return $settings; } - /** - * Creates a render array from a date object. - * - * @param \Drupal\Core\Datetime\DrupalDateTime $date - * A date object. - * - * @return array - * A render array. - */ - protected function buildDate(DrupalDateTime $date) { - if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { - // A date without time will pick up the current time, use the default. - datetime_date_default_time($date); - } - $this->setTimeZone($date); - - $build = [ - '#markup' => $this->formatDate($date), - '#cache' => [ - 'contexts' => [ - 'timezone', - ], - ], - ]; - - return $build; - } - - /** - * Creates a render array from a date object with ISO date attribute. - * - * @param \Drupal\Core\Datetime\DrupalDateTime $date - * A date object. - * - * @return array - * A render array. - */ - protected function buildDateWithIsoAttribute(DrupalDateTime $date) { - if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { - // A date without time will pick up the current time, use the default. - datetime_date_default_time($date); - } - - // Create the ISO date in Universal Time. - $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z'; - - $this->setTimeZone($date); - - $build = [ - '#theme' => 'time', - '#text' => $this->formatDate($date), - '#html' => FALSE, - '#attributes' => [ - 'datetime' => $iso_date, - ], - '#cache' => [ - 'contexts' => [ - 'timezone', - ], - ], - ]; - - return $build; - } - } only in patch2: unchanged: --- a/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php +++ b/core/modules/datetime/src/Plugin/Field/FieldFormatter/DateTimePlainFormatter.php @@ -25,12 +25,27 @@ public function viewElements(FieldItemListInterface $items, $langcode) { $elements = []; foreach ($items as $delta => $item) { + $output = ''; if (!empty($item->date)) { /** @var \Drupal\Core\Datetime\DrupalDateTime $date */ $date = $item->date; - $elements[$delta] = $this->buildDate($date); + if ($this->getFieldSetting('datetime_type') == 'date') { + // A date without time will pick up the current time, use the default. + datetime_date_default_time($date); + } + $this->setTimeZone($date); + + $output = $this->formatDate($date); } + $elements[$delta] = [ + '#cache' => [ + 'contexts' => [ + 'timezone', + ], + ], + '#markup' => $output, + ]; } return $elements; only in patch2: unchanged: --- a/core/modules/datetime_range/src/DateTimeRangeTrait.php +++ b/core/modules/datetime_range/src/DateTimeRangeTrait.php @@ -2,7 +2,8 @@ namespace Drupal\datetime_range; -use Drupal\Core\Field\FieldItemListInterface; +use Drupal\Core\Datetime\DrupalDateTime; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; /** * Provides friendly methods for datetime range. @@ -10,40 +11,68 @@ trait DateTimeRangeTrait { /** - * {@inheritdoc} + * Creates a render array from a date object. + * + * @param \Drupal\Core\Datetime\DrupalDateTime $date + * A date object. + * + * @return array + * A render array. */ - public function viewElements(FieldItemListInterface $items, $langcode) { - $elements = []; - $separator = $this->getSetting('separator'); - - foreach ($items as $delta => $item) { - if (!empty($item->start_date) && !empty($item->end_date)) { - /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */ - $start_date = $item->start_date; - /** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */ - $end_date = $item->end_date; - - if ($start_date->getTimestamp() !== $end_date->getTimestamp()) { - $elements[$delta] = [ - 'start_date' => $this->buildDateWithIsoAttribute($start_date), - 'separator' => ['#plain_text' => ' ' . $separator . ' '], - 'end_date' => $this->buildDateWithIsoAttribute($end_date), - ]; - } - else { - $elements[$delta] = $this->buildDateWithIsoAttribute($start_date); - - if (!empty($item->_attributes)) { - $elements[$delta]['#attributes'] += $item->_attributes; - // Unset field item attributes since they have been included in the - // formatter output and should not be rendered in the field template. - unset($item->_attributes); - } - } - } + protected function buildDate(DrupalDateTime $date) { + if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { + // A date without time will pick up the current time, use the default. + datetime_date_default_time($date); } + $this->setTimeZone($date); - return $elements; + $build = [ + '#plain_text' => $this->formatDate($date), + '#cache' => [ + 'contexts' => [ + 'timezone', + ], + ], + ]; + + return $build; + } + + /** + * Creates a render array from a date object with ISO date attribute. + * + * @param \Drupal\Core\Datetime\DrupalDateTime $date + * A date object. + * + * @return array + * A render array. + */ + protected function buildDateWithIsoAttribute(DrupalDateTime $date) { + if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { + // A date without time will pick up the current time, use the default. + datetime_date_default_time($date); + } + + // Create the ISO date in Universal Time. + $iso_date = $date->format("Y-m-d\TH:i:s") . 'Z'; + + $this->setTimeZone($date); + + $build = [ + '#theme' => 'time', + '#text' => $this->formatDate($date), + '#html' => FALSE, + '#attributes' => [ + 'datetime' => $iso_date, + ], + '#cache' => [ + 'contexts' => [ + 'timezone', + ], + ], + ]; + + return $build; } } only in patch2: unchanged: --- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php +++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeCustomFormatter.php @@ -38,9 +38,6 @@ public static function defaultSettings() { * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { - // @todo Evaluate removing this method in - // https://www.drupal.org/node/2793143 to determine if the behavior and - // markup in the base class implementation can be used instead. $elements = []; $separator = $this->getSetting('separator'); only in patch2: unchanged: --- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php +++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangeDefaultFormatter.php @@ -2,6 +2,7 @@ namespace Drupal\datetime_range\Plugin\Field\FieldFormatter; +use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\datetime\Plugin\Field\FieldFormatter\DateTimeDefaultFormatter; use Drupal\datetime_range\DateTimeRangeTrait; @@ -37,6 +38,42 @@ public static function defaultSettings() { /** * {@inheritdoc} */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + $separator = $this->getSetting('separator'); + + foreach ($items as $delta => $item) { + if (!empty($item->start_date) && !empty($item->end_date)) { + /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */ + $start_date = $item->start_date; + /** @var \Drupal\Core\Datetime\DrupalDateTime $end_date */ + $end_date = $item->end_date; + + if ($start_date->getTimestamp() !== $end_date->getTimestamp()) { + $elements[$delta] = [ + 'start_date' => $this->buildDateWithIsoAttribute($start_date), + 'separator' => ['#plain_text' => ' ' . $separator . ' '], + 'end_date' => $this->buildDateWithIsoAttribute($end_date), + ]; + } + else { + $elements[$delta] = $this->buildDateWithIsoAttribute($start_date); + if (!empty($item->_attributes)) { + $elements[$delta]['#attributes'] += $item->_attributes; + // Unset field item attributes since they have been included in the + // formatter output and should not be rendered in the field template. + unset($item->_attributes); + } + } + } + } + + return $elements; + } + + /** + * {@inheritdoc} + */ public function settingsForm(array $form, FormStateInterface $form_state) { $form = parent::settingsForm($form, $form_state); only in patch2: unchanged: --- a/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php +++ b/core/modules/datetime_range/src/Plugin/Field/FieldFormatter/DateRangePlainFormatter.php @@ -57,13 +57,6 @@ public function viewElements(FieldItemListInterface $items, $langcode) { } else { $elements[$delta] = $this->buildDate($start_date); - - if (!empty($item->_attributes)) { - $elements[$delta]['#attributes'] += $item->_attributes; - // Unset field item attributes since they have been included in the - // formatter output and should not be rendered in the field template. - unset($item->_attributes); - } } } } only in patch2: unchanged: --- a/core/modules/datetime_range/tests/src/Functional/DateRangeFieldTest.php +++ b/core/modules/datetime_range/tests/src/Functional/DateRangeFieldTest.php @@ -170,16 +170,6 @@ public function testDateRangeField() { $output = $this->renderTestEntity($id); $this->assertContains($expected, $output, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', ['%expected' => $expected])); - // Test that allowed markup in custom format is preserved and XSS is - // removed. - $this->displayOptions['settings']['date_format'] = '\\<\\s\\t\\r\\o\\n\\g\\>m/d/Y\\<\\/\\s\\t\\r\\o\\n\\g\\>\\<\\s\\c\\r\\i\\p\\t\\>\\a\\l\\e\\r\\t\\(\\S\\t\\r\\i\\n\\g\\.\\f\\r\\o\\m\\C\\h\\a\\r\\C\\o\\d\\e\\(\\8\\8\\,\\8\\3\\,\\8\\3\\)\\)\\<\\/\\s\\c\\r\\i\\p\\t\\>'; - entity_get_display($this->field->getTargetEntityTypeId(), $this->field->getTargetBundle(), 'full') - ->setComponent($field_name, $this->displayOptions) - ->save(); - $expected = '' . $start_date->format('m/d/Y') . 'alert(String.fromCharCode(88,83,83)) - ' . $end_date->format('m/d/Y') . 'alert(String.fromCharCode(88,83,83))'; - $output = $this->renderTestEntity($id); - $this->assertContains($expected, $output, new FormattableMarkup('Formatted date field using daterange_custom format displayed as %expected.', ['%expected' => $expected])); - // Test formatters when start date and end date are the same $this->drupalGet('entity_test/add'); $value = '2012-12-31 00:00:00'; only in patch2: unchanged: --- a/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php +++ b/core/modules/editor/src/Tests/QuickEditIntegrationLoadingTest.php @@ -89,12 +89,12 @@ public function testUsersWithoutPermission() { $response = $this->drupalPost('editor/' . 'node/1/body/en/full', '', [], ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); $this->assertResponse(403); if (!$user->hasPermission('access in-place editing')) { - $message = "The 'access in-place editing' permission is required."; + $message = "A fatal error occurred: The 'access in-place editing' permission is required."; + $this->assertIdentical(Json::encode(['message' => $message]), $response); } else { - $message = ''; + $this->assertIdentical('{}', $response); } - $this->assertIdentical(Json::encode(['message' => $message]), $response); } } only in patch2: unchanged: --- a/core/modules/editor/tests/src/Kernel/QuickEditIntegrationTest.php +++ b/core/modules/editor/tests/src/Kernel/QuickEditIntegrationTest.php @@ -9,7 +9,7 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\quickedit\MetadataGenerator; use Drupal\Tests\quickedit\Kernel\QuickEditTestBase; -use Drupal\quickedit_test\MockQuickEditEntityFieldAccessCheck; +use Drupal\quickedit_test\MockEditEntityFieldAccessCheck; use Drupal\editor\EditorController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; @@ -52,7 +52,7 @@ class QuickEditIntegrationTest extends QuickEditTestBase { /** * The access checker object to be used by the metadata generator object. * - * @var \Drupal\quickedit\Access\QuickEditEntityFieldAccessCheckInterface + * @var \Drupal\quickedit\Access\EditEntityFieldAccessCheckInterface */ protected $accessChecker; @@ -165,7 +165,7 @@ public function testEditorSelection() { */ public function testMetadata() { $this->editorManager = $this->container->get('plugin.manager.quickedit.editor'); - $this->accessChecker = new MockQuickEditEntityFieldAccessCheck(); + $this->accessChecker = new MockEditEntityFieldAccessCheck(); $this->editorSelector = $this->container->get('quickedit.editor.selector'); $this->metadataGenerator = new MetadataGenerator($this->accessChecker, $this->editorSelector, $this->editorManager); only in patch2: unchanged: --- a/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php @@ -34,7 +34,7 @@ class EntityReferenceRelationshipTest extends ViewsKernelTestBase { 'test_entity_reference_entity_test_mul_view', 'test_entity_reference_reverse_entity_test_mul_view', 'test_entity_reference_group_by_empty_relationships', - ]; + ]; /** * Modules to install. only in patch2: unchanged: --- a/core/modules/field/tests/src/Kernel/Timestamp/TimestampItemTest.php +++ /dev/null @@ -1,91 +0,0 @@ -fieldStorage = FieldStorageConfig::create([ - 'field_name' => 'field_timestamp', - 'type' => 'timestamp', - 'entity_type' => 'entity_test', - ]); - $this->fieldStorage->save(); - $this->field = FieldConfig::create([ - 'field_storage' => $this->fieldStorage, - 'bundle' => 'entity_test', - ]); - $this->field->save(); - } - - /** - * Tests using entity fields of the datetime field type. - */ - public function testDateTime() { - // Verify entity creation. - $entity = EntityTest::create(); - $value = 1488914208; - $entity->field_timestamp = $value; - $entity->name->value = $this->randomMachineName(); - $this->entityValidateAndSave($entity); - - // Verify entity has been created properly. - $id = $entity->id(); - $entity = EntityTest::load($id); - $this->assertTrue($entity->field_timestamp instanceof FieldItemListInterface, 'Field implements interface.'); - $this->assertTrue($entity->field_timestamp[0] instanceof FieldItemInterface, 'Field item implements interface.'); - $this->assertEquals($entity->field_timestamp->value, $value); - $this->assertEquals($entity->field_timestamp[0]->value, $value); - - // Verify changing the date value. - $new_value = 1488914000; - $entity->field_timestamp->value = $new_value; - $this->assertEquals($entity->field_timestamp->value, $new_value); - - // Read changed entity and assert changed values. - $this->entityValidateAndSave($entity); - $entity = EntityTest::load($id); - $this->assertEquals($entity->field_timestamp->value, $new_value); - - // Test sample item generation. - $entity = EntityTest::create(); - $entity->field_timestamp->generateSampleItems(); - $this->entityValidateAndSave($entity); - - // Ensure there is sample value a generated for the field. - $this->assertNotNull($entity->field_timestamp->value); - } - -} only in patch2: unchanged: --- a/core/modules/field_ui/src/Tests/FieldUIDeleteTest.php +++ b/core/modules/field_ui/src/Tests/FieldUIDeleteTest.php @@ -5,7 +5,6 @@ use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\simpletest\WebTestBase; -use Drupal\views\Entity\View; use Drupal\views\Tests\ViewTestData; /** @@ -75,13 +74,6 @@ public function testDeleteField() { \Drupal::service('module_installer')->install(['views']); ViewTestData::createTestViews(get_class($this), ['field_test_views']); - $view = View::load('test_view_field_delete'); - $this->assertNotNull($view); - $this->assertTrue($view->status()); - // Test that the View depends on the field. - $dependencies = $view->getDependencies() + ['config' => []]; - $this->assertTrue(in_array("field.storage.node.$field_name", $dependencies['config'])); - // Check the config dependencies of the first field, the field storage must // not be shown as being deleted yet. $this->drupalGet("$bundle_path1/fields/node.$type_name1.$field_name/delete"); @@ -99,13 +91,13 @@ public function testDeleteField() { // Check the config dependencies of the first field. $this->drupalGet("$bundle_path2/fields/node.$type_name2.$field_name/delete"); - $this->assertText(t('The listed configuration will be updated.')); + $this->assertText(t('The listed configuration will be deleted.')); $this->assertText(t('View')); $this->assertText('test_view_field_delete'); $xml = $this->cssSelect('#edit-entity-deletes'); - // Test that nothing is scheduled for deletion. - $this->assertFalse(isset($xml[0]), 'The field currently being deleted is not shown in the entity deletions.'); + // Remove the wrapping HTML. + $this->assertIdentical(FALSE, strpos($xml[0]->asXml(), $field_label), 'The currently being deleted field is not shown in the entity deletions.'); // Delete the second field. $this->fieldUIDeleteField($bundle_path2, "node.$type_name2.$field_name", $field_label, $type_name2); @@ -114,14 +106,6 @@ public function testDeleteField() { $this->assertNull(FieldConfig::loadByName('node', $type_name2, $field_name), 'Field was deleted.'); // Check that the field storage was deleted too. $this->assertNull(FieldStorageConfig::loadByName('node', $field_name), 'Field storage was deleted.'); - - // Test that the View isn't deleted and has been disabled. - $view = View::load('test_view_field_delete'); - $this->assertNotNull($view); - $this->assertFalse($view->status()); - // Test that the View no longer depends on the deleted field. - $dependencies = $view->getDependencies() + ['config' => []]; - $this->assertFalse(in_array("field.storage.node.$field_name", $dependencies['config'])); } } only in patch2: unchanged: --- a/core/modules/file/tests/src/Functional/FileFieldTestBase.php +++ b/core/modules/file/tests/src/Functional/FileFieldTestBase.php @@ -259,7 +259,7 @@ public function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) /** * Asserts that a file exists physically on disk. * - * Overrides PHPUnit\Framework\Assert::assertFileExists() to also work with + * Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with * file entities. * * @param \Drupal\File\FileInterface|string $file @@ -286,7 +286,7 @@ public function assertFileEntryExists($file, $message = NULL) { /** * Asserts that a file does not exist on disk. * - * Overrides PHPUnit\Framework\Assert::assertFileExists() to also work with + * Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with * file entities. * * @param \Drupal\File\FileInterface|string $file only in patch2: unchanged: --- a/core/modules/forum/src/Form/ContainerForm.php +++ b/core/modules/forum/src/Form/ContainerForm.php @@ -20,8 +20,9 @@ class ContainerForm extends ForumForm { * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { + $taxonomy_term = $this->entity; // Build the bulk of the form from the parent forum form. - $form = parent::form($form, $form_state); + $form = parent::form($form, $form_state, $taxonomy_term); // Set the title and description of the name field. $form['name']['#title'] = $this->t('Container name'); only in patch2: unchanged: --- a/core/modules/forum/src/Form/ForumForm.php +++ b/core/modules/forum/src/Form/ForumForm.php @@ -29,8 +29,9 @@ class ForumForm extends TermForm { * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { + $taxonomy_term = $this->entity; // Build the bulk of the form from the parent taxonomy term form. - $form = parent::form($form, $form_state); + $form = parent::form($form, $form_state, $taxonomy_term); // Set the title and description of the name field. $form['name']['#title'] = $this->t('Forum name'); @@ -47,7 +48,7 @@ public function form(array $form, FormStateInterface $form_state) { // Our parent field is different to the taxonomy term. $form['parent']['#tree'] = TRUE; - $form['parent'][0] = $this->forumParentSelect($this->entity->id(), $this->t('Parent')); + $form['parent'][0] = $this->forumParentSelect($taxonomy_term->id(), $this->t('Parent')); $form['#theme_wrappers'] = ['form__forum']; $this->forumFormType = $this->t('forum'); only in patch2: unchanged: --- a/core/modules/hal/tests/src/Functional/EntityResource/Editor/EditorHalJsonAnonTest.php +++ /dev/null @@ -1,30 +0,0 @@ -serializer->encode($normalization, static::$format); - // DX: 422 when incorrect entity type bundle is specified. + // DX: 400 when incorrect entity type bundle is specified. $response = $this->request($method, $url, $request_options); - $this->assertResourceErrorResponse(422, 'No entity type(s) specified', $response); + $this->assertResourceErrorResponse(400, 'No entity type(s) specified', $response); unset($normalization['_links']['type']); $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - // DX: 422 when no entity type bundle is specified. + // DX: 400 when no entity type bundle is specified. $response = $this->request($method, $url, $request_options); - $this->assertResourceErrorResponse(422, 'The type link relation must be specified.', $response); + $this->assertResourceErrorResponse(400, 'The type link relation must be specified.', $response); } } only in patch2: unchanged: --- a/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php +++ b/core/modules/hal/tests/src/Functional/EntityResource/Node/NodeHalJsonAnonTest.php @@ -59,20 +59,20 @@ protected function getExpectedNormalizedEntity() { 'type' => [ 'href' => $this->baseUrl . '/rest/type/node/camelids', ], - $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ + $this->baseUrl . '/rest/relation/node/camelids/uid' => [ [ 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', + 'lang' => 'en', ], ], - $this->baseUrl . '/rest/relation/node/camelids/uid' => [ + $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ [ 'href' => $this->baseUrl . '/user/' . $author->id() . '?_format=hal_json', - 'lang' => 'en', ], ], ], '_embedded' => [ - $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ + $this->baseUrl . '/rest/relation/node/camelids/uid' => [ [ '_links' => [ 'self' => [ @@ -85,9 +85,10 @@ protected function getExpectedNormalizedEntity() { 'uuid' => [ ['value' => $author->uuid()] ], + 'lang' => 'en', ], ], - $this->baseUrl . '/rest/relation/node/camelids/uid' => [ + $this->baseUrl . '/rest/relation/node/camelids/revision_uid' => [ [ '_links' => [ 'self' => [ @@ -100,7 +101,6 @@ protected function getExpectedNormalizedEntity() { 'uuid' => [ ['value' => $author->uuid()] ], - 'lang' => 'en', ], ], ], only in patch2: unchanged: --- a/core/modules/hal/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetHalJsonAnonTest.php +++ /dev/null @@ -1,30 +0,0 @@ - $dimensions['width'], '#height' => $dimensions['height'], '#attributes' => $variables['attributes'], + '#uri' => $style->buildUrl($variables['uri']), '#style_name' => $variables['style_name'], ]; - // If the current image toolkit supports this file type, prepare the URI for - // the derivative image. If not, just use the original image resized to the - // dimensions specified by the style. - if ($style->supportsUri($variables['uri'])) { - $variables['image']['#uri'] = $style->buildUrl($variables['uri']); - } - else { - $variables['image']['#uri'] = $variables['uri']; - // Don't render the image by default, but allow other preprocess functions - // to override that if they need to. - $variables['image']['#access'] = FALSE; - - // Inform the site builders why their image didn't work. - \Drupal::logger('image')->warning('Could not apply @style image style to @uri because the style does not support it.', [ - '@style' => $style->label(), - '@uri' => $variables['uri'], - ]); - } - if (isset($variables['alt']) || array_key_exists('alt', $variables)) { $variables['image']['#alt'] = $variables['alt']; } only in patch2: unchanged: --- a/core/modules/image/src/Entity/ImageStyle.php +++ b/core/modules/image/src/Entity/ImageStyle.php @@ -14,11 +14,9 @@ use Drupal\image\ImageStyleInterface; use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\UrlHelper; -use Drupal\Component\Utility\Unicode; use Drupal\Core\StreamWrapper\StreamWrapperInterface; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Drupal\Core\Entity\Entity\EntityViewDisplay; - /** * Defines an image style configuration entity. * @@ -276,8 +274,9 @@ public function flush($path = NULL) { * {@inheritdoc} */ public function createDerivative($original_uri, $derivative_uri) { + // If the source file doesn't exist, return FALSE without creating folders. - $image = $this->getImageFactory()->get($original_uri); + $image = \Drupal::service('image.factory')->get($original_uri); if (!$image->isValid()) { return FALSE; } @@ -344,18 +343,6 @@ public function deleteImageEffect(ImageEffectInterface $effect) { /** * {@inheritdoc} */ - public function supportsUri($uri) { - // Only support the URI if its extension is supported by the current image - // toolkit. - return in_array( - Unicode::strtolower(pathinfo($uri, PATHINFO_EXTENSION)), - $this->getImageFactory()->getSupportedExtensions() - ); - } - - /** - * {@inheritdoc} - */ public function getEffect($effect) { return $this->getEffects()->get($effect); } @@ -422,16 +409,6 @@ protected function getImageEffectPluginManager() { } /** - * Returns the image factory. - * - * @return \Drupal\Core\Image\ImageFactory - * The image factory. - */ - protected function getImageFactory() { - return \Drupal::service('image.factory'); - } - - /** * Gets the Drupal private key. * * @return string only in patch2: unchanged: --- a/core/modules/image/src/ImageStyleInterface.php +++ b/core/modules/image/src/ImageStyleInterface.php @@ -194,15 +194,4 @@ public function addImageEffect(array $configuration); */ public function deleteImageEffect(ImageEffectInterface $effect); - /** - * Determines if this style can be applied to a given image. - * - * @param string $uri - * The URI of the image. - * - * @return bool - * TRUE if the image is supported, FALSE otherwise. - */ - public function supportsUri($uri); - } only in patch2: unchanged: --- a/core/modules/image/tests/src/Kernel/ImageFormatterTest.php +++ b/core/modules/image/tests/src/Kernel/ImageFormatterTest.php @@ -7,8 +7,6 @@ use Drupal\entity_test\Entity\EntityTest; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; -use Drupal\file\Entity\File; -use Drupal\image\Entity\ImageStyle; use Drupal\Tests\field\Kernel\FieldKernelTestBase; /** @@ -101,89 +99,4 @@ public function testImageFormatterCacheTags() { $this->assertEquals($entity->{$this->fieldName}[1]->entity->getCacheTags(), $build[$this->fieldName][1]['#cache']['tags'], 'Second image cache tags is as expected'); } - /** - * Tests ImageFormatter's handling of SVG images. - * - * @requires extension gd - */ - public function testImageFormatterSvg() { - // Install the default image styles. - $this->installConfig(['image']); - - /** @var \Drupal\Core\Render\RendererInterface $renderer */ - $renderer = $this->container->get('renderer'); - - $png = File::create([ - 'uri' => 'public://test-image.png', - ]); - $png->save(); - - // We need to create an actual empty PNG, or the GD toolkit will not - // consider the image valid. - $png_resource = imagecreate(300, 300); - imagefill($png_resource, 0, 0, imagecolorallocate($png_resource, 0, 0, 0)); - imagepng($png_resource, $png->getFileUri()); - - $svg = File::create([ - 'uri' => 'public://test-image.svg', - ]); - $svg->save(); - // We don't have to put any real SVG data in here, because the GD toolkit - // won't be able to load it anyway. - touch($svg->getFileUri()); - - $entity = EntityTest::create([ - 'name' => $this->randomMachineName(), - $this->fieldName => [$png, $svg], - ]); - $entity->save(); - - // Ensure that the display is using the medium image style. - $component = $this->display->getComponent($this->fieldName); - $component['settings']['image_style'] = 'medium'; - $this->display->setComponent($this->fieldName, $component)->save(); - - $build = $this->display->build($entity); - - // The first image is a PNG, so it is supported by the GD image toolkit. - // The image style should be applied with its cache tags, image derivative - // computed with its URI and dimensions. - $this->assertCacheTags($build[$this->fieldName][0], ImageStyle::load('medium')->getCacheTags()); - $renderer->renderRoot($build[$this->fieldName][0]); - $this->assertEquals('medium', $build[$this->fieldName][0]['#image_style']); - // We check that the image URL contains the expected style directory - // structure. - $this->assertTrue(strpos($build[$this->fieldName][0]['#markup'], 'styles/medium/public/test-image.png') !== FALSE); - $this->assertTrue(strpos($build[$this->fieldName][0]['#markup'], 'width="220"') !== FALSE); - $this->assertTrue(strpos($build[$this->fieldName][0]['#markup'], 'height="220"') !== FALSE); - - // The second image is an SVG, which is not supported by the GD toolkit. - // The image style should still be applied with its cache tags, but image - // derivative will not be available so tag will point to the original - // image. - $this->assertCacheTags($build[$this->fieldName][1], ImageStyle::load('medium')->getCacheTags()); - $renderer->renderRoot($build[$this->fieldName][1]); - $this->assertEquals('medium', $build[$this->fieldName][1]['#image_style']); - // We check that the image URL does not contain the style directory - // structure. - $this->assertFalse(strpos($build[$this->fieldName][1]['#markup'], 'styles/medium/public/test-image.svg')); - // Since we did not store original image dimensions, width and height - // HTML attributes will not be present. - $this->assertFalse(strpos($build[$this->fieldName][1]['#markup'], 'width')); - $this->assertFalse(strpos($build[$this->fieldName][1]['#markup'], 'height')); - } - - /** - * Asserts that a renderable array has a set of cache tags. - * - * @param array $renderable - * The renderable array. Must have a #cache[tags] element. - * @param array $cache_tags - * The expected cache tags. - */ - protected function assertCacheTags(array $renderable, array $cache_tags) { - $diff = array_diff($cache_tags, $renderable['#cache']['tags']); - $this->assertEmpty($diff); - } - } only in patch2: unchanged: --- a/core/modules/language/config/schema/language.schema.yml +++ b/core/modules/language/config/schema/language.schema.yml @@ -131,11 +131,3 @@ condition.plugin.language: type: sequence sequence: type: string - -field.widget.settings.language_select: - type: mapping - label: 'Language format settings' - mapping: - include_locked: - type: boolean - label: 'Include locked languages' only in patch2: unchanged: --- a/core/modules/language/language.post_update.php +++ /dev/null @@ -1,28 +0,0 @@ -get('content'); - $changed = FALSE; - foreach (array_keys($content) as $element) { - if (isset($content[$element]['type']) && $content[$element]['type'] == 'language_select') { - $content[$element]['settings']['include_locked'] = TRUE; - $changed = TRUE; - } - } - if ($changed) { - $display_form->set('content', $content); - $display_form->save(); - } - } -} only in patch2: unchanged: --- a/core/modules/language/src/LanguageNegotiatorInterface.php +++ b/core/modules/language/src/LanguageNegotiatorInterface.php @@ -91,6 +91,7 @@ * } * } * } + * ?> * @endcode * * For more information, see only in patch2: unchanged: --- a/core/modules/language/src/Tests/Update/LanguageSelectWidgetUpdateTest.php +++ /dev/null @@ -1,40 +0,0 @@ -databaseDumpFiles = [ - __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz', - ]; - } - - /** - * Tests language_post_update_language_select_widget(). - */ - public function testLanguagePostUpdateLanguageSelectWidget() { - // Tests before the update. - $content_before = EntityFormDisplay::load('node.page.default')->get('content'); - $this->assertEqual([], $content_before['langcode']['settings']); - - // Run the update. - $this->runUpdates(); - - // Tests after the update. - $content_after = EntityFormDisplay::load('node.page.default')->get('content'); - $this->assertEqual(['include_locked' => TRUE], $content_after['langcode']['settings']); - } - -} only in patch2: unchanged: --- a/core/modules/language/tests/src/Kernel/LanguageSelectWidgetTest.php +++ /dev/null @@ -1,77 +0,0 @@ -installEntitySchema('entity_test'); - $this->installEntitySchema('user'); - - $storage = $this->container->get('entity_type.manager')->getStorage('entity_form_display'); - $this->entityFormDisplay = $storage->create([ - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'mode' => 'default', - 'status' => TRUE, - ]); - } - - /** - * Tests the widget with the locked languages. - */ - public function testWithIncludedLockedLanguage() { - $this->entityFormDisplay->setComponent('langcode', [ - 'type' => 'language_select', - ])->save(); - $entity = EntityTest::create(['name' => $this->randomString()]); - $form = $this->container->get('entity.form_builder')->getForm($entity); - $options = array_keys($form['langcode']['widget'][0]['value']['#options']); - $this->assertSame(['en', 'und', 'zxx'], $options); - } - - /** - * Test the widget without the locked languages. - */ - public function testWithoutIncludedLockedLanguage() { - $this->entityFormDisplay->setComponent('langcode', [ - 'type' => 'language_select', - 'settings' => ['include_locked' => FALSE], - ])->save(); - $entity = EntityTest::create(['name' => $this->randomString()]); - $form = $this->container->get('entity.form_builder')->getForm($entity); - $options = array_keys($form['langcode']['widget'][0]['value']['#options']); - $this->assertSame(['en'], $options); - } - -} only in patch2: unchanged: --- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php +++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php @@ -175,7 +175,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen '#element_validate' => [[get_called_class(), 'validateUriElement']], '#maxlength' => 2048, '#required' => $element['#required'], - '#link_type' => $this->getFieldSetting('link_type'), ]; // If the field is configured to support internal links, it cannot use the only in patch2: unchanged: --- a/core/modules/link/tests/src/Functional/LinkFieldTest.php +++ b/core/modules/link/tests/src/Functional/LinkFieldTest.php @@ -610,49 +610,6 @@ public function testLinkSeparateFormatter() { } /** - * Test '#link_type' property exists on 'link_default' widget. - * - * Make sure the 'link_default' widget exposes a '#link_type' property on - * its element. Modules can use it to understand if a text form element is - * a link and also which LinkItemInterface::LINK_* is (EXTERNAL, GENERIC, - * INTERNAL). - */ - public function testLinkTypeOnLinkWidget() { - - $link_type = LinkItemInterface::LINK_EXTERNAL; - $field_name = Unicode::strtolower($this->randomMachineName()); - - // Create a field with settings to validate. - $this->fieldStorage = FieldStorageConfig::create([ - 'field_name' => $field_name, - 'entity_type' => 'entity_test', - 'type' => 'link', - 'cardinality' => 1, - ]); - $this->fieldStorage->save(); - FieldConfig::create([ - 'field_storage' => $this->fieldStorage, - 'label' => 'Read more about this entity', - 'bundle' => 'entity_test', - 'settings' => [ - 'title' => DRUPAL_OPTIONAL, - 'link_type' => $link_type, - ], - ])->save(); - - $this->container->get('entity.manager') - ->getStorage('entity_form_display') - ->load('entity_test.entity_test.default') - ->setComponent($field_name, [ - 'type' => 'link_default', - ]) - ->save(); - - $form = \Drupal::service('entity.form_builder')->getForm(EntityTest::create()); - $this->assertEqual($form[$field_name]['widget'][0]['uri']['#link_type'], $link_type); - } - - /** * Renders a test_entity and returns the output. * * @param int $id only in patch2: unchanged: --- a/core/modules/locale/src/StringDatabaseStorage.php +++ b/core/modules/locale/src/StringDatabaseStorage.php @@ -3,7 +3,6 @@ namespace Drupal\locale; use Drupal\Core\Database\Connection; -use Drupal\Core\Database\Query\Condition; /** * Defines a class to store localized strings in the database. @@ -417,7 +416,7 @@ protected function dbStringSelect(array $conditions, array $options = []) { elseif ($table_alias == 't' && $join === 'leftJoin') { // Conditions for target fields when doing an outer join only make // sense if we add also OR field IS NULL. - $query->condition((new Condition('OR')) + $query->condition(db_or() ->condition($field_alias, (array) $value, 'IN') ->isNull($field_alias) ); @@ -430,7 +429,7 @@ protected function dbStringSelect(array $conditions, array $options = []) { // Process other options, string filter, query limit, etc. if (!empty($options['filters'])) { if (count($options['filters']) > 1) { - $filter = new Condition('OR'); + $filter = db_or(); $query->condition($filter); } else { only in patch2: unchanged: --- a/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php +++ b/core/modules/migrate/tests/src/Unit/Event/EventBaseTest.php @@ -3,13 +3,12 @@ namespace Drupal\Tests\migrate\Unit\Event; use Drupal\migrate\Event\EventBase; -use Drupal\Tests\UnitTestCase; /** * @coversDefaultClass \Drupal\migrate\Event\EventBase * @group migrate */ -class EventBaseTest extends UnitTestCase { +class EventBaseTest extends \PHPUnit_Framework_TestCase { /** * Test getMigration method. only in patch2: unchanged: --- a/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php +++ b/core/modules/migrate/tests/src/Unit/Event/MigrateImportEventTest.php @@ -3,13 +3,12 @@ namespace Drupal\Tests\migrate\Unit\Event; use Drupal\migrate\Event\MigrateImportEvent; -use Drupal\Tests\UnitTestCase; /** * @coversDefaultClass \Drupal\migrate\Event\MigrateImportEvent * @group migrate */ -class MigrateImportEventTest extends UnitTestCase { +class MigrateImportEventTest extends \PHPUnit_Framework_TestCase { /** * Test getMigration method. only in patch2: unchanged: --- a/core/modules/node/node.permissions.yml +++ b/core/modules/node/node.permissions.yml @@ -18,13 +18,12 @@ view own unpublished content: title: 'View own unpublished content' view all revisions: title: 'View all revisions' - description: 'To view a revision, you also need permission to view the content item.' revert all revisions: title: 'Revert all revisions' - description: 'To revert a revision, you also need permission to edit the content item.' + description: 'Role requires permission view revisions and edit rights for nodes in question or administer nodes.' delete all revisions: title: 'Delete all revisions' - description: 'To delete a revision, you also need permission to delete the content item.' + description: 'Role requires permission to view revisions and delete rights for nodes in question or administer nodes.' permission_callbacks: - \Drupal\node\NodePermissions::nodeTypePermissions only in patch2: unchanged: --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -2,7 +2,9 @@ namespace Drupal\node\Entity; -use Drupal\Core\Entity\EditorialContentEntityBase; +use Drupal\Core\Entity\ContentEntityBase; +use Drupal\Core\Entity\EntityChangedTrait; +use Drupal\Core\Entity\EntityPublishedTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; @@ -59,11 +61,6 @@ * "published" = "status", * "uid" = "uid", * }, - * revision_metadata_keys = { - * "revision_user" = "revision_uid", - * "revision_created" = "revision_timestamp", - * "revision_log_message" = "revision_log" - * }, * bundle_entity_type = "node_type", * field_ui_base_route = "entity.node_type.edit_form", * common_reference_target = TRUE, @@ -77,7 +74,10 @@ * } * ) */ -class Node extends EditorialContentEntityBase implements NodeInterface { +class Node extends ContentEntityBase implements NodeInterface { + + use EntityChangedTrait; + use EntityPublishedTrait; /** * Whether the node is being previewed or not. @@ -281,6 +281,21 @@ public function setOwner(UserInterface $account) { /** * {@inheritdoc} */ + public function getRevisionCreationTime() { + return $this->get('revision_timestamp')->value; + } + + /** + * {@inheritdoc} + */ + public function setRevisionCreationTime($timestamp) { + $this->set('revision_timestamp', $timestamp); + return $this; + } + + /** + * {@inheritdoc} + */ public function getRevisionAuthor() { return $this->getRevisionUser(); } @@ -288,6 +303,13 @@ public function getRevisionAuthor() { /** * {@inheritdoc} */ + public function getRevisionUser() { + return $this->get('revision_uid')->entity; + } + + /** + * {@inheritdoc} + */ public function setRevisionAuthorId($uid) { $this->setRevisionUserId($uid); return $this; @@ -296,8 +318,47 @@ public function setRevisionAuthorId($uid) { /** * {@inheritdoc} */ + public function setRevisionUser(UserInterface $user) { + $this->set('revision_uid', $user); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRevisionUserId() { + return $this->get('revision_uid')->entity->id(); + } + + /** + * {@inheritdoc} + */ + public function setRevisionUserId($user_id) { + $this->set('revision_uid', $user_id); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRevisionLogMessage() { + return $this->get('revision_log')->value; + } + + /** + * {@inheritdoc} + */ + public function setRevisionLogMessage($revision_log_message) { + $this->set('revision_log', $revision_log_message); + return $this; + } + + /** + * {@inheritdoc} + */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); + $fields += static::publishedBaseFieldDefinitions($entity_type); $fields['title'] = BaseFieldDefinition::create('string') ->setLabel(t('Title')) @@ -389,6 +450,32 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ]) ->setDisplayConfigurable('form', TRUE); + $fields['revision_timestamp'] = BaseFieldDefinition::create('created') + ->setLabel(t('Revision timestamp')) + ->setDescription(t('The time that the current revision was created.')) + ->setQueryable(FALSE) + ->setRevisionable(TRUE); + + $fields['revision_uid'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(t('Revision user ID')) + ->setDescription(t('The user ID of the author of the current revision.')) + ->setSetting('target_type', 'user') + ->setQueryable(FALSE) + ->setRevisionable(TRUE); + + $fields['revision_log'] = BaseFieldDefinition::create('string_long') + ->setLabel(t('Revision log message')) + ->setDescription(t('Briefly describe the changes you have made.')) + ->setRevisionable(TRUE) + ->setDefaultValue('') + ->setDisplayOptions('form', [ + 'type' => 'string_textarea', + 'weight' => 25, + 'settings' => [ + 'rows' => 4, + ], + ]); + $fields['revision_translation_affected'] = BaseFieldDefinition::create('boolean') ->setLabel(t('Revision translation affected')) ->setDescription(t('Indicates if the last edit of a translation belongs to current revision.')) only in patch2: unchanged: --- a/core/modules/node/src/NodePermissions.php +++ b/core/modules/node/src/NodePermissions.php @@ -62,15 +62,14 @@ protected function buildPermissions(NodeType $type) { ], "view $type_id revisions" => [ 'title' => $this->t('%type_name: View revisions', $type_params), - 'description' => t('To view a revision, you also need permission to view the content item.'), ], "revert $type_id revisions" => [ 'title' => $this->t('%type_name: Revert revisions', $type_params), - 'description' => t('To revert a revision, you also need permission to edit the content item.'), + 'description' => t('Role requires permission view revisions and edit rights for nodes in question, or administer nodes.'), ], "delete $type_id revisions" => [ 'title' => $this->t('%type_name: Delete revisions', $type_params), - 'description' => $this->t('To delete a revision, you also need permission to delete the content item.'), + 'description' => $this->t('Role requires permission to view revisions and delete rights for nodes in question, or administer nodes.'), ], ]; } only in patch2: unchanged: --- a/core/modules/node/src/Plugin/views/filter/Access.php +++ b/core/modules/node/src/Plugin/views/filter/Access.php @@ -2,7 +2,6 @@ namespace Drupal\node\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\filter\FilterPluginBase; @@ -28,10 +27,10 @@ public function query() { $account = $this->view->getUser(); if (!$account->hasPermission('bypass node access')) { $table = $this->ensureMyTable(); - $grants = new Condition('OR'); + $grants = db_or(); foreach (node_access_grants('view', $account) as $realm => $gids) { foreach ($gids as $gid) { - $grants->condition((new Condition('AND')) + $grants->condition(db_and() ->condition($table . '.gid', $gid) ->condition($table . '.realm', $realm) ); only in patch2: unchanged: --- a/core/modules/quickedit/quickedit.services.yml +++ b/core/modules/quickedit/quickedit.services.yml @@ -3,7 +3,7 @@ services: class: Drupal\quickedit\Plugin\InPlaceEditorManager parent: default_plugin_manager access_check.quickedit.entity_field: - class: Drupal\quickedit\Access\QuickEditEntityFieldAccessCheck + class: Drupal\quickedit\Access\EditEntityFieldAccessCheck tags: - { name: access_check, applies_to: _access_quickedit_entity_field } quickedit.editor.selector: only in patch2: unchanged: --- a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php +++ b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheck.php @@ -2,9 +2,61 @@ namespace Drupal\quickedit\Access; +use Drupal\Core\Access\AccessResult; +use Drupal\Core\Routing\Access\AccessInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Entity\EntityInterface; + /** - * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. + * Access check for editing entity fields. */ -class EditEntityFieldAccessCheck extends QuickEditEntityFieldAccessCheck { +class EditEntityFieldAccessCheck implements AccessInterface, EditEntityFieldAccessCheckInterface { + + /** + * Checks Quick Edit access to the field. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity containing the field. + * @param string $field_name + * The field name. + * @param string $langcode + * The langcode. + * @param \Drupal\Core\Session\AccountInterface $account + * The currently logged in account. + * + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. + * + * @todo Use the $account argument: https://www.drupal.org/node/2266809. + */ + public function access(EntityInterface $entity, $field_name, $langcode, AccountInterface $account) { + if (!$this->validateRequestAttributes($entity, $field_name, $langcode)) { + return AccessResult::forbidden(); + } + + return $this->accessEditEntityField($entity, $field_name); + } + + /** + * {@inheritdoc} + */ + public function accessEditEntityField(EntityInterface $entity, $field_name) { + return $entity->access('update', NULL, TRUE)->andIf($entity->get($field_name)->access('edit', NULL, TRUE)); + } + + /** + * Validates request attributes. + */ + protected function validateRequestAttributes(EntityInterface $entity, $field_name, $langcode) { + // Validate the field name and language. + if (!$field_name || !$entity->hasField($field_name)) { + return FALSE; + } + if (!$langcode || !$entity->hasTranslation($langcode)) { + return FALSE; + } + + return TRUE; + } } only in patch2: unchanged: --- a/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php +++ b/core/modules/quickedit/src/Access/EditEntityFieldAccessCheckInterface.php @@ -2,9 +2,24 @@ namespace Drupal\quickedit\Access; +use Drupal\Core\Entity\EntityInterface; + /** - * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. + * Access check for editing entity fields. */ -interface EditEntityFieldAccessCheckInterface extends QuickEditEntityFieldAccessCheckInterface { +interface EditEntityFieldAccessCheckInterface { + + /** + * Checks access to edit the requested field of the requested entity. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity. + * @param string $field_name + * The field name. + * + * @return \Drupal\Core\Access\AccessResultInterface + * The access result. + */ + public function accessEditEntityField(EntityInterface $entity, $field_name); } only in patch2: unchanged: --- a/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheck.php +++ /dev/null @@ -1,62 +0,0 @@ -validateRequestAttributes($entity, $field_name, $langcode)) { - return AccessResult::forbidden(); - } - - return $this->accessEditEntityField($entity, $field_name); - } - - /** - * {@inheritdoc} - */ - public function accessEditEntityField(EntityInterface $entity, $field_name) { - return $entity->access('update', NULL, TRUE)->andIf($entity->get($field_name)->access('edit', NULL, TRUE)); - } - - /** - * Validates request attributes. - */ - protected function validateRequestAttributes(EntityInterface $entity, $field_name, $langcode) { - // Validate the field name and language. - if (!$field_name || !$entity->hasField($field_name)) { - return FALSE; - } - if (!$langcode || !$entity->hasTranslation($langcode)) { - return FALSE; - } - - return TRUE; - } - -} only in patch2: unchanged: --- a/core/modules/quickedit/src/Access/QuickEditEntityFieldAccessCheckInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -accessChecker = $access_checker; $this->editorSelector = $editor_selector; $this->editorManager = $editor_manager; only in patch2: unchanged: --- a/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php +++ b/core/modules/quickedit/src/Tests/QuickEditLoadingTest.php @@ -115,12 +115,12 @@ public function testUserWithoutPermission() { $this->assertIdentical(Json::encode(['message' => "The 'access in-place editing' permission is required."]), $response); $this->assertResponse(403); - // Quick Edit's JavaScript would never hit these endpoints if the metadata + // Quick Edit's JavaScript would SearchRankingTestnever hit these endpoints if the metadata // was empty as above, but we need to make sure that malicious users aren't // able to use any of the other endpoints either. $post = ['editors[0]' => 'form'] + $this->getAjaxPageStatePostData(); $response = $this->drupalPost('quickedit/attachments', '', $post, ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]); - $message = Json::encode(['message' => "The 'access in-place editing' permission is required."]); + $message = Json::encode(['message' => "A fatal error occurred: The 'access in-place editing' permission is required."]); $this->assertIdentical($message, $response); $this->assertResponse(403); $post = ['nocssjs' => 'true'] + $this->getAjaxPageStatePostData(); only in patch2: unchanged: --- a/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php +++ b/core/modules/quickedit/tests/modules/src/MockEditEntityFieldAccessCheck.php @@ -2,9 +2,19 @@ namespace Drupal\quickedit_test; +use Drupal\Core\Entity\EntityInterface; +use Drupal\quickedit\Access\EditEntityFieldAccessCheckInterface; + /** - * @deprecated in Drupal 8.4.x and will be removed before Drupal 9.0.0. + * Access check for editing entity fields. */ -class MockEditEntityFieldAccessCheck extends MockQuickEditEntityFieldAccessCheck { +class MockEditEntityFieldAccessCheck implements EditEntityFieldAccessCheckInterface { + + /** + * {@inheritdoc} + */ + public function accessEditEntityField(EntityInterface $entity, $field_name) { + return TRUE; + } } only in patch2: unchanged: --- a/core/modules/quickedit/tests/modules/src/MockQuickEditEntityFieldAccessCheck.php +++ /dev/null @@ -1,20 +0,0 @@ -editorManager = $this->container->get('plugin.manager.quickedit.editor'); - $this->accessChecker = new MockQuickEditEntityFieldAccessCheck(); + $this->accessChecker = new MockEditEntityFieldAccessCheck(); $this->editorSelector = new EditorSelector($this->editorManager, $this->container->get('plugin.manager.field.formatter')); $this->metadataGenerator = new MetadataGenerator($this->accessChecker, $this->editorSelector, $this->editorManager); } only in patch2: unchanged: --- a/core/modules/quickedit/tests/src/Unit/Access/QuickEditEntityFieldAccessCheckTest.php +++ b/core/modules/quickedit/tests/src/Unit/Access/EditEntityFieldAccessCheckTest.php @@ -5,21 +5,21 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Cache\Context\CacheContextsManager; use Drupal\Core\DependencyInjection\Container; -use Drupal\quickedit\Access\QuickEditEntityFieldAccessCheck; +use Drupal\quickedit\Access\EditEntityFieldAccessCheck; use Drupal\Tests\UnitTestCase; use Drupal\Core\Language\LanguageInterface; /** - * @coversDefaultClass \Drupal\quickedit\Access\QuickEditEntityFieldAccessCheck + * @coversDefaultClass \Drupal\quickedit\Access\EditEntityFieldAccessCheck * @group Access * @group quickedit */ -class QuickEditEntityFieldAccessCheckTest extends UnitTestCase { +class EditEntityFieldAccessCheckTest extends UnitTestCase { /** * The tested access checker. * - * @var \Drupal\quickedit\Access\QuickEditEntityFieldAccessCheck + * @var \Drupal\quickedit\Access\EditEntityFieldAccessCheck */ protected $editAccessCheck; @@ -27,7 +27,7 @@ class QuickEditEntityFieldAccessCheckTest extends UnitTestCase { * {@inheritdoc} */ protected function setUp() { - $this->editAccessCheck = new QuickEditEntityFieldAccessCheck(); + $this->editAccessCheck = new EditEntityFieldAccessCheck(); $cache_contexts_manager = $this->prophesize(CacheContextsManager::class); $cache_contexts_manager->assertValidTokens()->willReturn(TRUE); @@ -40,7 +40,7 @@ protected function setUp() { /** * Provides test data for testAccess(). * - * @see \Drupal\Tests\edit\Unit\quickedit\Access\QuickEditEntityFieldAccessCheckTest::testAccess() + * @see \Drupal\Tests\edit\Unit\quickedit\Access\EditEntityFieldAccessCheckTest::testAccess() */ public function providerTestAccess() { $data = []; only in patch2: unchanged: --- a/core/modules/responsive_image/tests/src/Functional/ResponsiveImageAdminUITest.php +++ b/core/modules/responsive_image/src/Tests/ResponsiveImageAdminUITest.php @@ -1,15 +1,15 @@ assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_mapping_type]', NULL); + $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_mapping_type]', ''); // Check if the image style dropdowns are present. - $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_style]', NULL); + $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][image_style]', ''); // Check if the sizes textfields are present. - $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][sizes]', NULL); + $this->assertFieldByName('keyed_styles[responsive_image_test_module.' . $case[0] . '][' . $case[1] . '][sizes]', ''); foreach ($image_styles as $image_style_name) { // Check if the image styles are available in the dropdowns. only in patch2: unchanged: --- a/core/modules/rest/rest.module +++ b/core/modules/rest/rest.module @@ -15,13 +15,13 @@ function rest_help($route_name, RouteMatchInterface $route_match) { case 'help.page.rest': $output = ''; $output .= '

' . t('About') . '

'; - $output .= '

' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entity types such as the main site content, comments, custom blocks, taxonomy terms, and user accounts, etc. (see the Field module help page for more information about entities). REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the online documentation for the RESTful Web Services module.', [':rest' => 'https://www.drupal.org/documentation/modules/rest', ':field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', ['name' => 'field']) : '#']) . '

'; + $output .= '

' . t('The RESTful Web Services module provides a framework for exposing REST resources on your site. It provides support for content entities (see the Field module help page for more information about entities) such as content, users, taxonomy terms, etc.; REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. Other modules may add support for other types of REST resources. For more information, see the online documentation for the RESTful Web Services module.', [':rest' => 'https://www.drupal.org/documentation/modules/rest', ':field' => (\Drupal::moduleHandler()->moduleExists('field')) ? \Drupal::url('help.page', ['name' => 'field']) : '#']) . '

'; $output .= '

' . t('Uses') . '

'; $output .= '
'; $output .= '
' . t('Installing supporting modules') . '
'; $output .= '
' . t('In order to use REST on a web site, you need to install modules that provide serialization and authentication services. You can use the Core module HAL for serialization and HTTP Basic Authentication for authentication, or install a contributed or custom module.', [':hal' => (\Drupal::moduleHandler()->moduleExists('hal')) ? \Drupal::url('help.page', ['name' => 'hal']) : '#', ':basic_auth' => (\Drupal::moduleHandler()->moduleExists('basic_auth')) ? \Drupal::url('help.page', ['name' => 'basic_auth']) : '#']) . '
'; $output .= '
' . t('Enabling REST support for an entity type') . '
'; - $output .= '
' . t('REST support for content types (provided by the Node module) is enabled by default. To enable support for other content entity types, you can use a process based on configuration editing or the contributed REST UI module.', [':node' => (\Drupal::moduleHandler()->moduleExists('node')) ? \Drupal::url('help.page', ['name' => 'node']) : '#', ':config' => 'https://www.drupal.org/documentation/modules/rest', ':restui' => 'https://www.drupal.org/project/restui']) . '
'; + $output .= '
' . t('REST support for content items of the Node module is enabled by default, and support for other types of content entities can be enabled. To enable support, you can use a process based on configuration editing or the contributed Rest UI module.', [':config' => 'https://www.drupal.org/documentation/modules/rest', ':restui' => 'https://www.drupal.org/project/restui']) . '
'; $output .= '
' . t('You will also need to grant anonymous users permission to perform each of the REST operations you want to be available, and set up authentication properly to authorize web requests.') . '
'; $output .= '
'; return $output; only in patch2: unchanged: --- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php @@ -432,10 +432,7 @@ public function calculateDependencies() { */ protected function addLinkHeaders(EntityInterface $entity, Response $response) { foreach ($entity->getEntityType()->getLinkTemplates() as $relation_name => $link_template) { - if ($this->linkRelationTypeManager->hasDefinition($relation_name)) { - /** @var \Drupal\Core\Http\LinkRelationTypeInterface $link_relation_type */ - $link_relation_type = $this->linkRelationTypeManager->createInstance($relation_name); - + if ($definition = $this->linkRelationTypeManager->getDefinition($relation_name, FALSE)) { $generator_url = $entity->toUrl($relation_name) ->setAbsolute(TRUE) ->toString(TRUE); @@ -443,10 +440,10 @@ protected function addLinkHeaders(EntityInterface $entity, Response $response) { $response->addCacheableDependency($generator_url); } $uri = $generator_url->getGeneratedUrl(); - - $relationship = $link_relation_type->isRegistered() - ? $link_relation_type->getRegisteredName() - : $link_relation_type->getExtensionUri(); + $relationship = $relation_name; + if (!empty($definition['uri'])) { + $relationship = $definition['uri']; + } $link_header = '<' . $uri . '>; rel="' . $relationship . '"'; $response->headers->set('Link', $link_header, FALSE); only in patch2: unchanged: --- a/core/modules/rest/src/Plugin/views/display/RestExport.php +++ b/core/modules/rest/src/Plugin/views/display/RestExport.php @@ -435,7 +435,7 @@ public function render() { $build['#markup'] = ViewsRenderPipelineMarkup::create($build['#markup']); } - parent::applyDisplayCacheabilityMetadata($build); + parent::applyDisplayCachablityMetadata($build); return $build; } only in patch2: unchanged: --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -11,9 +11,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; -use Symfony\Component\Serializer\Exception\InvalidArgumentException; /** * Acts as intermediate request forwarder for resource plugins. @@ -60,20 +58,22 @@ public static function create(ContainerInterface $container) { * The response object. */ public function handle(RouteMatchInterface $route_match, Request $request) { + $method = strtolower($request->getMethod()); + // Symfony is built to transparently map HEAD requests to a GET request. In // the case of the REST module's RequestHandler though, we essentially have // our own light-weight routing system on top of the Drupal/symfony routing - // system. So, we have to respect the decision that the routing system made: - // we look not at the request method, but at the route's method. All REST - // routes are guaranteed to have _method set. - // Response::prepare() will transform it to a HEAD response at the very last - // moment. + // system. So, we have to do the same as what the UrlMatcher does: map HEAD + // requests to the logic for GET. This also guarantees response headers for + // HEAD requests are identical to those for GET requests, because we just + // return a GET response. Response::prepare() will transform it to a HEAD + // response at the very last moment. // @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4 // @see \Symfony\Component\Routing\Matcher\UrlMatcher::matchCollection() // @see \Symfony\Component\HttpFoundation\Response::prepare() - $method = strtolower($route_match->getRouteObject()->getMethods()[0]); - assert(count($route_match->getRouteObject()->getMethods()) === 1); - + if ($method === 'head') { + $method = 'get'; + } $resource_config_id = $route_match->getRouteObject()->getDefault('_rest_resource_config'); /** @var \Drupal\rest\RestResourceConfigInterface $resource_config */ @@ -89,32 +89,19 @@ public function handle(RouteMatchInterface $route_match, Request $request) { $format = $request->getContentType(); $definition = $resource->getPluginDefinition(); - - // First decode the request data. We can then determine if the - // serialized data was malformed. try { - $unserialized = $serializer->decode($received, $format, ['request_method' => $method]); + if (!empty($definition['serialization_class'])) { + $unserialized = $serializer->deserialize($received, $definition['serialization_class'], $format, ['request_method' => $method]); + } + // If the plugin does not specify a serialization class just decode + // the received data. + else { + $unserialized = $serializer->decode($received, $format, ['request_method' => $method]); + } } catch (UnexpectedValueException $e) { - // If an exception was thrown at this stage, there was a problem - // decoding the data. Throw a 400 http exception. throw new BadRequestHttpException($e->getMessage()); } - - // Then attempt to denormalize if there is a serialization class. - if (!empty($definition['serialization_class'])) { - try { - $unserialized = $serializer->denormalize($unserialized, $definition['serialization_class'], $format, ['request_method' => $method]); - } - // These two serialization exception types mean there was a problem - // with the structure of the decoded data and it's not valid. - catch (UnexpectedValueException $e) { - throw new UnprocessableEntityHttpException($e->getMessage()); - } - catch (InvalidArgumentException $e) { - throw new UnprocessableEntityHttpException($e->getMessage()); - } - } } // Determine the request parameters that should be passed to the resource only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Block/BlockResourceTestBase.php @@ -122,7 +122,9 @@ protected function getExpectedCacheContexts() { protected function getExpectedCacheTags() { // Because the 'user.permissions' cache context is missing, the cache tag // for the anonymous user role is never added automatically. - return array_values(array_diff(parent::getExpectedCacheTags(), ['config:user.role.anonymous'])); + return array_values(array_filter(parent::getExpectedCacheTags(), function ($tag) { + return $tag !== 'config:user.role.anonymous'; + })); } /** only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php @@ -280,8 +280,8 @@ public function testPostDxWithoutCriticalBaseFields() { $response = $this->request('POST', $url, $request_options); // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364. $this->assertSame(500, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); - $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.

Symfony\Component\HttpKernel\Exception\HttpException: Internal Server Error in Drupal\rest\Plugin\rest\resource\EntityResource->post()', (string) $response->getBody()); + $this->assertSame(['application/json'], $response->getHeader('Content-Type')); + $this->assertSame('{"message":"A fatal error occurred: Internal Server Error"}', (string) $response->getBody()); //$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response); // DX: 422 when missing 'entity_id' field. @@ -303,9 +303,10 @@ public function testPostDxWithoutCriticalBaseFields() { // DX: 422 when missing 'entity_type' field. $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format); $response = $this->request('POST', $url, $request_options); - // @todo Uncomment, remove next 2 lines in https://www.drupal.org/node/2820364. + // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364. $this->assertSame(500, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['application/json'], $response->getHeader('Content-Type')); + $this->assertSame('{"message":"A fatal error occurred: Field is unknown."}', (string) $response->getBody()); //$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nfield_name: This value should not be null.\n", $response); } only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/Editor/EditorJsonAnonTest.php +++ /dev/null @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['administer filters']); - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - // Create a "Llama" filter format. - $llama_format = FilterFormat::create([ - 'name' => 'Llama', - 'format' => 'llama', - 'langcode' => 'es', - 'filters' => [ - 'filter_html' => [ - 'status' => TRUE, - 'settings' => [ - 'allowed_html' => '

', - ], - ], - ], - ]); - - $llama_format->save(); - - // Create a "Camelids" editor. - $camelids = Editor::create([ - 'format' => 'llama', - 'editor' => 'ckeditor', - ]); - $camelids - ->setImageUploadSettings([ - 'status' => FALSE, - 'scheme' => file_default_scheme(), - 'directory' => 'inline-images', - 'max_size' => '', - 'max_dimensions' => [ - 'width' => '', - 'height' => '', - ], - ]) - ->save(); - - return $camelids; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'dependencies' => [ - 'config' => [ - 'filter.format.llama', - ], - 'module' => [ - 'ckeditor', - ], - ], - 'editor' => 'ckeditor', - 'format' => 'llama', - 'image_upload' => [ - 'status' => FALSE, - 'scheme' => 'public', - 'directory' => 'inline-images', - 'max_size' => '', - 'max_dimensions' => [ - 'width' => NULL, - 'height' => NULL, - ], - ], - 'langcode' => 'en', - 'settings' => [ - 'toolbar' => [ - 'rows' => [ - [ - [ - 'name' => 'Formatting', - 'items' => [ - 'Bold', - 'Italic', - ], - ], - [ - 'name' => 'Links', - 'items' => [ - 'DrupalLink', - 'DrupalUnlink', - ], - ], - [ - 'name' => 'Lists', - 'items' => [ - 'BulletedList', - 'NumberedList', - ], - ], - [ - 'name' => 'Media', - 'items' => [ - 'Blockquote', - 'DrupalImage', - ], - ], - [ - 'name' => 'Tools', - 'items' => [ - 'Source', - ], - ], - ], - ], - ], - 'plugins' => [ - 'language' => [ - 'language_list' => 'un', - ], - ], - ], - 'status' => TRUE, - 'uuid' => $this->entity->uuid(), - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - - /** - * {@inheritdoc} - */ - protected function getExpectedCacheContexts() { - // @see ::createEntity() - return ['user.permissions']; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedUnauthorizedAccessMessage($method) { - if ($this->config('rest.settings')->get('bc_entity_resource_permissions')) { - return parent::getExpectedUnauthorizedAccessMessage($method); - } - - return "The 'administer filters' permission is required."; - } - -} only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php @@ -424,11 +424,11 @@ public function testGet() { if ($this->entity->getEntityType()->getLinkTemplates()) { $this->assertArrayHasKey('Link', $response->getHeaders()); $link_relation_type_manager = $this->container->get('plugin.manager.link_relation_type'); - $expected_link_relation_headers = array_map(function ($relation_name) use ($link_relation_type_manager) { - $link_relation_type = $link_relation_type_manager->createInstance($relation_name); - return $link_relation_type->isRegistered() - ? $link_relation_type->getRegisteredName() - : $link_relation_type->getExtensionUri(); + $expected_link_relation_headers = array_map(function ($rel) use ($link_relation_type_manager) { + $definition = $link_relation_type_manager->getDefinition($rel, FALSE); + return (!empty($definition['uri'])) + ? $definition['uri'] + : $rel; }, array_keys($this->entity->getEntityType()->getLinkTemplates())); $parse_rel_from_link_header = function ($value) use ($link_relation_type_manager) { $matches = []; @@ -531,17 +531,17 @@ public function testGet() { // DX: 406 when requesting unsupported format. $response = $this->request('GET', $url, $request_options); $this->assert406Response($response); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertNotSame([static::$mimeType], $response->getHeader('Content-Type')); $request_options[RequestOptions::HEADERS]['Accept'] = static::$mimeType; - // DX: 406 when requesting unsupported format but specifying Accept header: - // should result in a text/plain response. + // DX: 406 when requesting unsupported format but specifying Accept header. + // @todo Update in https://www.drupal.org/node/2825347. $response = $this->request('GET', $url, $request_options); $this->assert406Response($response); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['application/json'], $response->getHeader('Content-Type')); $url = Url::fromRoute('rest.entity.' . static::$entityTypeId . '.GET.' . static::$format); @@ -634,7 +634,7 @@ public function testPost() { // missing ?_format query string. $response = $this->request('POST', $url, $request_options); $this->assertSame(415, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); $this->assertContains(htmlspecialchars('No "Content-Type" request header specified'), (string) $response->getBody()); @@ -806,7 +806,7 @@ public function testPatch() { if ($has_canonical_url) { $this->assertSame(405, $response->getStatusCode()); $this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow')); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); } else { $this->assertSame(404, $response->getStatusCode()); @@ -835,7 +835,7 @@ public function testPatch() { // DX: 415 when no Content-Type request header. $response = $this->request('PATCH', $url, $request_options); $this->assertSame(415, $response->getStatusCode()); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); $this->assertTrue(FALSE !== strpos((string) $response->getBody(), htmlspecialchars('No "Content-Type" request header specified'))); @@ -902,15 +902,19 @@ public function testPatch() { // DX: 403 when sending PATCH request with read-only fields. - foreach (static::$patchProtectedFieldNames as $field_name) { - $normalization = $this->getNormalizedPatchEntity() + [$field_name => [['value' => $this->randomString()]]]; - $request_options[RequestOptions::BODY] = $this->serializer->serialize($normalization, static::$format); + // First send all fields (the "maximum normalization"). Assert the expected + // error message for the first PATCH-protected field. Remove that field from + // the normalization, send another request, assert the next PATCH-protected + // field error message. And so on. + $max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format); + for ($i = 0; $i < count(static::$patchProtectedFieldNames); $i++) { + $max_normalization = $this->removeFieldsFromNormalization($max_normalization, array_slice(static::$patchProtectedFieldNames, 0, $i)); + $request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format); $response = $this->request('PATCH', $url, $request_options); - $this->assertResourceErrorResponse(403, "Access denied on updating field '$field_name'.", $response); + $this->assertResourceErrorResponse(403, "Access denied on updating field '" . static::$patchProtectedFieldNames[$i] . "'.", $response); } // 200 for well-formed request that sends the maximum number of fields. - $max_normalization = $this->getNormalizedPatchEntity() + $this->serializer->normalize($this->entity, static::$format); $max_normalization = $this->removeFieldsFromNormalization($max_normalization, static::$patchProtectedFieldNames); $request_options[RequestOptions::BODY] = $this->serializer->serialize($max_normalization, static::$format); $response = $this->request('PATCH', $url, $request_options); @@ -988,13 +992,13 @@ public function testDelete() { $request_options = []; - // DX: 404 when resource not provisioned, but 405 if canonical route. Plain + // DX: 405 when resource not provisioned, but HTML if canonical route. Plain // text or HTML response because missing ?_format query string. $response = $this->request('DELETE', $url, $request_options); if ($has_canonical_url) { $this->assertSame(405, $response->getStatusCode()); $this->assertSame(['GET, POST, HEAD'], $response->getHeader('Allow')); - $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type')); + $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type')); } else { $this->assertSame(404, $response->getStatusCode()); @@ -1095,9 +1099,10 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - // DX: 422 when incorrect entity type bundle is specified. + // DX: 400 when incorrect entity type bundle is specified. + // @todo Change to 422 in https://www.drupal.org/node/2827084. $response = $this->request($method, $url, $request_options); - $this->assertResourceErrorResponse(422, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response); + $this->assertResourceErrorResponse(400, '"bad_bundle_name" is not a valid bundle type for denormalization.', $response); } @@ -1105,9 +1110,10 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - // DX: 422 when no entity type bundle is specified. + // DX: 400 when no entity type bundle is specified. + // @todo Change to 422 in https://www.drupal.org/node/2827084. $response = $this->request($method, $url, $request_options); - $this->assertResourceErrorResponse(422, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response); + $this->assertResourceErrorResponse(400, sprintf('Could not determine entity type bundle: "%s" field is missing.', $bundle_field_name), $response); } } only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/Node/NodeResourceTestBase.php @@ -23,6 +23,7 @@ * {@inheritdoc} */ protected static $patchProtectedFieldNames = [ + 'uid', 'created', 'changed', 'promote', only in patch2: unchanged: --- a/core/modules/rest/tests/src/Functional/EntityResource/ShortcutSet/ShortcutSetJsonAnonTest.php +++ /dev/null @@ -1,24 +0,0 @@ -grantPermissionsToTestedRole(['access shortcuts']); - break; - - case 'POST': - case 'PATCH': - $this->grantPermissionsToTestedRole(['access shortcuts', 'customize shortcut links']); - break; - - case 'DELETE': - $this->grantPermissionsToTestedRole(['administer shortcuts']); - break; - } - } - - /** - * {@inheritdoc} - */ - protected function createEntity() { - $set = ShortcutSet::create([ - 'id' => 'llama_set', - 'label' => 'Llama Set', - ]); - $set->save(); - return $set; - } - - /** - * {@inheritdoc} - */ - protected function getExpectedNormalizedEntity() { - return [ - 'id' => 'llama_set', - 'uuid' => $this->entity->uuid(), - 'label' => 'Llama Set', - 'status' => TRUE, - 'langcode' => 'en', - 'dependencies' => [], - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNormalizedPostEntity() { - // @todo Update in https://www.drupal.org/node/2300677. - } - -} only in patch2: unchanged: --- a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php +++ b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php @@ -49,7 +49,7 @@ public function setUp() { */ public function testHandle() { $request = new Request(); - $route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json']))->setMethods(['GET'])); + $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_format' => 'json'])); $resource = $this->prophesize(StubRequestHandlerResourcePlugin::class); $resource->get(NULL, $request) @@ -76,7 +76,7 @@ public function testHandle() { $this->assertEquals($response, $handler_response); // We will call the patch method this time. - $route_match = new RouteMatch('test', (new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json']))->setMethods(['PATCH'])); + $route_match = new RouteMatch('test', new Route('/rest/test', ['_rest_resource_config' => 'restplugin'], ['_content_type_format' => 'json'])); $request->setMethod('PATCH'); $response = new ResourceResponse([]); $resource->patch(NULL, $request) only in patch2: unchanged: --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -8,7 +8,6 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Unicode; use Drupal\Core\Cache\Cache; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; @@ -219,7 +218,7 @@ function search_update_totals() { // search_total. We use a LEFT JOIN between the two tables and keep only the // rows which fail to join. $result = db_query("SELECT t.word AS realword, i.word FROM {search_total} t LEFT JOIN {search_index} i ON t.word = i.word WHERE i.word IS NULL", [], ['target' => 'replica']); - $or = new Condition('OR'); + $or = db_or(); foreach ($result as $word) { $or->condition('word', $word->realword); } only in patch2: unchanged: --- a/core/modules/search/src/Controller/SearchController.php +++ b/core/modules/search/src/Controller/SearchController.php @@ -5,7 +5,6 @@ use Drupal\Core\Cache\CacheableDependencyInterface; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Render\RendererInterface; -use Drupal\search\Form\SearchPageForm; use Drupal\search\SearchPageInterface; use Drupal\search\SearchPageRepositoryInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -85,7 +84,7 @@ public function view(Request $request, SearchPageInterface $entity) { } $build['#title'] = $plugin->suggestedTitle(); - $build['search_form'] = $this->formBuilder()->getForm(SearchPageForm::class, $entity); + $build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search'); // Build search results, if keywords or other search parameters are in the // GET parameters. Note that we need to try the search if 'keys' is in only in patch2: unchanged: --- a/core/modules/search/src/Entity/SearchPage.php +++ b/core/modules/search/src/Entity/SearchPage.php @@ -22,6 +22,7 @@ * "form" = { * "add" = "Drupal\search\Form\SearchPageAddForm", * "edit" = "Drupal\search\Form\SearchPageEditForm", + * "search" = "Drupal\search\Form\SearchPageForm", * "delete" = "Drupal\Core\Entity\EntityDeleteForm" * } * }, only in patch2: unchanged: --- a/core/modules/search/src/Form/SearchPageForm.php +++ b/core/modules/search/src/Form/SearchPageForm.php @@ -2,10 +2,9 @@ namespace Drupal\search\Form; -use Drupal\Core\Form\FormBase; +use Drupal\Core\Entity\EntityForm; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; -use Drupal\search\SearchPageInterface; /** * Provides a search form for site wide search. @@ -16,10 +15,10 @@ * trigger the search being processed by the controller, and adding in any * additional query parameters they need to execute search. */ -class SearchPageForm extends FormBase { +class SearchPageForm extends EntityForm { /** - * The search page entity. + * {@inheritdoc} * * @var \Drupal\search\SearchPageInterface */ @@ -35,9 +34,7 @@ public function getFormId() { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, SearchPageInterface $search_page = NULL) { - $this->entity = $search_page; - + public function form(array $form, FormStateInterface $form_state) { $plugin = $this->entity->getPlugin(); $form_state->set('search_page_id', $this->entity->id()); @@ -75,7 +72,16 @@ public function buildForm(array $form, FormStateInterface $form_state, SearchPag // Allow the plugin to add to or alter the search form. $plugin->searchFormAlter($form, $form_state); - return $form; + + return parent::form($form, $form_state); + } + + /** + * {@inheritdoc} + */ + protected function actions(array $form, FormStateInterface $form_state) { + // The submit button is added in the form directly. + return []; } /** only in patch2: unchanged: --- a/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php +++ b/core/modules/search/src/Plugin/ConfigurableSearchPluginBase.php @@ -23,7 +23,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->setConfiguration($configuration); + $this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $this->configuration); } /** @@ -44,7 +44,7 @@ public function getConfiguration() { * {@inheritdoc} */ public function setConfiguration(array $configuration) { - $this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $configuration); + $this->configuration = $configuration; } /** only in patch2: unchanged: --- a/core/modules/search/src/Plugin/SearchInterface.php +++ b/core/modules/search/src/Plugin/SearchInterface.php @@ -110,7 +110,7 @@ public function getHelp(); * * The core search module only invokes this method on active module plugins * when building a form for them in - * \Drupal\search\Form\SearchPageForm::buildForm(). A plugin implementing this + * \Drupal\search\Form\SearchPageForm::form(). A plugin implementing this * will also need to implement the buildSearchUrlQuery() method. * * @param array $form only in patch2: unchanged: --- a/core/modules/search/src/Plugin/views/argument/Search.php +++ b/core/modules/search/src/Plugin/views/argument/Search.php @@ -2,7 +2,6 @@ namespace Drupal\search\Plugin\views\argument; -use Drupal\Core\Database\Query\Condition; use Drupal\views\Plugin\views\argument\ArgumentPluginBase; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; @@ -77,7 +76,7 @@ public function query($group_by = FALSE) { else { $search_index = $this->ensureMyTable(); - $search_condition = new Condition('AND'); + $search_condition = db_and(); // Create a new join to relate the 'search_total' table to our current 'search_index' table. $definition = [ @@ -110,7 +109,7 @@ public function query($group_by = FALSE) { // Add the keyword conditions, as is done in // SearchQuery::prepareAndNormalize(), but simplified because we are // only concerned with relevance ranking so we do not need to normalize. - $or = new Condition('OR'); + $or = db_or(); foreach ($words as $word) { $or->condition("$search_index.word", $word); } only in patch2: unchanged: --- a/core/modules/search/src/Plugin/views/filter/Search.php +++ b/core/modules/search/src/Plugin/views/filter/Search.php @@ -2,7 +2,6 @@ namespace Drupal\search\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\filter\FilterPluginBase; use Drupal\views\Plugin\views\display\DisplayPluginBase; @@ -151,7 +150,7 @@ public function query() { else { $search_index = $this->ensureMyTable(); - $search_condition = new Condition('AND'); + $search_condition = db_and(); // Create a new join to relate the 'search_total' table to our current // 'search_index' table. @@ -185,7 +184,7 @@ public function query() { // Add the keyword conditions, as is done in // SearchQuery::prepareAndNormalize(), but simplified because we are // only concerned with relevance ranking so we do not need to normalize. - $or = new Condition('OR'); + $or = db_or(); foreach ($words as $word) { $or->condition("$search_index.word", $word); } only in patch2: unchanged: --- a/core/modules/search/src/SearchQuery.php +++ b/core/modules/search/src/SearchQuery.php @@ -2,7 +2,6 @@ namespace Drupal\search; -use Drupal\Core\Database\Query\Condition; use Drupal\Component\Utility\Unicode; use Drupal\Core\Database\Query\SelectExtender; use Drupal\Core\Database\Query\SelectInterface; @@ -206,7 +205,7 @@ public function searchExpression($expression, $type) { $this->addTag('search_' . $type); // Initialize conditions and status. - $this->conditions = new Condition('AND'); + $this->conditions = db_and(); $this->status = 0; return $this; @@ -314,7 +313,7 @@ protected function parseSearchExpression() { } $has_or = TRUE; $has_new_scores = FALSE; - $queryor = new Condition('OR'); + $queryor = db_or(); foreach ($key as $or) { list($num_new_scores) = $this->parseWord($or); $has_new_scores |= $num_new_scores; @@ -402,7 +401,7 @@ public function prepareAndNormalize() { } // Build the basic search query: match the entered keywords. - $or = new Condition('OR'); + $or = db_or(); foreach ($this->words as $word) { $or->condition('i.word', $word); } only in patch2: unchanged: --- a/core/modules/search/src/ViewsSearchQuery.php +++ b/core/modules/search/src/ViewsSearchQuery.php @@ -74,8 +74,8 @@ public function conditionReplaceString($search, $replace, &$condition) { $conditions =& $condition['field']->conditions(); foreach ($conditions as $key => &$subcondition) { if (is_numeric($key)) { - // As conditions can be nested, the function has to be called - // recursively. + // As conditions can have subconditions, for example db_or(), the + // function has to be called recursively. $this->conditionReplaceString($search, $replace, $subcondition); } } only in patch2: unchanged: --- a/core/modules/serialization/serialization.services.yml +++ b/core/modules/serialization/serialization.services.yml @@ -33,7 +33,6 @@ services: # this modules generic field item normalizer. # @todo Find a better way for this in https://www.drupal.org/node/2575761. - { name: normalizer, priority: 8 } - arguments: ['@entity.repository'] serialization.normalizer.field_item: class: Drupal\serialization\Normalizer\FieldItemNormalizer tags: only in patch2: unchanged: --- a/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php +++ b/core/modules/serialization/src/Normalizer/EntityReferenceFieldItemNormalizer.php @@ -2,15 +2,12 @@ namespace Drupal\serialization\Normalizer; -use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; -use Symfony\Component\Serializer\Exception\InvalidArgumentException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Adds the file URI to embedded file entities. */ -class EntityReferenceFieldItemNormalizer extends FieldItemNormalizer { +class EntityReferenceFieldItemNormalizer extends ComplexDataNormalizer { /** * The interface or class that this Normalizer supports. @@ -20,23 +17,6 @@ class EntityReferenceFieldItemNormalizer extends FieldItemNormalizer { protected $supportedInterfaceOrClass = EntityReferenceItem::class; /** - * The entity repository. - * - * @var \Drupal\Core\Entity\EntityRepositoryInterface - */ - protected $entityRepository; - - /** - * Constructs a EntityReferenceFieldItemNormalizer object. - * - * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository - * The entity repository. - */ - public function __construct(EntityRepositoryInterface $entity_repository) { - $this->entityRepository = $entity_repository; - } - - /** * {@inheritdoc} */ public function normalize($field_item, $format = NULL, array $context = []) { @@ -55,32 +35,8 @@ public function normalize($field_item, $format = NULL, array $context = []) { $values['url'] = $url; } } - return $values; - } - /** - * {@inheritdoc} - */ - protected function constructValue($data, $context) { - if (isset($data['target_uuid'])) { - /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $field_item */ - $field_item = $context['target_instance']; - if (empty($data['target_uuid'])) { - throw new InvalidArgumentException(sprintf('If provided "target_uuid" cannot be empty for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName())); - } - $target_type = $field_item->getFieldDefinition()->getSetting('target_type'); - if (!empty($data['target_type']) && $target_type !== $data['target_type']) { - throw new UnexpectedValueException(sprintf('The field "%s" property "target_type" must be set to "%s" or omitted.', $field_item->getFieldDefinition()->getName(), $target_type)); - } - if ($entity = $this->entityRepository->loadEntityByUuid($target_type, $data['target_uuid'])) { - return ['target_id' => $entity->id()]; - } - else { - // Unable to load entity by uuid. - throw new InvalidArgumentException(sprintf('No "%s" entity found with UUID "%s" for field "%s".', $data['target_type'], $data['target_uuid'], $field_item->getName())); - } - } - return parent::constructValue($data, $context); + return $values; } } only in patch2: unchanged: --- a/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php +++ b/core/modules/serialization/tests/src/Unit/CompilerPass/RegisterSerializationClassesCompilerPassTest.php @@ -4,7 +4,6 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\serialization\RegisterSerializationClassesCompilerPass; -use Drupal\Tests\UnitTestCase; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\Serializer\Serializer; @@ -12,7 +11,7 @@ * @coversDefaultClass \Drupal\serialization\RegisterSerializationClassesCompilerPass * @group serialization */ -class RegisterSerializationClassesCompilerPassTest extends UnitTestCase { +class RegisterSerializationClassesCompilerPassTest extends \PHPUnit_Framework_TestCase { /** * @covers ::process only in patch2: unchanged: --- a/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php +++ b/core/modules/serialization/tests/src/Unit/Normalizer/EntityReferenceFieldItemNormalizerTest.php @@ -3,18 +3,11 @@ namespace Drupal\Tests\serialization\Unit\Normalizer; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\TypedData\TypedDataInterface; -use Drupal\Core\Entity\EntityRepositoryInterface; -use Drupal\Core\Entity\FieldableEntityInterface; -use Drupal\Core\Field\FieldItemInterface; -use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; -use Symfony\Component\Serializer\Exception\InvalidArgumentException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\Serializer; /** @@ -45,25 +38,10 @@ class EntityReferenceFieldItemNormalizerTest extends UnitTestCase { protected $fieldItem; /** - * The mock entity repository. - * - * @var \Drupal\Core\Entity\EntityRepositoryInterface|\Prophecy\Prophecy\ObjectProphecy - */ - protected $entityRepository; - - /** - * The mock field definition. - * - * @var \Drupal\Core\Field\FieldDefinitionInterface|\Prophecy\Prophecy\ObjectProphecy - */ - protected $fieldDefinition; - - /** * {@inheritdoc} */ protected function setUp() { - $this->entityRepository = $this->prophesize(EntityRepositoryInterface::class); - $this->normalizer = new EntityReferenceFieldItemNormalizer($this->entityRepository->reveal()); + $this->normalizer = new EntityReferenceFieldItemNormalizer(); $this->serializer = $this->prophesize(Serializer::class); // Set up the serializer to return an entity property. @@ -75,9 +53,6 @@ protected function setUp() { $this->fieldItem = $this->prophesize(EntityReferenceItem::class); $this->fieldItem->getIterator() ->willReturn(new \ArrayIterator(['target_id' => []])); - - $this->fieldDefinition = $this->prophesize(FieldDefinitionInterface::class); - } /** @@ -89,14 +64,6 @@ public function testSupportsNormalization() { } /** - * @covers ::supportsDenormalization - */ - public function testSupportsDenormalization() { - $this->assertTrue($this->normalizer->supportsDenormalization([], EntityReferenceItem::class)); - $this->assertFalse($this->normalizer->supportsDenormalization([], FieldItemInterface::class)); - } - - /** * @covers ::normalize */ public function testNormalize() { @@ -154,149 +121,4 @@ public function testNormalizeWithNoEntity() { $this->assertSame($expected, $normalized); } - /** - * @covers ::denormalize - */ - public function testDenormalizeWithTypeAndUuid() { - $data = [ - 'target_id' => ['value' => 'test'], - 'target_type' => 'test_type', - 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb', - ]; - - $entity = $this->prophesize(FieldableEntityInterface::class); - $entity->id() - ->willReturn('test') - ->shouldBeCalled(); - $this->entityRepository - ->loadEntityByUuid($data['target_type'], $data['target_uuid']) - ->willReturn($entity) - ->shouldBeCalled(); - - $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled(); - - $this->assertDenormalize($data); - } - - /** - * @covers ::denormalize - */ - public function testDenormalizeWithUuidWithoutType() { - $data = [ - 'target_id' => ['value' => 'test'], - 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb', - ]; - - $entity = $this->prophesize(FieldableEntityInterface::class); - $entity->id() - ->willReturn('test') - ->shouldBeCalled(); - $this->entityRepository - ->loadEntityByUuid('test_type', $data['target_uuid']) - ->willReturn($entity) - ->shouldBeCalled(); - - $this->fieldItem->setValue(['target_id' => 'test'])->shouldBeCalled(); - - $this->assertDenormalize($data); - } - - /** - * @covers ::denormalize - */ - public function testDenormalizeWithUuidWithIncorrectType() { - $this->setExpectedException(UnexpectedValueException::class, 'The field "field_reference" property "target_type" must be set to "test_type" or omitted.'); - - $data = [ - 'target_id' => ['value' => 'test'], - 'target_type' => 'wrong_type', - 'target_uuid' => '080e3add-f9d5-41ac-9821-eea55b7b42fb', - ]; - - $this->fieldDefinition - ->getName() - ->willReturn('field_reference') - ->shouldBeCalled(); - - $this->assertDenormalize($data); - } - - /** - * @covers ::denormalize - */ - public function testDenormalizeWithTypeWithIncorrectUuid() { - $this->setExpectedException(InvalidArgumentException::class, 'No "test_type" entity found with UUID "unique-but-none-non-existent" for field "field_reference"'); - - $data = [ - 'target_id' => ['value' => 'test'], - 'target_type' => 'test_type', - 'target_uuid' => 'unique-but-none-non-existent', - ]; - $this->entityRepository - ->loadEntityByUuid($data['target_type'], $data['target_uuid']) - ->willReturn(NULL) - ->shouldBeCalled(); - $this->fieldItem - ->getName() - ->willReturn('field_reference') - ->shouldBeCalled(); - - - $this->assertDenormalize($data); - } - - /** - * @covers ::denormalize - */ - public function testDenormalizeWithEmtpyUuid() { - $this->setExpectedException(InvalidArgumentException::class, 'If provided "target_uuid" cannot be empty for field "test_type".'); - - $data = [ - 'target_id' => ['value' => 'test'], - 'target_type' => 'test_type', - 'target_uuid' => '', - ]; - $this->fieldItem - ->getName() - ->willReturn('field_reference') - ->shouldBeCalled(); - - - $this->assertDenormalize($data); - } - - /** - * @covers ::denormalize - */ - public function testDenormalizeWithId() { - $data = [ - 'target_id' => ['value' => 'test'], - ]; - $this->fieldItem->setValue($data)->shouldBeCalled(); - - $this->assertDenormalize($data); - } - - /** - * Asserts denormalization process is correct for give data. - * - * @param array $data - * The data to denormalize. - */ - protected function assertDenormalize(array $data) { - $this->fieldItem->getParent() - ->willReturn($this->prophesize(FieldItemListInterface::class)->reveal()); - $this->fieldItem->getFieldDefinition()->willReturn($this->fieldDefinition->reveal()); - if (!empty($data['target_uuid'])) { - $this->fieldDefinition - ->getSetting('target_type') - ->willReturn('test_type') - ->shouldBeCalled(); - } - - $context = ['target_instance' => $this->fieldItem->reveal()]; - $denormalized = $this->normalizer->denormalize($data, EntityReferenceItem::class, 'json', $context); - $this->assertSame($context['target_instance'], $denormalized); - } - } only in patch2: unchanged: --- a/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php +++ b/core/modules/shortcut/src/ShortcutSetAccessControlHandler.php @@ -19,8 +19,6 @@ class ShortcutSetAccessControlHandler extends EntityAccessControlHandler { */ protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { switch ($operation) { - case 'view': - return AccessResult::allowedIf($account->hasPermission('access shortcuts'))->cachePerPermissions(); case 'update': if ($account->hasPermission('administer shortcuts')) { return AccessResult::allowed()->cachePerPermissions(); only in patch2: unchanged: --- a/core/modules/simpletest/simpletest.install +++ b/core/modules/simpletest/simpletest.install @@ -6,7 +6,6 @@ */ use Drupal\Component\Utility\Environment; -use PHPUnit\Framework\TestCase; /** * Minimum value of PHP memory_limit for SimpleTest. @@ -19,7 +18,7 @@ function simpletest_requirements($phase) { $requirements = []; - $has_phpunit = class_exists(TestCase::class); + $has_phpunit = class_exists('\PHPUnit_Framework_TestCase'); $has_curl = function_exists('curl_init'); $open_basedir = ini_get('open_basedir'); only in patch2: unchanged: --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -13,7 +13,6 @@ use Drupal\Core\Test\TestDatabase; use Drupal\simpletest\TestDiscovery; use Drupal\Tests\Listeners\SimpletestUiPrinter; -use PHPUnit\Framework\TestCase; use Symfony\Component\Process\PhpExecutableFinder; use Drupal\Core\Test\TestStatus; @@ -285,15 +284,8 @@ function simpletest_phpunit_xml_filepath($test_id) { * * @return string * The path to core's phpunit.xml.dist configuration file. - * - * @deprecated in Drupal 8.4.x for removal before Drupal 9.0.0. PHPUnit test - * runners should change directory into core/ and then run the phpunit tool. - * See simpletest_phpunit_run_command() for an example. - * - * @see simpletest_phpunit_run_command() */ function simpletest_phpunit_configuration_filepath() { - @trigger_error('The ' . __FUNCTION__ . ' function is deprecated since version 8.4.x and will be removed in 9.0.0.', E_USER_DEPRECATED); return \Drupal::root() . '/core/phpunit.xml.dist'; } @@ -420,7 +412,7 @@ function _simpletest_batch_operation($test_list_init, $test_id, &$context) { // Perform the next test. $test_class = array_shift($test_list); - if (is_subclass_of($test_class, TestCase::class)) { + if (is_subclass_of($test_class, \PHPUnit_Framework_TestCase::class)) { $phpunit_results = simpletest_run_phpunit_tests($test_id, [$test_class]); simpletest_process_phpunit_results($phpunit_results); $test_results[$test_class] = simpletest_summarize_phpunit_result($phpunit_results)[$test_class]; only in patch2: unchanged: --- a/core/modules/simpletest/src/ContentTypeCreationTrait.php +++ b/core/modules/simpletest/src/ContentTypeCreationTrait.php @@ -4,7 +4,6 @@ use Drupal\Component\Render\FormattableMarkup; use Drupal\node\Entity\NodeType; -use PHPUnit\Framework\TestCase; /** * Provides methods to create content type from given values. @@ -41,7 +40,7 @@ protected function createContentType(array $values = []) { $status = $type->save(); node_add_body_field($type); - if ($this instanceof TestCase) { + if ($this instanceof \PHPUnit_Framework_TestCase) { $this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created content type %type.', ['%type' => $type->id()]))->__toString()); } else { only in patch2: unchanged: --- a/core/modules/simpletest/src/Form/SimpletestTestForm.php +++ b/core/modules/simpletest/src/Form/SimpletestTestForm.php @@ -71,7 +71,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { $form['clean'] = [ '#type' => 'fieldset', '#title' => $this->t('Clean test environment'), - '#description' => $this->t('Remove tables with the prefix "test" followed by digits and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'), + '#description' => $this->t('Remove tables with the prefix "simpletest" and temporary directories that are left over from tests that crashed. This is intended for developers when creating tests.'), '#weight' => 200, ]; $form['clean']['op'] = [ only in patch2: unchanged: --- a/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php +++ b/core/modules/simpletest/tests/fixtures/simpletest_phpunit_run_command_test.php @@ -2,8 +2,6 @@ namespace Drupal\Tests\simpletest\Unit; -use Drupal\Tests\UnitTestCase; - /** * This test crashes PHP. * @@ -13,7 +11,7 @@ * * @see \Drupal\Tests\simpletest\Unit\SimpletestPhpunitRunCommandTest::testSimpletestPhpUnitRunCommand() */ -class SimpletestPhpunitRunCommandTestWillDie extends UnitTestCase { +class SimpletestPhpunitRunCommandTestWillDie extends \PHPUnit_Framework_TestCase { /** * Performs the status specified by SimpletestPhpunitRunCommandTestWillDie. only in patch2: unchanged: --- a/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php +++ b/core/modules/simpletest/tests/src/Unit/SimpletestPhpunitRunCommandTest.php @@ -4,19 +4,15 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\File\FileSystemInterface; -use PHPUnit\Framework\TestCase; /** * Tests simpletest_run_phpunit_tests() handles PHPunit fatals correctly. * - * We don't extend Drupal\Tests\UnitTestCase here because its $root property is - * not static and we need it to be static here. - * * @group simpletest * * @runTestsInSeparateProcesses */ -class SimpletestPhpunitRunCommandTest extends TestCase { +class SimpletestPhpunitRunCommandTest extends \PHPUnit_Framework_TestCase { /** * Path to the app root. only in patch2: unchanged: --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -7,8 +7,6 @@ system.site: uuid: type: string label: 'Site UUID' - constraints: - NotNull: [] name: type: label label: 'Site name' only in patch2: unchanged: --- a/core/modules/system/src/Form/CronForm.php +++ b/core/modules/system/src/Form/CronForm.php @@ -131,7 +131,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#type' => 'checkbox', '#title' => t('Detailed cron logging'), '#default_value' => $this->config('system.cron')->get('logging'), - '#description' => $this->t('Run times of individual cron jobs will be written to watchdog'), + '#description' => 'Run times of individual cron jobs will be written to watchdog', ]; $form['actions']['#type'] = 'actions'; only in patch2: unchanged: --- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -5,6 +5,7 @@ use Drupal\Core\Block\BlockBase; use Drupal\Core\Cache\Cache; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Menu\MenuActiveTrailInterface; use Drupal\Core\Menu\MenuLinkTreeInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -29,6 +30,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa protected $menuTree; /** + * The active menu trail service. + * + * @var \Drupal\Core\Menu\MenuActiveTrailInterface + */ + protected $menuActiveTrail; + + /** * Constructs a new SystemMenuBlock. * * @param array $configuration @@ -39,10 +47,13 @@ class SystemMenuBlock extends BlockBase implements ContainerFactoryPluginInterfa * The plugin implementation definition. * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree * The menu tree service. + * @param \Drupal\Core\Menu\MenuActiveTrailInterface $menu_active_trail + * The active menu trail service. */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, MenuLinkTreeInterface $menu_tree, MenuActiveTrailInterface $menu_active_trail) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->menuTree = $menu_tree; + $this->menuActiveTrail = $menu_active_trail; } /** @@ -53,7 +64,8 @@ public static function create(ContainerInterface $container, array $configuratio $configuration, $plugin_id, $plugin_definition, - $container->get('menu.link_tree') + $container->get('menu.link_tree'), + $container->get('menu.active_trail') ); } only in patch2: unchanged: --- a/core/modules/system/src/Tests/Entity/Update/MoveRevisionMetadataFieldsUpdateTest.php +++ /dev/null @@ -1,83 +0,0 @@ -databaseDumpFiles = [ - __DIR__ . '/../../../../tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz', - __DIR__ . '/../../../../tests/fixtures/update/drupal-8.entity-data-revision-metadata-fields-2248983.php', - __DIR__ . '/../../../../tests/fixtures/update/drupal-8.views-revision-metadata-fields-2248983.php', - ]; - } - - /** - * Tests that the revision metadata fields are moved correctly. - */ - public function testSystemUpdate8400() { - $this->runUpdates(); - - foreach (['entity_test_revlog', 'entity_test_mul_revlog'] as $entity_type_id) { - /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ - $storage = \Drupal::entityTypeManager()->getStorage($entity_type_id); - /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */ - $entity_type = $storage->getEntityType(); - $revision_metadata_field_names = $entity_type->getRevisionMetadataKeys(); - - $database_schema = \Drupal::database()->schema(); - - // Test that the revision metadata fields are present only in the - // revision table. - foreach ($revision_metadata_field_names as $revision_metadata_field_name) { - if ($entity_type->isTranslatable()) { - $this->assertFalse($database_schema->fieldExists($entity_type->getDataTable(), $revision_metadata_field_name)); - $this->assertFalse($database_schema->fieldExists($entity_type->getRevisionDataTable(), $revision_metadata_field_name)); - } - else { - $this->assertFalse($database_schema->fieldExists($entity_type->getBaseTable(), $revision_metadata_field_name)); - } - $this->assertTrue($database_schema->fieldExists($entity_type->getRevisionTable(), $revision_metadata_field_name)); - } - - // Test that the revision metadata values have been transferred correctly - // and that the moved fields are accessible. - /** @var \Drupal\Core\Entity\RevisionLogInterface $entity_rev_first */ - $entity_rev_first = $storage->loadRevision(1); - $this->assertEqual($entity_rev_first->getRevisionUserId(), '1'); - $this->assertEqual($entity_rev_first->getRevisionLogMessage(), 'first revision'); - $this->assertEqual($entity_rev_first->getRevisionCreationTime(), '1476268517'); - - /** @var \Drupal\Core\Entity\RevisionLogInterface $entity_rev_second */ - $entity_rev_second = $storage->loadRevision(2); - $this->assertEqual($entity_rev_second->getRevisionUserId(), '1'); - $this->assertEqual($entity_rev_second->getRevisionLogMessage(), 'second revision'); - $this->assertEqual($entity_rev_second->getRevisionCreationTime(), '1476268518'); - - - // Test that the views using revision metadata fields are updated - // properly. - $view = View::load($entity_type_id . '_for_2248983'); - $displays = $view->get('display'); - foreach ($displays as $display => $display_data) { - foreach ($display_data['display_options']['fields'] as $property_data) { - if (in_array($property_data['field'], $revision_metadata_field_names)) { - $this->assertEqual($property_data['table'], $entity_type->getRevisionTable()); - } - } - } - } - } - -} only in patch2: unchanged: --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -12,9 +12,6 @@ use Drupal\Core\Path\AliasStorage; use Drupal\Core\Url; use Drupal\Core\Database\Database; -use Drupal\Core\Entity\ContentEntityTypeInterface; -use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\DrupalKernel; use Drupal\Core\Site\Settings; use Drupal\Core\StreamWrapper\PrivateStream; @@ -1792,138 +1789,3 @@ function system_update_8301() { ->set('profile', \Drupal::installProfile()) ->save(); } - -/** - * Move revision metadata fields to the revision table. - */ -function system_update_8400(&$sandbox) { - // Due to the fields from RevisionLogEntityTrait not being explicitly - // mentioned in the storage they might have been installed wrongly in the base - // table for revisionable untranslatable entities and in the data and revision - // data tables for revisionable and translatable entities. - $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager(); - $database = \Drupal::database(); - $database_schema = $database->schema(); - - if (!isset($sandbox['current'])) { - // This must be the first run. Initialize the sandbox. - $sandbox['current'] = 0; - - $definitions = array_filter(\Drupal::entityTypeManager()->getDefinitions(), function (EntityTypeInterface $entity_type) use ($entity_definition_update_manager) { - if ($entity_type = $entity_definition_update_manager->getEntityType($entity_type->id())) { - return is_subclass_of($entity_type->getClass(), FieldableEntityInterface::class) && ($entity_type instanceof ContentEntityTypeInterface) && $entity_type->isRevisionable(); - } - return FALSE; - }); - $sandbox['entity_type_ids'] = array_keys($definitions); - $sandbox['max'] = count($sandbox['entity_type_ids']); - } - - $current_entity_type_key = $sandbox['current']; - for ($i = $current_entity_type_key; ($i < $current_entity_type_key + 1) && ($i < $sandbox['max']); $i++) { - $entity_type_id = $sandbox['entity_type_ids'][$i]; - /** @var \Drupal\Core\Entity\ContentEntityTypeInterface $entity_type */ - $entity_type = $entity_definition_update_manager->getEntityType($entity_type_id); - - $base_fields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($entity_type_id); - $revision_metadata_fields = $entity_type->getRevisionMetadataKeys(); - $fields_to_update = array_intersect_key($base_fields, array_flip($revision_metadata_fields)); - - if (!empty($fields_to_update)) { - // Initialize the entity table names. - // @see \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() - $base_table = $entity_type->getBaseTable() ?: $entity_type_id; - $data_table = $entity_type->getDataTable() ?: $entity_type_id . '_field_data'; - $revision_table = $entity_type->getRevisionTable() ?: $entity_type_id . '_revision'; - $revision_data_table = $entity_type->getRevisionDataTable() ?: $entity_type_id . '_field_revision'; - $revision_field = $entity_type->getKey('revision'); - - // No data needs to be migrated if the entity type is not translatable. - if ($entity_type->isTranslatable()) { - if (!isset($sandbox[$entity_type_id])) { - // This must be the first run for this entity type. Initialize the - // sub-sandbox for it. - - // Calculate the number of revisions to process. - $count = \Drupal::entityQuery($entity_type_id) - ->allRevisions() - ->count() - ->accessCheck(FALSE) - ->execute(); - - $sandbox[$entity_type_id]['current'] = 0; - $sandbox[$entity_type_id]['max'] = $count; - } - // Define the step size. - $steps = Settings::get('entity_update_batch_size', 50); - - // Collect the revision IDs to process. - $revisions = \Drupal::entityQuery($entity_type_id) - ->allRevisions() - ->range($sandbox[$entity_type_id]['current'], $sandbox[$entity_type_id]['current'] + $steps) - ->sort($revision_field, 'ASC') - ->accessCheck(FALSE) - ->execute(); - $revisions = array_keys($revisions); - - foreach ($fields_to_update as $revision_metadata_field_name => $definition) { - // If the revision metadata field is present in the data and the - // revision data table, install its definition again with the updated - // storage code in order for the field to be installed in the - // revision table. Afterwards, copy over the field values and remove - // the field from the data and the revision data tables. - if ($database_schema->fieldExists($data_table, $revision_metadata_field_name) && $database_schema->fieldExists($revision_data_table, $revision_metadata_field_name)) { - // Install the field in the revision table. - if (!isset($sandbox[$entity_type_id]['storage_definition_installed'][$revision_metadata_field_name])) { - $entity_definition_update_manager->installFieldStorageDefinition($revision_metadata_field_name, $entity_type_id, $entity_type->getProvider(), $definition); - $sandbox[$entity_type_id]['storage_definition_installed'][$revision_metadata_field_name] = TRUE; - } - - // Apply the field value from the revision data table to the - // revision table. - foreach ($revisions as $rev_id) { - $field_value = $database->select($revision_data_table, 't') - ->fields('t', [$revision_metadata_field_name]) - ->condition($revision_field, $rev_id) - ->execute() - ->fetchField(); - $database->update($revision_table) - ->condition($revision_field, $rev_id) - ->fields([$revision_metadata_field_name => $field_value]) - ->execute(); - } - } - } - - $sandbox[$entity_type_id]['current'] += count($revisions); - $sandbox[$entity_type_id]['finished'] = ($sandbox[$entity_type_id]['current'] == $sandbox[$entity_type_id]['max']) || empty($revisions); - - if ($sandbox[$entity_type_id]['finished']) { - foreach ($fields_to_update as $revision_metadata_field_name => $definition) { - // Drop the field from the data and revision data tables. - $database_schema->dropField($data_table, $revision_metadata_field_name); - $database_schema->dropField($revision_data_table, $revision_metadata_field_name); - } - $sandbox['current']++; - } - } - else { - foreach ($fields_to_update as $revision_metadata_field_name => $definition) { - if ($database_schema->fieldExists($base_table, $revision_metadata_field_name)) { - // Install the field in the revision table. - $entity_definition_update_manager->installFieldStorageDefinition($revision_metadata_field_name, $entity_type_id, $entity_type->getProvider(), $definition); - // Drop the field from the base table. - $database_schema->dropField($base_table, $revision_metadata_field_name); - } - } - $sandbox['current']++; - } - } - else { - $sandbox['current']++; - } - - } - - $sandbox['#finished'] = $sandbox['current'] == $sandbox['max']; -} only in patch2: unchanged: --- a/core/modules/system/tests/fixtures/update/drupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.php.gz +++ /dev/null @@ -1,517 +0,0 @@ -‹ŠRXdrupal-8.2.0.bare.standard_with_entity_test_revlog_enabled.phpì]is⺶ýÞ¿‚Jݪ>}ê(ǃ<¥ß=ï&IIHB n%[28ÛØfÊ­ûߟŒÍ3&ýŽ¿t¬akkí¥½·dñ?ÿë4œoþ™ú—fcê—|daäb/_·l—d “|ûó÷ß¿¥~OýK>Ð?ÎSùHEI!ZÊó -…;-'¥ÛnÊ'ô³UO9×±=âÒA¥§†á¥‚R=ä¥êÄ".ò N©ƒ”ß ©ŒÛq™’O™VoÛ¦wJ%Kyšk8~ÐÈŸß¾u¼qÁ§©pÿΌĘüñóÛ·h¶eÍ7l+õÏÔøÁÙYøéÉ“ß~Ì—yZƒ´Ðo?À_šK¨`OH5ÉoßUÓÖš5ZÐ'–ÿýr]4øí[*õ]7ˆ‰½ï©þ5ý’~màèWôKàá×ß=âÈüþÇø‰eû)«cšÃ§OÏ—“'žñ>ªCç¡5[§cyFÝ"8RçGøßw—t Ž©ö(F0 ¥rdÏoK{dÒÕ* ºÈÕÈ­!O3Œ8:1‰U÷aežû>ß]§óÁ€wêŽåäH&²êÔf8DvnˆÃ¾;®ÑBî Õ$ƒeØ›ìXF»C‚r‹ CumˆäZ-Ð_­ÖEfgÙ†ÚWÀ|+µõ¸›}º0(äObÊ(—þ‹\jÑk0¾ÐIkàµÍZ0Hó‰[󈪹ãërK…´Æ­h¡VSm<ˆCjÇÂæA#O«`¢£Ž9cdê01‰O¶å‡Yú¾ûŸ¬EÉZô·[‹Éú]”~¡5àÿ!û!cÿ Àdô¦]?pîcsKÝÐ2×YßQQŸ$‚¸:Ú}’NÁñt‘$‚?9¼ÄJrÛ/¢ßÓ…Áö=ê—;qVíÙS`¬ €@9†56…EÃ&¶×‰GGug+!}Çp÷CDhíÊ'†´:-êjq¤p\¢…®q¸@Ãi%OC#køίî”a¢†Ž)Üž×,ê(®’|T_€ïþ“Ö¤ü| £ˆÉ–Z,Wu%ˆGŽ@<´ (4a„uÖIXçh¬ã#à -’O ñ$Ä“OB<Ç!ž¸§nÎI8'ᜄsöÂ9£éKh'¡„vÚ9ížfw‰kÃ1!ž„xâIˆgÄî&¬“°NÂ: ë‹uZÄê$œ“pNÂ9 ç‹s‚kHT”lb%´“ÐNB;Ç¢áÅ Zî)g<цեˆÆ÷ÖãꀶÿñäÊ:М٭VÌË¡>Z$Žð®ÉHÚZr9Ó‘/gšgŸu·3§h«{™Ö“[¤éY0¬£l6‡¥ÀQOá’wj†‹ròNÍvr$ïÔ,’ÿß­™ëòxëå—zÅ%žr—•: -…”ëùÔ9 . åÕ‰½–2èÇ4’îHÞSTNkñUñp%·Pë ÜGîíaƒyþÔ£1Z„â®å|âÎÐÆ”'®íö#·û³ìh,Ÿfw¬õ §H¸ÅÂ1Ë ‹¶ùñŠ¾+ -n¦ßùçh¡ÈQÖ“Í.Ö;8}ÍHû.“p>û¦é]}†=‰áuÔ7 -åÃÐ<Œ(}{fßÓh·¢µa¤'Nˆjµa·ˆƒê‡ØâåX Ûó¦ÇŬØn÷bÅ¡Åiúÿh·~áEgÛÌó÷[ù ª½XIÌw2öf¬ÈÂÚ±Ç`bƒ^¿ÚÅaš±Í…a“¼åÆW…Mû[¦Œ©—߶÷”îb›Ãôº¦ *ÕJâ?Y^½wm¹‡áÌ*nD+Ú±:­šEzK‰:òK]ùåêŠöº0œÈäÎuFt H2K!ÀaQ¢ÑBug$Àb™SY™$Y9ht ÏG¡ðŸ4›ùÒë%{ûÄe¯/íŠÕN»i‡d/ç´®Z…~¡i¾4%÷AÓëà'&0Flz§„ujº¡ûm.s맂¬ >¨¥øìðÉaƒæHöÒ ¦ÓZ8 9MdtŒÔáØF[ã9UfR«ÇL” ˆ 2ò*C4QS "(¨" Ȳ Qä9 ¬ë>¨Ï-ÎûÜüŸêq»}%ïâLWºÅl:Ȭž÷q#_Õ+yR,4Ø;о±ª½\4èœt<„͜ÎÄsËüæP¡¹Ük«Î9ÜÂ( µPר_ß<˜Ó}4›!žGƒêØü¯°Ça 0‚@™PãÑ`‰eeQÁ:Ï¿vâå&÷¿–^t“̧·÷¼&µó]«cx¾ -=®È4¯à[ÚÖ[ÍüÊ üX©˜ÅDƒÂÝ Oð6ÀÎÀ8ì>nVq]Í(þKÃÙKÍŽðK'a‚ŒQÍ7|“ÄÍCN'@×eŠpu€4LƒLY”DE†'Ü×õp$÷Qѽ×..p9¹X)œWúJõ¿º2ï nÕ©øê9ô•§h^\š wª²ý88B 'ø4é6®s¾¢Òd)Âád<_ØwìqG'¡bP1‘ˆeH aU q@R™gdñ’þkSñÛÃÃósùŽ{î»B»êkÊ»v}s‘î;7ÙvïØ—»oW*™(Osà#n挬ͲíñŒú¯©ƒÍ÷x–Õ¦ÅïÃ2)uʸ™_ž‘=œóŠ r¤ ‰2®, aâXI•$SwˇùPÞƒü^ÁB9ó\_»ê ]²:/•KÒ -°}sÝ/ËË>o á|e–{,blŒ£è )È]o i³s¶4ÖÍð ÙMö{–Õš6í§4Ò0Ož-³4‚p0•ÇtpéU\ZÓÈÊ: 8™ºÑr -P‰ÌMÒIG˜ƒ<øüí£Z-Ü=^?¼ì ¨Giž›XÀhû3€H~&nœ²>æ\_wÖèßO3mnÆ볦ðÉ›<íÙÚâ,‹L­…‡‰C/\ - s+iºŠ0d?ÙÍ Îñ£Ûþår‡+>x½zúÝ7•"y}Ë°´¿~þ²PõJõûB%Óà:×W´E—}A«Q˜Ê–d9À7;Ç¢Kb QFãÄt1P$VU$¢rƒÅÝwý?Ü•ÇŠ(_—›èÙ¸"U³\è²Ö;É×3-¦Zí½VêNûٹ;÷Î+‹ÞÍœFc;9IJG8o°'ÏòXWuE€Â@fP?©¼¬LvwlvÙ“ß ÉwÏÂy *­ÞmN÷„~ö½u«²Àô§þl›ýBI¹»ËòÝ.ŒÒ43Fò²ù•0žÙêÞã½øP±ÛlÅCcF¡\+P/@A€*¨:À«îäÞËînæºÖåsWó®Qlø¼x]yŒîгS`×'[w;:žÅPa§ä­—UŠæ­‡¯ûLF³ßp>? ª}ÃD‘• À˜!ƒ @P”V5¤CEWxPoáàžïëu»Ü»õÙÛLÚBïÚåøмn¥oßšð‘©Õ€ì1Å¢Ò'woÑ#|pŒäUÛˆ«cºdñ ØÞ|‘¨*/I¨Á^9ä$P\³@gFgFã…Ýϧʹ¨–ÏÛ%t‹™ûæÃYý·—û‹Â»ŸÇÞΑ¦R2®P»Z‹zºâ¹«·WbW\ùZ¬ó§ï Ä‘ÖGgh6?Öl¦°P. ¯*C½ -^bŠeóœ(IêîÇ:…WŒlÑ»PËý·Þe^~¹e»FæE¥­ÝæŠÍŽ /úêSûöâÉ‹K&x]ÔÜ€û©û‚ûÂþ¡Oø){<}a{sˆ#‰ç ©@‚DÑ¿T‰³ -FŠÌBÝxïT/HÚ0trùÄ_‘²Xõ¯›—Fï±xžyª6ýlý¦Ü»7HF >É/ÕÝFž…ã’Ún™µCAû…£áíìÌ°îhÞX½§Ám$§*òF?º2‡ne ¸È«,Ò9  $¨³PTˆèG¨‰ŠLd–Ù= p‹ýíºùþÖªô æŠAu¥Pe¸s[º.b§üØ»îîkÅnÖ~Ë"gJ‡Çé¨f;ؤf!4¾ñy Æ &žæÎøœ&¤MŸ§ÔiÕa–—BáòžB¦·>ŸRa¶žÌÑ-Aá4N~ì"ÎDŠŠˆM怌:‘,G€Œˆ¼.ˈÕD:ŸŸ4‘j»êÝñìg1Ïoš:H;Å{CÉpF‘ñ΋¹G)k]zJ»ÐE‘œÓ0Äê`a*©¸™°ÇÔ¨ˆ7Ž%F—gÍÜÂT ›£³FÃ^2ÉÕ̹iÚ=oÜ"%–”mMî»L+…‹æŸNuB°Š´æ’å‡[–‡:ƒEN©‡¥k@¢¤†£&««˜…ä³,´;håÌúõ€/:yáêêMù×·Þ#ÓBšñ7xᔯ-»Ý›ŸX9tB-,›Ù2QƒR³eÚ ~"Ê1¹ŽL&íþEú¨å˜CËGç.qÌ!MÓúKZyMŽ—½ŠÝqÇfŠŽ7¥b¥¼À.'œ *Œ?iwOÐpˆëÙÖèÖÅ¡¡F$žÚ¼*ð€Pá)y«pX%²ŽeB>Íæßl«[÷ùtó¹À‘ÂíS¶WÖs†IÊåLVþ½+kN\×Ö%už·úز,Ë»ŸBB˜É@*J¶%fLŒ«Î¿’±Mš0tÒûž—t2FZŸÖ¼´ä¿&ÇÙ^’¶ªÝFvokDTØÝA6» év#é¿?VÿS¶ÀáÞW÷¹gIñhÕûŒÄ{®ë¬BX’|í~;X©þs¯–†•À—Çì‚Àbô~6ãœh_|ý6S·lBþ’¶\s‚|ÚuÞ*•9«¿–œ“´vXØûP^Ñî »í‡”ó?¤‡þCXr}× ¿qáË2¹m)@U î,2‰ Œ«T3Lh˸Œ­ Æ*ÔQK`ìÈSÌ~^¬Ý ú¨ª/x½ìi¾Ÿª½¿ódÊãÍÀpâŽß+í—†ì/â¯uËÒ•½»W% V*wGßÊHApGøù0äµ-öüÎà…ÎïÞpOðÅMôdŒÆÙ9`Æ÷qÛ[îW%¤ºïÑÁ¨'"ÙáçÚšjÁfÛ þÚ G‚Ò¦ÿ.çµõ¥†ð*zË­'±é‹DÍêÜAc½¾¿ÿUæ- s9_ˆI8_…z–TŽˆ(«ë]·Çdç 3Eì~ÞIòƒ‡K8θd¦n #¼_"3ôHWEÜ P3 Ê,r¾ |š¢1º½Šž}yõ¦‹gZ¾ÕÓ‰žÚ3Rƒé´újhîùÕÑd<¹Û·A6pÜÚ‰…t8v#©v³¤Z¸é¬e£dê ™ºê—úë¦ÿoçßo7àæþïöEakùýžlÊ#Ïâpƒç„ WÉÞgÈ6 @¹© -ÏÀa:Á¶ðÎ/‚> ·»B©ç×JÅ~ÓƵôìôÚnôXòî¡£ÛJµ TèŒ+`÷¼‰xíŠ -»À‰±ûêSî&Žý,ñÕ7ÐÎu ’×E!ª·‚uMðQ€‰© ÊT‹ó/ƒ©3ãÉÞ´ž-¿f{òäÝðÒµë³T¦öì²wZ¥óåz/=ÞM«j8IRìúÚXÑ¿â.-Dì?UÁY -—G®/”Ñ8Ø4U…¶  #*ŒÕÖ€@ %bŽâ˜ÎùçhNƒ­n<Ž“µéSãÅ©æ'9A -üª5ˆF€¤ëÝj?6óÓ´ÂvÛc*!lö0SBÌž¢Ñ_¶Äëò(Ï[¦…fHp3„ûlRˆ0ò¢ºƒ Ft‹ž_|HOÆü½m¿ukn•çúÐt¼ÍÜÞ¶[­ZJ-ÌÇ´ø djõ»xÇV‘¬ÇQâ«']¢)cGZ˜ÚVU@¬ C#* ;€« ›6¶ˆÀð‹ š>¦ÐËÈ}nLÓÍ œ4³¨o'éJváÍ™jÌ» gê Ã.‹‡HRáD/áØ1Zê?//—‡hÎhL—±8ˆTuS£‚m°*5”D j ÙTǶBÎïÞqD…ë¶KãW³l=—`ƒt -÷·9•›o9V|5¦CžÏ4íÒÂ;`HH*‚è-û•^]ž>a𙚑ƒ8°)ŠS˜ªc•0fBÓ¤6û*KBÒé“÷X¼+&»n½ ‹T©¦Òè4ÛÙ{^]´üi¯_›í  VôØSMd2ùÔsœ(¦vi°çÆ5&Žå+…aÍB +]ªÀ‹PÀ‘ª«šnéúâ §áå6Éèåµu;¾·rOS-é¶oïêæ{eÞJߦû¶U{iLs6Ï[;é$é½j"¼UÅ…ìåx<>Ê>oÉ—üu“¾éüus —ªÏœö¸¤¬&ƒ†" u[v…HøSB]é&Ô“3Å6¾ -®Á"'LNˆò×ìkƒT{Uö°Ç„[¾üæÎBµ3è¼’û³Y íþÜ™;kUɯœÃŒ†Ýbv×rgÿÚÿµ¥ “&KÕw„eßÛ»PÿyÔÄ]Õ¶»ñ¦Íæ…›—¬ü_žj:Ñ–ù¦LÚ ‡±kþbSïÍ8Æ $¯Œuõ©o·îyL›,䫉l¾îÚ?ÒB ŠÀ>gž9Hƒe`C–œè\Óà¨*rÓ4lýü.¨¹hq–T°ŽMÛ,¶ÎnÇØîXdʨçš2•Ébžn9¹ñlЮŽÆƒÚ Æ‡üIü,ìéF¦mùÏ™÷ïwó[…ygØ1ÕwG1Æemí˘¯µ"þ§ÝþéÚí·ìþ§ÞÎQo²Ú}ùçsê #]±©Æ…f#Š¼‹‚e -˜D3 ¨^ âõ&­ñMõ¶^GP¿?lÛþØc‘ªúÀï?¨í6ùPÝ…}[NPw¹\¢Í˜»x¹õ”`ÑJÏÊÃÒûà±?,ÜòÃÀ/@m_Ýíaô uµ5ÙUwÑçGª;]®KzûÑ}ʱH588~“ÚÓåCá^‡.ãþSJø”T8 wpà)Å<·‘>Êý6.ç^›ã%äË]$%b/VŒM+LW±¢šŽ¬{BÀRe'“qðäÙïóûÌD(Ø/é”ó½×VÕêú`Q]7œËuÓüCsË‹¤çÝ':Þ¨Ô|éܾގF­D½“OAÕ^ÜÎÉ辑Ó'Yê±’øÞ¹euÇÑ£ƒrMÄ#i´-Waèç -ožn¥_OnqÊyÙWÝÀºM0Ü! Dm`jâ*RLlAf xÝ -Œ? ûªÎoÙƒó¤5°*n¯OßšÕìkýå­F FwŠg£E&Aªo#ò-³¯0:iº›Xý\žgtGñ’ª(×4'¶XéŒ ¦J‰ŽtKÉzwÌ@4Çšm:¶nPŠ/pcó>« N–M>#"VÅ1ÙÏ £ydöS‹Qme?eåÙÏ(¹¹éõ$--ê+e>—òc•ù<ÝŽSgðù)wÛšËE -¥~hÔ󨔧‹i²_T_Që6ȺÞn‡ª¯Î|êqZö·ˆ‰ƒbj/…¹7§#R˜ªªìXÄâÿÔr'ý,SöûO5² ÇzA’Ð<-¹»šõ¾Üwºx„+Çqåà õÂ#ØJ4,eðg¢:A²ŸÜ]„1Ѭͷíf'ÍËÅ„Ãëè u· …÷Îúƒ‰\[ay£¸îgqÊ -b9ª¦Œ f0@™M€a!G‡H¡_£änUn£)1Ê*ð郉…üéªéís™ @ÉT^Õt?íºÕ;v÷¥è&š=VùæYÍÔ ?t‹¸XØé'Æîö¹¨"‘7È._ãªÀohKù¬Ný¬° wâ7bHŸÑQ\d*–' F5‘ -°E4€LSq€ujrŽ,횤¦}ȓ˵üÑlI¶-Æè€Ì§LF탈zd ÂsyºFš­ÙÃë€<ÜÁ!.ÁinX|Ĭ ä5ˆíåÔÜ̧Êw¿{ìG¾7f^”­ƒ¼pôÖmÎF¿0aT·e€]¯á{m± Ž*&Q#…+¿Óè±As™¿ßèwt²½ò›,/¼y.kßôÚ$ç·³À.ai²ãN³À´0©ó UÀ E6ˆÚPW™Ó0@ŒËc¾¶4S™ÌFðºñê«ÙDBñ쬣[Æd˜}˜uf98š·ú£÷I)=º(™4¯Ï]\ð*1YÇ/*²Ù=ñt¹x›ä‡ëEÜ®šÀ;À,Ÿ2–ƒ†Ã `ƒ›ÂX• c‡ØŠ¤\î¶ã5¯h§K¿d,ø•Œååá«Øõă9»Uq«ßH1Ë,=<α°AJÑÉÂ^×Ë£Ä~—ã«쌓Ùê3H,‡i‚|+Ö[WbÈ"jé¶m‹1fÕQ®†åhúPåxŒ½]œrU#z——ëT¤ ß·ä…ð²°æZV䩵lÔ¹ÂU°Âd… Ö€É!–© #Ò±T¬]îŠô@-ìûÓÌË}ئÊɧlY¸ØÙq£ÓŸ”T%õ¬æHË'í|]ß½‘ôëjÙ`Ü>szOãI©“*8“{gJpƒXö BËF5“~â…Gr×wï+#»…A’v«¬ÓúÑtøñ§Ê„®Vv`¥ÇG[5 !‰0ˆ*ò¦  -'Ät Ùxúšho?N:¹b°|׌ü]vŠ:Íúói½Ûó K‹Í© ÓàýÔkn÷æÐu5I,Àr\"|³Q­r\¹Ëu!ü•ãñåÖ Mv]£Üì`@,û‡ËQ¦YÖñÕQ'à»r™N÷®çùÙÁ,Ó©;F†Òáƒ^0`ÜlÃVfgéöÄoÿ¾0Úo¢·¢ÓÀ®¸ò‡ï7 ›þŒ¿UEã¶Í  a&D´† –iF¡ø@7 ׯʴg:é½-<à !7óOCPêyh”îôÞËïÀTú¶+Ô Ïå3Ó¤·#!¨aNnSñÚr¥ò}1êÙ-Y¾ÎfÇÖus3Á¢Ô‘ñ È…;J¨*7MS bî?§ùä‘YÜ–ïÀtX¾·xJ§Úsgвî -¯Ü›”mLm;ÆÝ#XÃV‚ñ›Õø·‚Ùc£X÷&¶;3¦\EŽ ÃB+6‘-KMYt§2¡‚-¦°o‹3Î$ %Ð)²åX÷ ýí¥„­*IòŒõîݾ=*ÉÆëºÓ껾=ÙÆyI±=.^½|àfuù«¼ô¨=Ž¿‘´>îånƱ®Q,$4Au…jwµ+Š…9dú³}Úk¡þ´0ß_<µ[{{Túr"“yúk'~"6hÇÃù Û-ÐP£€ð* ºãU?r½.¦>¹·?oøLÞ†u¼eéÂtVtÀ1VR‰ܦA„•ešÛB|óóù@+OE…S? ^P,>vFùRqâfS¸–˜ôr®ý–2 ü”ïXf}Øœ/ôÆíËn®~ã§×TÛ“Þâ©jøÔ|j}wÊ~ÓÖ{¯þÇAäX¿‰Ø\SLdê‚™MNU q ZÒujßÂóZç° 5YIx\¾h7Ç8…;Y”Í÷ÔÇDµK[}6¯¥o憎—9%»¾qŠÙ Ïn‚-ÔyòSÛßëñ¬Œ,S!&D€Y†p˜lfb#„—¤0‚ħôxV>M7ŸŽi¿”M7¸ûÖéž+žù4´S(Y¥wô° &æ)§‘u~¦õ´ç+­ègzÕÄàÍêÔé :^š¼ -sDm–hu<\ž+ïˆ - Û[_£©‡!™Õµšû1šp@£Ý¡ÛlFeÃÚvp"uõÆÿcïZ—G’õ«ókNÄT·î—™‰àblÀ€mŒÝøĆ¢¤*@H  `GôsœÚÛ*Ý@¸±ÁݽgûGƒ[Hª[fVfeæ—dÛÿ#ñ™¿ -Ç̹[’ôÜmkQ6A×@KZÛ–)ÉZC¤¿Ù«"dˆg2c–)Oæ=k¹ØYz{Â%ö¢‡­r/K£ÑríÇá&¡•^ŠÎÆí|ä¿ör¿O°½Ètbù¤Ϲ6²³ïäøt5WóÎ ‹-Æ -@vƒ•Úòós·?ta‹Ž’Ô¼]†V¼vé5ê9¦¥P²¡ÄÊiþÔ˜âa~%ýg?ÀóÜ=ÛÍwϱô7p][‡ù) -ÜÐ˽3\ÄÈ;R k‚ -4?7%l:Ktæò„›ä}D÷¢žH«ý¢Ä+Ì$ÑJYUg!á#?)K¶¥[úþsî‚NCêf¹ÅLÊ+')oZÜåÃ’e‡ÕþCØO• ˆf·N«Û[íesíBû™­u/†§Wä£Sö‰ -hÂ+ÛéK‹ó•½dŽ2˱ªKG¦d\¬i´.¨¶ÈÇÝÉ”Ñ -Õ -ÕdÑÒBu”w\7È* è%§Q‡ -BRæÝ,ÈR¦ÙïÙ'¦h$W‡L0·þtnõ×ü£²Z/F]ÔžкƒæX_v†÷£îIS‰©WŠG¦I(ž»Ö²bq¾}LXQxxé{»nzþ3²GCQnžú½úÀ¼{fÁìIí¼\éâi…caú)ùŠ2|5ZâHõ‚'ö½¢B€Æ*\Š¬óÀ4e(qDÇ`ÓS÷÷›l>;–ÖŸÈúí^ î/ìyêÒ¾™÷YézÕn ¦5‘Bá²yÛzYzbß¹W‡ƒ©1¼|œqã´ÛÂvÑ>œëfaSÛé\¹§//·AŸ1tS®Ì¢”þ‘Ææ¤|J{ÐŒúCß›¨7„ßçi™Ø®¹ñÞÉƽlЦ)à_¿ÒKû/&»&èµ—Ò¶^¸€öu²I¦ë_:ñæI›àJši~àn€¼ªF?L%zg¾‰^H³éuÚ_ÞD—,|u 5ªb-C7È|ÞT¬ÆchÍ“z¢4&¾dú¥äñÊáEÈhUJ—*~ŸXÞß{B{S’Ç€ìÏFÔ§¯)T•Ž­¼ôg)3>ÛØ'Êžîæûør&Ç£7ÐéŒ]ÉáÂv!ʶ‰=ž¦Œx_Žw…P·cÊdQm_7F/£ª«E׃èÕ~Âs¸ÑbÜ£l'‰á’6"šd¤Jo¹ƒLÁÚB[E‰º¥ó0g“–Ô¼xƒ°%A1KÓ^5€bò2àÌ!ÅP%Q:þœô=Â’ß–Ù>RVª’lM§òB²doílÙc”ÇÛ&®4ƒãGÕ 3QB°Öê_ºû²’¦´l;ù³IJùÛ’2a£ xÖ §i5”Ù!­¿ÕÙM³gTzUß^‹Rdþü d 1…™//þû$±ðFI¯•“©5À'2äÊõ¬ªóÚwåÿh™]XÁÄ]Gú9Êú%ÉÏ!Éø9²”9’uÕˆ¬@ä:£ÒÈŽœ®p -yé Äz ¦Q–òG.¢0÷â ?©åNÓ¤µ¼®Ùìö$OñÒYZU•›*þ¢31 ±k-±áuwêÑí,¾”OJ¹*‹?÷Ëʤ¿ äh'4ª–{ïIåÑÙ¤'{åÑ“LîíEÐãU·Øœ"¬bìW;§.QÔ}Aö< õбLÅË '@ž(K†Y€@—¨*Uh°"Ô?²<iR›2Ô÷?ºŸW;Óž×–ïî$f´X®ÚKívy×#¬ ”âxGy¸«/­Ç]´eü¨Øá2¶Ú‡)*寣!’öý+Y8Ú±ÜÅ~?Üg!5á ¸ãy8g/gûHvQ9C’XbV°˜¡12 /@׃ƒˆUø0m‹<;D#)$)¾áý R}æun²8cq{߬iv/TÜÓ&|h$€ìšoÈ«kÜ£Cá;ÅÄù·o6Çåpÿ?ÙdØ°É”¡É-2Ë‹u cA+" #(1†Î‰"˨â‡r‹TÊ-;[Ì[æÔ¸cÿeÐ_÷ü®›Üox˜ÝÈÒݤÑ7“Þ0\¿Ü}ñj'(f+_¼Ç6Å­à,œ£d{ˆÿ±›HþÀ @ °š•ùéúÙЧsoñ ôþŠù¯ðS?yXÚ¹#̽x‹`¨%>l+q¼‡±Å4U,}pž8' …ÍSIÌh1m?Bü%º4Œg8óAÇužçn˜ù2å Ò8~e© (îù¥CxàH E#“€"BH&š§`tr³,V…EgJ%ÄàÊ{¤ÄÖ[ýŒÛ/“ª‘¿”œ7õþ*œ6õHà ¤ô奓–4ûg?OprË7J€íåø}˜Ô£¸*ÇÚÜ‚ÎÉ2–Ãë<z - äÖM I¼¡È"ƒãô$rvOèeIä[«¡—¢F½"ó’tqaÁòiEv(=´‰Úù)~Á»àÜÐplj:Æ.¼±ž;®×\1KÖ4Ú‹Ç+-|º_bmã>´¡á•z=€U*óvàpÎgYÜçÞ·#ñòó…и(3 / GÍ*¶åŸè‘wo ­hòg¥:§ôÎÿ¨tñÆ2ÜJôîÊou¯0! ôG¥?±Ü,FS÷OŽe9v˲{Ѹ‡x7‹¾‹µx¾ hKéZe~þö£Òñ[l½¬„ ¥?'ª>‘ \ÑÀ>-.–”&¯—šSÒ>8ÔY%G†r¤ÀàLYWeEF0d€9 DCPFUy^ùØ*ÑGœ:àrž#oèëI—&«Í¦1ÒW ãê÷f¯Uëé7#uÙ¿±SšÕzƒÅŽ”Ⱥ˜ƒŸ9ßyCÈå×aû٣1áH618j2¨ jBºŠ (!‘á°„xùØ$#kžÝe“ì‡ïí`\Ë;·WvJW c2šùÄuPƒ…c¦:X\>Ó^k§\ -—†é—týБõÞ]¥\ó-ˆÃê›âûv‡ª0#7ô*+Ë£qϸB¶Ï¤Ÿ~ -ÛâæA©)Bk@$ƒò?c“”¤˜s@8àÏËM^nj¢ë´ \Bôå@›t'ÄT&±i šÒý¢¨¦±^ĘŠ;ç¸1Óoטâ§EâRK0ñÝŸ‰šOðÄóºÎ¨4¢ª„ž V!ê>Ö¯«5%òOÿPzÞ¯r!ûë‘['"i2Rnûb¸ö„æðna›Î°>´75ÁBMåñò¡¾«¦ç#>Èež#æ¢sù çm»# W’)#F‚©ª@€ Œ%@èU€º¡sœú¡„›Kó:™j/jCW^ö—Ðz‚·Ú]]õ¯GbËmt“/¬dù¡u5¨Öç;þì6æ få/Q{<™¾ÍÍ¡Š‘tB©oÚ!8I‘$l"ûˆÌë×EìûÑfAÝêfþ¸=µ†f¿>|nÜ®0rÄ»Àõ»ùEkÝ›¯FÓ]]K¨õläÍ+=oÈÉìRÏä)ïÅ;}gjf¾5¿ÝÊ+P¤I@D¨K‡¨2V¤@!V6䑽|Nö¦I½*‡½Ÿ¼³/­›ÎÓÈju»S››Îf&*w#SRŒ«ÁZì=ÝŒ´ví¹{q›ùü¾Ïçq#K=ý¤µÐ³´‘ÜßÏ:f³3õÜ€2Û6Wi¾hüç34Î$̵À;ø™gäM6ÉóLzW†ÏNÛŠ?|ýÙ¸ø þ@5X,³"U åP±I´(,èÈZá;*P'ÃÂ<.úšî+5_»qŽ/;œ§"Çe@m3[â…ºþUu'xÒÜž+òþ»¼JUêÜyì¼È:%3%šW<[ÇñøÏÛ¬Þ{@Ïs"Ï’hà1x „,P, ’Œ‘ |„þõ†Ýêý'îÒ <Ôš–ݸ_ƃþ=åzs|Õ´ $6Àlygm‚+E½LJJt|Øaû¯ýê×~µÏÈZh}ód9MdÒDLZ›d¶âKÉ4¾-¸ƒuº–ÊÇÄç¦}ûLñÓªOošBåºØ/ãõu NFwŽ¯É†Â$žCR{‚–_:¾°jL0¼”.NÂR¤‡#Qí ‚‚.ê@”%ˆ3ª›Ô M•1$ÃàN÷¾…•K]~¿QZT[®Û K¼ô×õ—Çé–ý^îÛÒ‡A¼MPòZIÎVåê¾{rÌëxE˜9Íωe6½–<–\/@%nˆƒ‰=we¡ÌãšB-•'›æë¹¥¸?{¡9•ì¶»Æ(k‡Éþ†• Ñ]ÐTþÆsòážýÏ°L¾ô,}¸’\¡KO¾B»B¹ŽüåÚÒ7/Hÿo[äÙô# ˆ|L¸Š}óÉ·|‹É·/h“íÇ:äËš+¾gT ÅÆ[‰6¡ -¥gï €¶[¸@ ;¾@öƒ±ÿiÀHlü#U's³¯ÅV[Ïcþ7Ç5]:ƒ[žXÊFwDï/Yݽ;NY^yqS'f†ð¢%Ã+éKÉ=§ôF9Ø›-ÞLè«·h#ߪ Ó~ÑKÕ¼:•œƒ­¨æm'jŸã÷õ¼X¿RŠ›1OࢄxÝwv­¯ÝµzeêçÎï§ô£¤ñZÊù6r¥enO -wñº¸Œï8s?ÏËh&Ú³e‰®}äþ˱&¦Q f$ HP:G¬/AexY5¡)¡Ókè¾Û:Ãi[¹·´§öÀž\våB›OÚ7@™ÏoïzÚt×tM‰;³Çm"…bJ§ã€e%ÒHÏ”a^ñ?»yÅ -êOj^½fù¤¹dÇ[>?’eÿÜébå[ça4P9 jÖ^ÛÉ8šûd¯á³¯ùw­e×2pjø¾U<4­›i—D5MóÂfU®I÷×kÇ҆Ɠ>Ç3ñRÐ9´¹m›êI[IµÅƒ“ëÞ|–I½õ -ÓxóÂQ^ôËg?ÊÕú´ˆcÇ(Ü@ÄÚåÄÖ§FHÄZÁÀZa?*à‡ Ò„ïkD³›inDåIÞ7y3ðÜh^éËž¹À`àÕKèúu›k(áúùb$b¿©Œ/Ö瘼¨T¥M²÷çO)Ù•^ÕEQ€*J:d²!鲡ÅÀ!ÕMýGíJmÎaîÍ—ôñày3õ%o€Æ›ëé@¿¯Ž—ÏëÞFS%¡»»+EÉ -Þ~ºŠ×ô‡Êï‚ÂüëÿÈÇÿüï<Ø4Éôny>ŠaFHæ!$º±ŽhÙE¤èK¤;ÈätVâÄ¢Ì(Ü>êÙ,91 ú?ŠÂIˆpãa¶-å‘áÈXþ*¸kÒKÔµHÞË÷3‘Ùœ˜>áü8:c A¬*ž¦Ç  -@°/"AUq§# ¼ÎFjoî<]Ý.9¦:<ß÷ªRÛY^»m à´'—`>l¢îžöCO:¢IØ#49†l ç•ß9ŽPùxÒt„LQ½£E YPf(zo@r"™µC”vܳg¤42–]J‹/}¥eÕ[#6¨@UǬI¤¡3Aâe ˆ& Å‘‰$ŽÅ§£¦½ØŒºE6Ò«ñõz*ºóK^´ýŽ!\Ï…n Í #˜=¸ ÁµÅͱíV±ÍÓݵîÓ+¿³ !9òñɱ¹Æ© -P$Ž¡Ðr*ÐÉ#À0tÉD†‘eõÉ÷ìI.®x_ ¹øÒYI.)Pñ-ç+=ÐN‹ h1¸¿æc;9ÀzŸš0Xv¡÷Òšnê|SAO®Ú¼èoÌe£ÓÐ|ôȺѼ`kUîå´z I­¶×Ëb¡ AD“Ç’Zz“ñ¦aqýî—úÀø2ì_F­† -“i_Xò’ã8°ûØÚÍÅòéå’=ðò0%!/\™¤àE‰C4-Éä‰E@†C@‡²"é -æLæGmKUüÈ.cíßßVëÕÇËÉ˪;sº£jÛ6žBfjOM<ä]ßÝ•„)ª[„bðo¡ AÊEFlr§ÿ÷gjÑ»£BᙀOs%©Êœ–Y­ØÖ W¼öÿ¨DjsÅ#Ì}ìÓŒOZ,¢²pýÀÿ”t&¶D·yˆ4Ú™(óT§÷s(Jôzªè硘èÖúoö®¼7q%Û^k¤™+M¥½/ýZw !ìDH¨\U³ØŽm£ÜïþªlKHzZšù' -ÞÊuÎÏg©:Ë6Ú˜ZA°®’òøq÷£{¿mÁÓ‹ÐÓKàÓû&òˆZrˆbPý"q25Ÿ©TÊ&ÏcY×ä^  ÞA½B=Š¡^ ¢^‚¢^jò½8ê¥Ô‹‘ÔKC©wK½L½oåY˜•îJµ.š–³£F°€Ü¼Ž„Gzí›P¹ž4…V6¬Ü5 ÔKàÔ‹ðÔK\Í^²wÎè?–bÛüØœ¡¸ê¥TUzp -có¨ºB–0wqYC럆†èg ù{Ö ®Xfæÿ=ºób30T/FTï[ïÛš|iP½$lV½®zûÀê%jåÛ©Èò°y1…®KåínúÙÅrÑt•— C†(°z4¦t!àΔ É„ûŠ2}üÛ5`¿¬ßìªE”îÌmËù‚ã-…ŠûÀ¹•êÕLÉ­ŠœË>>VËcc0îPyí÷½ÝÞ[yµT+›ºÿb–lc- -ǃ?r)’ðër•˜íÛ`•--#‚¶Q¢EÏq ¶»ç7{Rç<®‚7\{íÚæ,=·¾ó¯DŒRè±i¥Ræ“×bõqé±8˜ŽòD[W’ïQ<÷Øl;OïÎ965„âýˆ¸öMáøû8Eý¾CŠÊw¾¯þâ}+¶(%é ïg,~ˆSÛÜ6cë}³7·ÃY0ŒvÈý¤R@„ M¤%«¯Â þsŒÜ´@JWez§4B˜pŠªˆ€çxê[i*u êÈ+<°ˆEr_Úëè„ú¹§ç¸\cǸ!¢ª“ü *0ºófTPÝüSaÆËûBàv¼ÁØsŽ¤p¥Í­#BèÝ…¬^•@Ù%J =ñ©’pßÿÊŸßSþlòPÏ;oÞ~@ìüõRñ½ƒb[¦Í‚W…—¨tëÛC Û÷µX6 ¹\|ûk 0Hæ_0¨=·ê vx´?P\¢ÅÌ’:»k:+,Ö|sñ6!Eˆû¬n óÆÍFv3ÛÞÁ.a;ýmåÒÝT›=2ƒúÛyk&{êä€uL—˜"6LÌñ*¼$A%@â -U‚'ˆ˜W¿¢\û ð~¤*ÚéŠDn— {"uˆ?_=…¦«–ì<Ú:X,½ÛK[Uܧ¹[¼Ë^N\«µöûêž½ªA:Ĩ­IpPƒ(ÿÕ ÿYä ×ÿxÙÿI¢öE’ãÅ‘lÖC2×PˆÊñ¢‰d ‰Ñ–¤ÆCб¤êP’¸ó«Û¾Ñ«ô•º´Ç¤ïÙY¯ŽŒg‹°ÉçZ¥¥„º/•×9,•·:º5ŒZ¬“É/ª(’$\½ùœ”\Nßùißä\¾×–Г±$ "ŠkM *à4q2ÒÎdx%¼ý¬ìÔV±5™ºÙ »•B¶ŸåæŽ% ©!WrõÅíܺÎÊ¥v²66„zù— L ÛG̶06»˜S˶¦³iáxxStÝ—Úý˜”1T„$êuÈGñ6r ¶¡¤%¿Äè×úœý’’_ò:w‡ýP6­t)G6ÃRÍúßZÿaÙ‹*ðÅʧ©+a’9‘¸Kg0ˆŒ–ÓB!†óûå-_¹%|…ëÇ…Ï=øæl8‡y«~Õ·]À D¹¢v ÞuÁ.üåìjUåž.KšÐÂùeµRñvºäñú–c)²í¡‚ÞЄQÑ!ñÊ¿ 3û$i9Žr¢@4…ð@Ñ$pyÁøAQ¹µl¥Ù¯ù7jÕ‘4.¿lJJ^R®+ZðT;ÕÛ°¤¶Š—á®´¶<Û¥Ý2è[¶×ל 1ÞêË1’˜LHðA‘t‘Ç€ ( §¨R¿D×yÄ!ÄÉ©.9ËI}\r£<_ž åàoBmV%¾PÉÍôB¾"-j ¶oÚWÆøzùmŸd{ ˜æg¬CÇvñÒgMI‹£ÿ5@˜Â1u+ âA54‘£æ©[*Q]¨¥!SUTˆyYRøÏëRöÙh𫆠Ü4CÑ,ºñ¼Áuî”þ°ò4ê+˜÷æÆܯ\> áÎz׺•ØºíA‚¾B…^µ S¯~'.Þè‚cfŸÉ ¨SÃSÇ&ƒ‡ CUÊ›Ø4 þ«×/N‡Ç$_ѧóëbv¦5š€Y®*5=5ìÊ÷5/_[> ¸e¬ì¬Õ ršk;”Û«óð ëëß ‘·û5 q=gê|T—èÄÐLŠ`"ž­–cXÖÁ©ªBT,Aþ÷]ð¼ãùËÖ“U–pÙ¹“\Éé#®Yì„—Âìm›èP5]Mß]ðLvÓwh¶ zY-¾bƒÀɘý?³^zn9>Ü/‚Æ)F¨Æ‰@’Mj„BMR¶¯"Š¦Cý¾fÆį G²G ÞwŠå\­Ø-v -£N¿Vëî «LA {¨áì®|nxõgõC†Æñ~ >î£ò¯kœ¦“ç*$X:4¨·*è -«$%ˆø÷m½ä»þêv‰Šû8m@T€J˜7Œ! +w C$³fxN©88\žüÞé‡0päÑ¿ÔÛ9EUÈ&‘dUB,±E’jê@S0ëÊÀ«º)ˆ—ÎO?ø*Ü\ºÁÈ6gÕJàãr8OºK§: Õ\«Ô—“q8Ùö Ü®¡¹^òߥÚ.X‹ò™:©|(ª(¦×¯ŽøËrŠÆ@¯`"›é<1Yî1§U D“tÓPá—®e…A±Þµš¾»(N¸IXm*‹~)WsçÅl-¬§üÝmaÑ©†ø>Ø]³HñëC ‘¯òå ˆöê Æ}Ï™¬Ñxe…Z~@‡tg,}$Š¼ é -…… -Ä«è¢AO]B¢¡Šgž_h쵘#1 “`óx9×>·[°¶‹Éá×鲋Í—Å8 I&›¾0ÃÁ¬Kv&N"&83Kí²îÑ™‚wø…Ž"$ÎÿñÍKô« ¾C’OPܬ.~ň‰h -ÏÊÑ3£CV.@(DG -2tMP¾Ú=} >†îªe¶†]ž+ê êúSͼ2noCoØÔ½ríÞŸfiãä0ÙöÜúÚ—ì¢}ìüÃÿã½èyu¸_#a´™œ€Þ€ºÉA$H†ÊÖÀtðÚ,ŠŠ!ä~ß {îÝêFÁš¬.çSÁUu¯nòîeVÅ——íQsØlÊ]äÛûk`Gè¶gœÐ¹èª}Œd ŠÂo?€•×þ5`ñ"[ë\‘L}ÌLÖjLSy@=SÒ4ãüV¿J#%*Þ$Í.:dqcºÑK‘%{ºf¾Øo£œfö©ê # «@1ˆFÕ“`ƒ1‘J ÆQÿRÿjïøtáÓ¬ùí®ßHÃ|(Èb³åäé‡ ûá¢ÛMõ¶e«ã]¿hmþ Üž‚Ò˜ákœ­¢Þò åN”Ô`­ä3 ëà V"8ê=bÒ—Ú„¥ÜýïÇy²RDìkiUóÂÉÕ Ð7Pub"¿ÛY˜×­Õ(/¡?n`sð_ V;2¯¨ÒGü¡3Ùæ°É&͹£l†þz¶…ñª që°ðÏc-kÊÁé -ÇÒXƒ“ÛœÍ÷µUéaµ¼*4;£°”ëÌnÂ!&+*}غîZ6']}aXVÍ‘âƒÑ¾2Õ™Þ6»æe0RTÓ䯸ª¸åùAÃ0UY’PY96ÙõåÝluñjÆÂ¥¿—ÈÄ·ì±õâÃH#Ý>Õî†^Çx’Ꜿy¶•Ôõü(éïõöÌë -ÅZ‹“ï:å¢n -ÅNý©PZ¢6G+ /Fn¨vçSHo™æLF¤·ã,¥u¾[ðµlâ÷'⊬SÛ ŽOÐ/ÓšlÎœ@¾í)¼.;ýyEëËåÀÇv0Ò*°ª·/KÝ7¹S8±æwÎë‹“€I“#«‚°W¾ræNø²Ñz*GÚDm¢v“ÙG}t¦®ã%kéùïÁÔe>Ÿ:ÙŸÂe¬ºnÈÅ+Ü)Á¤ rm=¿z0G†hd«×O¥ÛÕð–Ë /'Ý¡Ò—/åZèèö)BîH³Î5¢Ç™Œ­ ÑËüí„á™×)Á2¹„OÖ;®%5žÙüˆ¯ÎÌEyÒ÷dë›ÌAÜŸ³˜LoJ|?Y×é+þŸo$cù*ÔX1½I˜™Q#Øˤv‘éPrèÌ&8c KïÌDQÑ“ð"ÓB{ÌêGmëHQ)g±ž ¯™àb’+]Ëô -ªZ¼Ê–\±®X–¶h£ÂìA»ÌëUoæ˜Öö)´$öì"ñÒßçÖJPC’ÊC`R³H’!ÍÄ:0!'  -ú„Ú§E{Wú—Cwü|Ø®K‹{®8h÷ïðåÝÓxUÑTÿv9‚9\éS{±íÐààÂzj%#ÃØ/l'QËì–TQq:–B¾^se~u€Ó+" %¶­Ï©,÷‚—Ì“}'ÈñH1 €–€dH@ÍÀ›ºÊñ‘žü›8éC÷ÊòEçZë×­~gp}/ÌÛ¸®ä›¨ÄÝ‹f6lAœ½ÝñåÄ—ßã£ÄÇ7NþÚ­Ûg"‹¸I_È. ?ΰ$ ÿ˸f:Np( õÛ8EQE‚@ eÖ³EÓ¤0/h‚lpÂù-Nc›z“Ž¼ÒWx ˺¤VýS·Ü¬ÔÍ’>i6šU)ot -j¶°ÓŽž%×F$Øå=QØœ8Ä.¶K‰v;®ZO1¯˜Æx§è‡dPЀIØ - €  ‹¦4…`M%ª ñçï.œÆ©ºÐ€âÈt®ïÇœ)6GË›®Âa£^¸¿Ìîê!_¯Z`l;ÚKNI¬ðÂïKfn–±áܼö1÷=â˜ü‹¹ÅÌï‰W‡ØÅ 6¶ÊÏ+H2'M—!Pu"ð¢Žež».s0¿çW«¼-Ýñ~Ê6ú¹Y±:Ò²…›yk©^–'}­ˆ–hOFØ[—ýñ­µ>~€I¢ž¨=vsÌ¡f“Jˆ1ÕlF˜Iú |ç\j®²¯ù …·.ƒ õ?ÓYánºÊ3áríJrëª#Èß.›Ç‰ãÄõD|?µÂ1XYI“¿"n›Ðú«9·]£¡&£1YO8zæôÆÔ ÄûÞ»øÇ¿~ËàÙµÏË|¦Ó¿Ïtüç‘ÿl!çÙ_˜ÏædþŒÖ³é…“g<™<“%y†¾ûÇß¾[ë•G²D“YT:5áøÞûNGˆj—Óç1-"Ƚïß׾˺‰ŒBáðóòÕ\ë¡v•a‡ÿü™ü%ÿù3*¶ó'`æÎ 2jŸàŸßãƒ?¿Ç—°j/ôrþÏÔô×ÏÿgïI›G’ý+ -¾ì--ßÌ‹c t› ˜c`™PèÄjdÉH6`&:bÿÖîÏÙ_ò*³²J%Y ÌÎƾÙؘ6:JU™YYyçôO™€æ8/‰çìd_Ûø õíÁJµˆ=îÃãÛé³1ÀUÝ{Iå~˜²Áù°?àdá~[CØNcf…復˜!‰µkTßdE° †«ä›'½Óízc¿ç÷woÎOªw}÷ññbüpg_·Î?D9MÒUÝH¨8Pä…¹äÏÂŽVAHfãe0„]Ÿ¥ ÿˆ -¡Rð˜{BR^壔˜ÓðKûðð¶ÑšŽýÇym2:ónjýêåõ9=ë{Û°»w‡Ûï+ÉM°ÝîµÃ6šuÃÑk6žÜžZ®¡û~­Ùìzv£]·iûÈöSl,åÓ1]ï>;¥‚€çOÞ#oãÄ¢KÆ7V†“ÂŽôj]Ü„??ª Ò1º‹~ÿ@ÁGüøäEÓÙw¦L³ <Ú²r%Ïè¦jñ`SËÅWá‚:?„˜pÞM;Ã3Ç ýÞþÉŽL¶ÛÙU­ë Ã;w·õ4¨OÛ‹»±ébýø¶€‚F€Ù¤ó)&J†J˜·oY­?üæ%Ýqoûò2²û{çW»WƒÁAÍz:ݽXÜtW·»Û_üž}ö!G\må&Œm«Äè#x†Ï1jMÞ $òI0ñ„' <^¼ƒÑ}äV&“Ä);à+ü\í"I°jñîW¢ª:/µy¤”ÓcrPÂ%ž†ðìÈ”8ð­Mg†Íy©]X³pŸ8$IÚ²MªXUVâ€Ç®-É«”±K§Æ;Ö´vÁ”¤wÖ8º·½ƒ­ãGk~|×»ùö:³{eôÒÖÓŽÕzº? û[ï3ãÈ2W/´´ø£© zyaU s¦úu²ßD±Ñ(ð’IjNÊÐbƒ¶”`,kû!¿N­‹Ó–³çÔfçÇÇÖé5û¼³oõïÎÌxq²˜´žNC£}XéÇ€§P앧…×4n§©w ÛÒN­É¸nivµmµšÍªó{iá°ùœ4ÝóAíhºã}¹JGCÿX¿l^ãÑö׋Ž~pà·æñ$-¶n`?O©2Xd¡×ÉšcËÒE«Æ{6À#`ÕºIâùTÝ@¶K™ŒÁÀËn²]˜2uœ=Åv¯w'lh"í‚9ÝK ¼ÉB©Ý¢sy¦½ÇÙ‹MU”º+é|2ŸSÖhïmΦ­[ïÁn·O¶†_ë¦õóÁQ:íL;íÛ©Öï'ýæÍÖþÓQØŸ¿ÏÐ?‹çIÿÂ[ªÏƒÂ"72.vp» ƒé°¾îÛPŠòu­–Íd ¿j[õªßh×A‚âI®) D\êk”>Ss\‹¸’7ôšpô/‹«‡ï¨ó¥Õœn;wñSäݺmëiêuCóâ4z4†ÕkR,®7&r:ÎÏ5ãk2^oœ³û´]ΚQä–´´~Ÿm‹ÁàKΊ”Ñ]Sv¼0j]¨¡†H­À÷°ù"L:F<÷r·ìeÑ[B BM6fÁ”pS•ãqÀ™€w¨ã¥Òò3|…Î'‹éÄ -ö5Þï ‚«e’£ôô“ÆĺÊ'ìE‚t ±4ŒHªh=IÇŠ0ÀŒmöVÀtñ 6ÂÃ8€n&‰§…jäc/ñÀ}%ÝÊ|Æ š!@ÔsKalB°f³$°%m“…åë¡ê˦Oèì0 *Ä-¡?t!p¸vU«^Y8 R–•³ü— ª‹<âV§ÜÓdþg€ "0ÂÆ,—ÿ£)‡¤fE®†5‡ù-'Œ#ö~P`š›ÄSÝ"qƘãD÷L›qL‹q´´uÁ¡c'¿ŽÐógÙ¦} ®Œe\1&–ÎCÞRµ¦Šn`/ß\å®…-`ëCÜš2@žWðNÇLÇD¾•Äªh;¸…þ 4¢ƒ¼ Pö‚g±}¦¨ï1… áâ“6OèÞ,ˆí!±e«hÃDýÄ.ªäm†ä„0šÆÙ7ã(dƒL=T Ë[¦èOÆÉð%°Îè °`…ˆ7½íe¶× ƒD 3,|¦Â€ëqË ÿ)Õl‹MÔŸGÎŒ2k·öy5b/jý„#I`-C® ÃÁù“Ä<;&N 我=?$Ô½Gl„¾d2‘Ú`ŠZ2ç‰|/2œÎÚ„k¼xø¾ Ûæì^¤Ú—^Y ò†€üj’í>G²ð}8:œå„Û]›pk¯€ß3d›ÛÕÔ;°\6^ñä:áïHy3:øk¼×ÒhxÐX€TùoN£¥*™Ðð?@BÅ Jß×y«Äk^¿ûÍmçS»ÉR -†è±§tv@P¢»×Dñ -º=fÑu -°dóPüT*§àÃñfÎXÚŸ—­Íy©g=K…ÎÕæaüØ9‡ÉýUÑò"ŠgŠQ<ËþòÀµÜ$„u‰üd1ÌcªÊ¼2ñDæ€â$Åy1aòM¡ŸÆñÓÙ¾_}Šï÷Žë{ÕÖe7™ûOO~ ÷/þéi¸ãïíãÅûÌ_˜Èæ‡q\”Ü"÷ÆN‘ȦäâPº®© Òfž5‘\›Z{ræ z4­Üœf@.Á_×ܯÌÛë¦)V -g+ðf+è¢Q}5]à0xtˆ‘³èé7Ñ 4zfýH2`XÒ±é4;ˆ$9d­Cx!’ÅA)Œ&ßB´B†PøÉ~÷Ê#^ƒQ9ΡQÑ3I1–’í«ˆæOo¦8O<†3“ç4\t.xr¢1@0I¼P”êåN·V*†«‰ÃôsÙ¸…#½Ð7¸xÌɈèŠ+êÿ­ä‚0B2!!&ŸTaŒEv˜û®c6q¡ûsp›sÛ.V -ÐÞ$Jà(Äw6ÈÙg×¢À&P`/*àx5BË鮫Ò]›lo$1`”º’üÏñ®|Ž‡ $Ï–þ ²ÿp"k(G£ëÍ@:^±5U'tšT¶‚¸ 4,~q1®7†$éã ÊÎÈe1ÑÜ41·Š6R”ƒ•ßòTÌ%žãUÁ‚#†aáVBUNlá)ÌíÑŸ–éæŽ@Ž¤´ÚÚÝ7£Mû³0 Ž¿p|¢“q%>Í̵ŒÕV£©_Ä’ç0TÉv284ùþý÷.¸–¹ë±ŒÁýsgrËx†n/Ua­ä,æ$&>ñ_/±ý^Ü‘0  —l5ßA}‚©üEQˆÞlž °‚Úže’—¥ -`Øhü5%ß· ÚŸé‹b­Íl­\ïZ¹Ønõ½‹XsµïA­ø$-÷¹  7ÅîL{õ“a|_7†;wó“ËÏûöc}4u·?Ïﻡù´7;¼ÆwnÿM~o7ø•W?zm¨¸ë¸ÍvÃЫ:Ô¯nùºÕjµõN½Ó¶º¾×´ï¯~ÿ¶à¿á¤µ»3lß_]Ü ìó{ÿqæÞ^xɱqt|ÐH/ÎÜÖqý*ò‹–kò¸ê¹ôÇx¹ãšA–µTÄ€Òâj›S/™)YGß[GA^G‹I<mÔfÝjtº~ÇÓkõFMot,†8·Óлf·ÓêN½ù{Em~k>í ݽ­»~Õ>¸¹³qó̳o§ÉÞVçÆ4vþr7ö§{Oq!C­¹†%œAn«¸©­l“W@ZµiMµk7cN^šfõDG›E5ð.P„XzfI•—LžvDÁCMeÑ¡˜¼uå-`>àáåm™,£ÊˆhŽMñ²‰| ]ÍÙÉÍ@ÊöJÌÊåÁŒ%Øvµ®7jnSo´Ù:mßÓ»ÕnÕpí¶cWß_©øm´åîU÷íÃÑ·æ]ëçó«Þçt~¾=Ý; -»¼=|MΆÃiÒ¹,c -*,– *‹ª”YíÕDÖy™È òd‘Èl+ œ×Ò¬j§³Ü lTMaoƒ©¸!Egaöe¶¸/N>HÝóRéöþ ¨vµçªK•>r<¢«°… B¦U,¨Ô§Àù•„>÷¼‹@R+¦P¨FbyGRv¦o¨oåeCIÍÍ¢$%“ŒÍ¦E™3ÒÝ|Þ¤&—¬TþÔ´ñnYŒg'DÐÊ+œ¼Fo6ŽùNeé®vƒ“‡›©8ø:­FUdoɧ?¥Ðt[ì¬IÍJ·ãáAupñóùÁÙÕöS»Ñ¸tj­á¸Þ¾_Ú½Îíçáx4Ù_ëKôQ?C²èµƒ‹˜e¹†¥ ·lU“r}3kzšipY"á§Êa2Ôl!’Ntž9'BëÌ»¹— ¿Í(Ñrïo.[8Ÿd Óýxh®**¹Ê&r=Z²a»›Â‹m*6Ô._ Ìe¡lS²‹ÉÛˆz)áÛ²™æ%»dKøMlñÆwòÿ†Ö"5Ãàúƒà$ä–h@Z1ãlµ<¦Æ´¢…©v¹ŒC® C?ïÆ͈÷Â]L¶U‰«Z°E/²Ü“?y{pÎ}ÿéÔ e££Þ!Ñî¸F?¾ˆÐf–_? Õ,¿"~@»Y~Eü7ÅñcÜWð>ôïXÑ,¯/;½íú#«Au'†ÃS~RÙ‚y°Ÿý!ŸKé“~ˆk÷VB¿Î{'“Öd*0Ù;8¢û·¶ˆ!øºµ-EÞÊÿž ? ž5¡;ô–Ke„ -ûô+ˆDvÒàpDØ»£éß”þ½)náÄ:q»;ç¡×˜×ïú£“ýýÎNÔÛµj·ç¦ÙMÎí…7¾_v7炘 ²Û‰%‚f£¬…gù]è„Òµœ¶ÞhU ݪ{]Ý·›®mÔ;ì¯4«+Ígª×±âiâUxŽ‰)SƱCeæY¼0l¡t¬±Ô0!9ûï¨${ò¥¶3~샓oÕÚQ÷ñò¾:6÷ýñø- «—wº·í{ -v—»øÔ‹"-l쎲e楙pÀ {a(„ºO¼F4WˆbgÖÜãYÕMØÕ b"é’Ÿ7˜¹ÊÙ*ÐCîA¼LCF2EC é¾#¾"Ž¤¬ö™ü° Ä+íj¬Xí@q` «=ÒY±Üåâqqpøò,¯QB¢ºMñUùãN)Ï‹*æTÑ#ü ʆhŠšœxßTpŠˆª,XË„“•Ž+%$È…:rfJ ÓÄC_‹Ü)U1>ψ$K'\ (¬xˆ!Z\%%®”­¯Á5¡åuÉ&t·L/¢ Ȳ'ÅÁs´§Œ“çû_žø¨Ä,ÑDâãe<óƒ´ày(žÉƒÅÁ6†ˆ¬Êì ÝŠûÑNþº©Ö¡9ájǘ!†ˆæÄ ø´BÌæâs&FÕæ” ¸j¥N6˜µRGà ïÃÆÎÀæžðœÉ -‚ylD-¡:aý ™*-#eľk „¸¸rÏ@%ÔxÆSx)UòcùJ3$”|!KÓÎß1s6¢ÜÓØ=Ù2˜Yá ¹ Žîæ'­Vý¤ìß&–½¼ücùTê+†§rxÕ5`§úFBٙů˜jE°!=ô]I[&DuHÜ&•—=ü¯¿ÿƒý_0v¬íK×ÿÉþ!¥¼0PœZ>Hj›@¢ÀFåMÎ^àêM’žK_&êå$¸3êÃÏ®(NnJÖ±«Ùã‘^é8Y„%Ÿ9óÂìlSÙÔxA0X®ËJxã”[J*9Ò«‰R2¹×¾óo+‚Üz¬ËE±-W|‘Dˆ’FDÈ”øÝR}çѪVr3—ÚFM(sô”¹ð¬ÄÄ3¸W«\o«Rk"[ª*@9æ„PïÑñ¦¹°z- -7/ó@”\äÚ&ûòÜñ2KW}WŲ,)ÌnYíƒõ@ö 8/³T3:Oé‘G 6ÊaQ1ÔƈJ -®£²)DµÜm3SšKkrÍ¢ ÿE~@»lNràú !·M…µËDæ¼Â˜—šEm*œ7vQ«ë~ü`bŽ•Š“l4S¹Ÿy¡!™—O”lTú1á¶à2“¯nS,¸D7+ÍkAE$KZ4«¢˜¾bNT-B>ýœµü»ðÛ0õ\ç®dèÈÖy/¯¡PBº)Ù–R1ž|¾”º”5¿`V¸–ÌdŠÌ«K)3¼Ù'†³t“žÉ›Û¢r.Áï¢`§N¾NF£¢Þ&ë¨Y+µnÈ{+¬Mjg'Ŷ%ãF“!"WM5!T,›6DæØÛ-„ÂŽ$îí)0q½?¤âßG*ݲÞ,øÖV› þRÖÀK8‰rk#aã‰Ã³”ÈRŸKlDÄ-”°‘úG±¥ÒaÞþÿïãËáç ÷¯ôèøV­S5º5Ýj4[z£å:z×q:z­æ7Ú×°ëÕ÷‡¥-7ó“ ãܼ?Ä73I/£àf¼QØÁ–¿8¶ìãÛpÎôæþN?ØM³Võ¶zèß.G¦ShíǾþ<Åñ«…-zHå6MÚ+dyèž¾D.†}OxM2G7]Ós®óÜÄ_tá¨Åó…‡}¯SyßË|8K-ÛÃòK®˜7ûyÖõá|“££z !ãÝ~Žð/}„é9ÕJÿÒ>šßÏGÓ|ƒæ0”y Üÿúû?´#åšâˆ`OB„#wEüáïyÞßó’¡AU^ -¼Gàæcì %†k<žçv¡0Ç*Z”òúÏ‹(ìH ±h™– 䀭âO…øà ´¸‘ŠŒòp¡¬OÙ•ïÊŠϪnÀ>ÍU’î(êPÎsö<¾¿!0* nÔ•B$œ7µ–ÌÙLŠ1yØ)6²‰’d+Rrùÿ¹STñ–Y*.˜ßršEz(Ÿjõwè÷ £Jè51œÞ¼M°Và#Ší­h‰+nƒz;§9*[ReF/ÉŒªIEâ7ò~äbûÛdÓ -¨-ûÎ(Q¨VHM£%¼ƒxÉäMsmú5£ã-CôĺeÇSÝ*OŠñC|®2”çd-ÐR²³gn¬`a¦Sö_áÖý?öÞ|ÉqãÚžˆùož‚Ó1¾v-$v´âÞ¸­ÖbÙRËV·d_' QE5‹,qéEþê‰æ ¾ùï>ٜ܀ÌDY ‹Õ‚Ã’ŠØr;ù˳þÅYŽ7Äœ)ºëùÍìÝ5SìµêèbCPºÁU²¿F{Þ8""vÔ—ó÷úµÍ®l\Û‚„K¶ú,^¶V‰›¦‚ªó‘K6’yƒg´†;5ªˆ,óÛÍ|£h†n@¸Ð&™¹.Ë‹3cUô›Æb0Ã/LÙ­`R륅iT¹Ü[Ê4®ß’™L_×:á‘ÒLCw5w®ÈU¶å×·ÇpRßcDÛx95h|¢ùÄjQkÔ(%o¿[Ó,+k³ ª’01[ñ”ATò2}†T+Tëÿµi¦5fgâFM ²~%ëUu5Ïò-W½!ë7°kŽ¿8u»²Žptu¹“.Et᧯i(9Ѭf\‘¨éa9ìØ›¡Ë©Þ7úù-Õ­Zm -²Øâ:ýVí±J/ë<9×,Óë< “bô‹ä^¦«m0j2«×<~ÌßÐü'‰‘¯ñí\]T)hšÖ—ò3Lf -®›JÜþu¦y¸Ø8Ý—J>ÃáâÊÃEáHÇSe†\vúó‡ïfI_eóãÙ3ž=ãÙó8Ξ{`ž4:Ò¸ëÍV„2Ç‘/Ý-™GEíâ²PâõV.7ÎŒ§êMOÛøUlT©MëߦªÍ t‡†¶VsÔi±¥Ön:Meïy¸ÿïµFGxDàÇ„À¡–nÍ­/07<Õâê=ÍÊd¹PTìF|Á£P±NõÂw -Ï+ì®´eõÞíˆ F%2Àm‰ ˆùÐ`Špܦé¿wÈ€ÞfÓi^™î£üC¢šrx¼ÌÆžMÓŒ¤O„Á=EÔ6ͨ¢§ÖU£MP¸|ÕhŸ¨£*Rà 4h‹Šù˜lhÐPÍJcVm=>#ÚTW0Ì ¸WÚ3~»ÚA•¯ãOÒ#wx\,u\Ìøß—륮Å6ëc:F©î«šÌÖòîé$7û£bìê Yέh'à|Å|xâ5Ë–LK—-WºSm]ÓôéÄÊ ".ÑU»cUI ´^0GË«Y5ù5ßÓoê„îýü¾É«–µÇ—l»½{áö -ôæöO¯Ýw׉f†.-²F˜™!{ÄxŸ©ñ¾88šñ„HQuoÉÞxãÂLú£ù=2ë)š?›éS8õv9M¨÷)#þoG¡@*Ü“å®òM5½²3IÇ}·ýðcó²–C*è•'q®SðYRÜÆa©ÇzÊ{Íj§‹Š¥¿:&êEfRÑò½ã^2DHŒHáAP:—ÇŽ£Ôq1JK7Î\/Ë÷âËÕbD!|ð«€™›Ìûìžñ/ü⻟ÿüúó¿‘Ýßn~ŠæÑOoüö¦¼ž¿úùå¯ßü]¿X}¿Þýã ÷K#þ%¬ú%'´Á£3Ï{zGIb{Xð %ã‡&*Kª~öÉU–4‘.Á€‘.¡%M±çb:¡Ê%2bZÌÇ1--q$æ{uÉþ`ŠÍê†4Gé–ðjŸó~Ê•»Œ‰i6&]‡ñßWý`÷W}ŠØ”Α¢ ¦5Ô\@q¶&>Pe+¾¹ê¼ª•p7_.æK¢nQêA|TÿÕâð×ô=™È}lê‹[YBIFK‘ü%¢­*´-kŸ›×4.·Z ý€-ð9aÇ5`U†ÚM»1S6—eâúuËpfPÞßÃÛäyÙnCÆbç*¹ÀF3Ýg—g¦“£˜éÄðG3Ýf:A÷Q˜é _eyíª5½Žwþê”ýݾFˆûCÜè‰0Bœ qª¸ã+.\3|%­ÊM7.xWÕ›é¹zþi`ÞâÅäšú&Kè ÅÕ'}õIÑN#Ù)U ؽ ¸æÎû&ž íi"Dd-ó¤=—ewɽ™(¥×›iÈv—WÙŒk ™´ÙWs]«ÎŸçú݇žãNîí˜é“C³eß·¨FU;-ê´Óê³ÿ¸ì´ûŒžº–ê˜^®ªiR ³âè4ͼûMµƒšÿüÓ˜U†O4¹?a䱩(L4‰ªÏ›Ú~û®@µÑÕJØß WßÎ7@ÿò¥ëß‹^áÅBÉŠ`O?Ãã€?jÊdvHŠ¸4ð]?#§(RâE‚Ä-Ç+R7JP™+èå$)âÃؽÕ?~ñ2õ~ù.Ê_÷—Íßý¯ÓŸ®7?~½z~ø‘D³×Ÿÿ1Ë—ÿøã‡U£hOKF8¸ó¢¾sHÑžÀ’Žé¬e{6…µ˜¦LÂF;½ÒÌ„f6âùÏl¢"ÕYDWz!ëYrÉÔ:Q®³r·X4ç¨Ã<N2 ÷±‰ËC´ÞÈ[ÿù&_ÉŸÔœ+“Þ·ðçä?ÿïcJæ%Yªa“y O6\@ˆ‹7b#´]Uù_õoTÁP8¼(j®ö£+WÝl3E¼Õ~‹àj²%—`Šõê¶Þ¬Í+f€^=N=YûìÕɸO–«îÔåæS\å/¸‹œ,//±}òv=_Q-Ÿ³ÅØ5mÜ¥Nê…ç–³N¬'—G rn˜vÁ]5õr{ª#þ¥öó¬9ãö³ aá­Œ‚äœt×›ZiÕöâa†RÔf'½ë¶{=¬9©¡à²3a]%t&éyºLFí„ñª*—¼–×?Æ%9ܲÑŸƽ꘴l=Vûô!‡š;±WéOÆ|l£„ôÇïññddó±]j>¶=§•îçÞyÊH™5N%€©>e„cÓ}ÌÈWmÇ @ªº¢æݾÛ^W¡ÝËÑe«Ö—‹Îo=f_{n'i]{þ²©C0VXSÇÝÇqÅXÆWªŽï£[Fe©t/›S˜V¸-’‰¼ä Äo 3÷l»ÞIøË.[Ì7×BÖKÍ'K¼ØT´ñãò¶~zŸÏþ= ñêʃœ:Üv÷ÓSãå£r*>zŠºÈ|qÇÐ -dÉ7gˆt»ò͵)/YæF™f”iF™æð,sGgã%ܼÊ%(gÍàO|FÚ>a8òÂØþU¼&\“Û]ìXk×Û÷·ÁX6Ê™ÃXž'/VsÒ6ª?÷ iò,‰Æ)ß;VZÑF[:,mfNˆ…IˆeOq‡´mOeE÷vÅO6}fpïT<Ž WÌm}V—í­ôѦÈЛÀï¨ã¢åƒ Á¢ï7]áhÓp_9DÑ÷ËËwºñ‹JÇgÑÍ ùÆ„|Ã'äëȤw/ŦiNaýزõ&blDP-¾÷F£&1«“üø°`ÜúÇnýÚV~ ü’ÐØþFÀÂ`¼ýÑ°ô’˜ê-Íc[KsMÒ6æúñaÁÈ JŒÕqð QÒþ$½zpO­pÚÈ©ãÌ)â8ë®X£+‘ˆ®ä¼»\Ù+’²%½jkò-i®5Ç®™q×úE 8F|[VlÄÁi¹è´n®WïfâÃóå›JÐ\uÇ ¶Ž[1 ‹ùË/DêG—Àëû}#S÷åÜŸH°%¡-¿`ï0ÈøaŒVfìù³PP6‹ždäCÓ^l7Ïx\ØüY$6Ì ‰sÃöWÅæBõê<_­˜O% -uzÚÈ‚&–ibÉS«ƒO;Ú·§’5²Ñ:,¢žVZö -àLcØt^R;áâàŽRe~K¨ãÁ8z3u²ã}iíÉmÑã6:qòai}ËAÅNš‡¡Dnæಷ,ü4Î=/õ%yñ±ÊÛ/ò›_¿._]éþýOYùîO¿~x-þôúÇÿxý=˜ÿ´K’¸¸Z}U~qe$ñ *f -‡o „们Åô?‚å§ë²÷z2ÒÙ{3Dºm~\[åÛ6C%ZÚ|µ-m~#¬(z¾¡‹<Ûü²ê{·žkî+WÎ 1÷>éJe¿8~)YX¹†ß3îSEnÃ;Ïoo¤ úב߼‘a»Ípq`¹äî4Ü¿rÉ÷wéãbLè>!Ïß>‡’à ¼îë^g”#J³¯Ðãð†YIJÊê$¯ÈùÐ|Zª[R«#øNÔ¡0a¶díÌe—•ò¶•CÛƒ—¨ULÚþg{LÚ”ª}d¹×‘̽~Ñe¯ÏºVÃø€\O6=ÝÂÄC!vc'‰|äe;8wC'/C„<7õƒ\zœÊí€vw·ƒõ{ÿüïÎ7}ó§ðíüù‹¿þ°zûÛq|ùáÅ" Rÿëg_{þÒû«îvòN4’}„,ù5¿nºð^[™XÊ2š>Cìû‡zx¼™ÿF¡=¥ÂuÙÛÍÀ¿l7”˜‰Unlò;ò°Þ÷ö6Ø›'þ#t7 óÍ9ªöSKžxÃÝ ÚWóJé»]mñ‚½´±xªIÞc“ËߢSÜÖßÚd¡ß™iÎXßÐ{¸7‘.ŠþŒ7ªéáÔ~2Aî'þ²zdÛ_n°2Çù­¦OiTâL@|Ÿ8Oôù®åüŠÆE/z<‰ô¥P4l"ýDH@åÜ8^~IWWûÏ›y×Ï ç?»³è×%Ïš¿Ú2ìSt_í*÷Añ·žó^è¥&J6æùr¥k ~yݤp_%J¿!Å|w£v›Sâvû¨ÄùI¶Ö«÷³èK¾ðdÿ²›5 ]àò[÷ÙYÓ½¸îé)ÞëóLSáYD-CW¿5zíðÅ¢iäy­ø|IÍÁÅyí<|^°#S®Úõ¾•Ö®÷e4Þä9ü†¡YåüÙGÆ«g 8øÜK\¹…n†éfØq£›ác¬r3Lòpbٌ΄š3á°G…ãMáÏ mç…Ôq^ÈWÏp^ÀD}÷Íw_Ž=.þÐ}ÓÇC£#þF$à–²@NƒüãMe’¥Ò󔯞‡m~%ZpDÀ!JŽXÂÆIÀÜÔJ{}3fï¾s¤ËVaï€ò.#ðÀ7ßEß½ -µ—#‚;¯¡ÉÕZÖ»k¸±$Âì<,ô6«ÕÆ5yu“ù!Ы¿yŽÊ34)ûíb…‹ w¡xDà%Yè‹:Ù -›ñ挕¾º°V…Á†‹€l[¢«z€íY3o° ¼ÅmG´ÑvDÛKA[¥®¢êéäë¡x†‡g´®@ÚÝFø#«=Rßj©Ý[Öuenï7ý!–VöܼV±'W¤ƒ«š}™¢æS6#ŸþóŸâäînà€G¾‡ƒ‚Ï`v«‘Ï7ó:Ì%e+$¯qªbîù\¤ †±É8eÍ–×?‘«#4 ®ë:Ù8íƬÎ1Gg MØ.ý¯ÿÎPŽÿزo,…Í–»²žç¶´A2Sukf%¹lg1# GÀw¿xÿT…Šè%i:´—*ùJù¥JäTv•*1:Y©’1' 铓䈲E÷ð²ÃÁåú]"˜>IƒáÒ^+(!\#Œxp°SŒfî]IùìÂI\eÃ03‹·Z¦y9å±lÙ£yRÌôJÔÇÛ+÷.3’n ™ë¡‹›Q©øåJ¤£:c•wÓÓß7Úmhh¥/ÐÕTÚ¹Fʪö¼R2°~–Õ2xd¯†&.:µß³Òà…Á¬É^‚ºÈ”z>×E¤¬‰^è·¾2Ò«’J«ª‘¥VÝ¥è`[92–°%“dnC’j¹Ê~6*¥õØìÔѸu:»H­O2v·<¸>þ}ïö®5øÚ²Þ=¶¬×¾emk¡nW¯}»"5}Q½+;Ú‹»¬ÿS?5¨W÷ ’ù=5•­ºÄæ¬t“5«dÄä7”€ñŠÏRÏWƒ’J­«JÕ3"OLeÙ`ëuóö]w}˜ÌB¶BFcf¡Ï.0³®@¯‹ÓÞ§n«@G- B 3ú f\tS£‰zR49Äžj{û}ó2qÜÙŸ¯þê¼/ýòçâï/^üúwñMòÚýæ/_ý-yõ ‰¯ôªw4Ñ‘\!±3TíÊWê=íì¬zo=Ëý”qâUeÖÛõêfµ%Åd»šl¯É„µÉ\:-‡ZˬVªè°¼E¼¨x¸ -utïŠ -u•;ÚýKÓUžT~g¥à*Á.ÃéŽË”ΨãrµtÕê%N2B–‘$eòlŸ -jÒ$þ>ÞÓÝhÝÇq»!Švm®ÞI³úð~m~ì3 -]°ê}W³Ú-ÝížîÎÙjùjÿùjýÀýfLÁÆì´÷¹£± Ð(¾l¸öîõÑ×4-§WH·¯dÕ ê¿ö7²ÈW7„¢áÿÚ€øýŒÿÛ6‡õ›§,Üï<¿½]|¨géñ×m´©Ç”“gQ†Ö¾®-Q›ÆþX¨Ã᣺ø)B²V¢d²B‡DYÝYƒ¼ìÑdwf„›kìÜ|è9>5‘ÇT¯ -DýF ìªo?`4-×À'þð‡?|ûüå×?>ÿúË™²÷0ôylol®Ûû¶ØÜvT¸w0î¾sdàèÛCÏ…1vˆ@ZE»s hÛ´Guêr·¼Wƒ8†dŒúèŠúÐôkÁ=clt¯7òÖþŸÉWò'u­Æéó-ü9ùÏÿ+Ï_vX¸[ÏŸ¥’€mûv-u½³žÉídQä|xLi'¬ÒÚ!êRc(í]Ò¼ÖW|°bà^Zi°7“¨½O¨…i¿øòÕ‹a¸Á“p:¼×læHz´¤%oÏsnûƒ xÖÌ2Fû’6òáG^îx-"¡ØüO‡Ýy ^§:Þc{n”ó53>Óqµ™©›wFÒˆzãõÈaµRÕOW!tUŸ-¹ú€š»†ŠÛ =øo¶dm’·ò¢¯+Y½œì&&j|ò01±D‰q»yÆsdƒrd>ÛftIHÑ'u}ÎÄBùnËLÓÌâ­þÐwCuw,^#lda¥'ÝfóôýÌè'¾¦)uv퇾܊`ÛÅðmV7–ÓÎ;ŒáÛ·ï}6ªf3~·ŽÌŠ­;»ýp—jek<é¯ÑÒæ¹/Ç3¬Q×?tuî$od&±Ó·œpIÅê‘qäuŽ‚¶]ø—δ#¶\"Ø cq¿Z¬6¼þÐÓàžc\HFNîe±”né¤×Ga™{$I|Ü=Û îRÚopGrQXöžpØÝ<¥)XžÞ`J3g±š;·/¾úþ§2ÛÎf?ãÕõWeùúÛåOøíuðýç/¢?ÿðåóe~=ÿauóWÝjN‘L̲àñÔ¬­_+·°™{¾f3ÿd’}˜,Èhó¬6rèX"[Ùo!oaNös5}x#‹Óe‘@–í’C‡s[eÙ„k ñÏø½¢ÚºLƒÑ Ùß ¹‡_;8É‹5ùµQA÷Ù° -:[œˆéçàÿÉ…fŽ]ÿÿyî›F©¹¨Ü¼ —;C‹újgýÓ{=À߯eWƼ1o Á{4!xë‡$þ¬¨ø`Ô9¯î¸&Ä£M°é¯ª`ý|·½n ö²=»Ê©µ•ã7å}©’>ÞKy;BÞy#ä=ZÈãJ;äU€tw|éÇýü\ãe-J‡Ùqw·Ò ¥£Ø1uߨ™x%Òû''¨úvB;Ùµ#ÔŽPûh¡vŸõ¹*ýh±»¢†<ŸBž¶'/Е“fê$ Oͬw'N@áRžNJx>J÷ûDÙ‹m]k»+¢YÌoæ[E /ní(-JF\?úÚê]­Þ®ñrC»+BÕòö(›H«Es¢t=²KÈ=ZV¨gj†*±õƒ¥-¸—Ä·/ºwÇ£{3ºwg‰îÝ¿#Û:-Õð4qØ•¬€ÕÌQßeWGiËÈ '804„úߊ(¬ü©sŠFµ\¤ŒIŸÜ¦Z²%S€5Ýü|Õà zû®_ŠÓºéžeu,kž #Â~Ÿ{CG„} }¾îˆhc³æ °žãªK3ß|‚CØÔ¡íý|¨jÖA¹bTõÑðäé5Æ1Œq cÃÇPÅ1 çv=lÑ—N!šVë~Uaèdâíf‚±µ+—VËAbÓ^æyõ`%ö4|2˜>E{î@OÉ{¹eÔ9 ºÌèÐ-¾€ [¹Ý®îJîB+9#¢Œ’/(˜*œÇ£L©-F¤ßÛRŸ U8µ‹R~»K_§°Iv–öÄäÿ›ŒòïIäßÇ,âÚÜ´¡ʯ6nq¬Í—×d=¯çªv”ϼ#‹Ú„÷¹ïõM¶yÛϵ`¨sM18N¥A]é0lJˆK -• vmΧzåB³Ì!mWU,¤#…ž/QÚ¿_-W7@ºÐƒž¾ÛY’Y$NNÒÜ J’8i„‡øA/S7³HÅ÷M–Vùn™Íoqæ¦vF1 rïåßýõ‡ð/øÛ¢üêzûÕ«~ùÓûŸœ/>ýUø|•ÿùêåsïÅæÅË—_foß¹îßüº'l=Li™>ðZ<0‘h¾ÞÚX¬Bb|!2hÁgWË+Zjc»šàINÖ[Ø—“­ÚÄè¾× ¿ì@9tæp¿75}BûÏl*SýrŽ_oFú£†?•ÏÀ\õÊð±ú·ºJPTo«±µe÷NkýÞe×8@­q`ÑzÎh•!¶ceˆ††ïA+CQ¢KÿÄÜ«x~˜ŸŒBJf%óVi¹iLrüœù°\`ª -7´# [ -ßeÓqÑÝ^3=á¼_ÙÖfb#ÔŠ&nõš;ƉnuE3k«Ž³­,D¡så‘9sGcîh̹2}³–¶Mîךe³÷+_=Èì©¡%×ç¡Û×·¯¶}ÇÝzÔnU­=‚ü\'Nѧù©qáÑ­áKçì¤ÿe…Eíêжä–ïzÿtQך‡=åÕ”‚šë¸êÿÂÊ¿›Ùsvƒ:c(%êìÃ-¬ñ¬fj[¬ÓDä””áï{ÝK¾Öi…âÇaâ‘ìr¥¾nØf{¯ÂS•çé4KQ»Õà¹ÓŽK¶7ãÚåy –M±ÐÒ /wú§t§ú??UfàèÜn0bWŠ¿™¤kê\T5­3$4¼4w¨M©lݨo–Šd™)*ã-Àpá–¬€—ìé1yeD -”;iQDN€pà¤I8^Fâ¸ôp‘ÅAC¦;Ôc@ú÷Õ¤Xü·çÇo^|þá›o¯¿üê—Ïÿœ’¯nÞÿñåOÙ—¿x¿úÎíÂÉßýíç/–¿~»Œâo {~,R=¨3fJ]Ðá¿T7̼mU|xhC—V \ ÿðZ…Þ„‘ Õb/¯&ïæÛëɇÕn=¡YC5æ·äÍ°Zów½ëž5\Û:3¬ê<ÚæßßžÏsŠ dO=§ý˜°ÉlZÅQóÐe+t7ˆ[Áƒ%J?•õ>bu2¥/‡Å|/«Í~DæûƒK*„G›ï•³ãJŒÝIKI…c‚CÝA52}â$­‹zxj"לŸÙnñFHÛÕÀ²ªénµTâ¨LÒk›Ý_ÿ¥œÆ - À“RŽPûMá±X¯nkø2¯ÜiA²­C¯ÝOYÄ[Æ×^ZoÙEMËi´í–vy%»­ÝÕ]cŸá€sªgí³Æ«=Ž.ë0q½mmÝ„ Ë£MÕUK·&(¨Ü£¼ÉZ+Š^SíÛ¼†“ý 2”÷‚×7TÙÏ´Ó'K¥O}m*ټƬVª3fµ³Z]rV«†Ã”I:Ò ž!sê€ ¨åÇ Å‹›ÄFAìQƒ˜#­)’ï•2à‹µz¦‰%§²¤É Êr%ø­™H«¼]ï¤Ìû<ßJ}@j>VâÅF¶þùb•¿~·£®ˆ"ƒ -óÒœñÝ5!Aºk®õ)‹…e|&> ™Úþ…óT ùAöhÄãG<~,x¬e¸È°+Mg 7>™<±€7mŽá‘€£†ÖÜ’ ¿% ´—i¨<Ï *„kß1WóIÉgbĶÛFl{„ØÆ2ÊÈ23|µjc+éƒån»[«u8`®þù’½Å• áo¶{ÑƩף%žDãßæ3UHl¤/iøµ­þ¿~ùLFæS·:Bï½#ôþæ —î” -X'×d™W’°ÀôõúIÑÎy`XGáSPåØØ$}ãžóÆ[gb¿×qxÄᇠ‹x Z-=K7Ä5Äü¸zZ nF¿a¹ZÂcÓŒ~#²¸aF—¯žáÄ%ÖÐk#¬}|°&Ã?¬QÁw1ÏßpWLéC©g -QyPOD×ÌêLî Zç4çˆbÿ&];õ¾újFëÕ»À‹-žU ëeh¿Ü,ŽÀ¯¯É[€I%-G$ï°0’QvMjQ­¤©ÂmUé¢X ï ßÎÕ”3—\áz3•U$áòÕM&*+¡°¡:–7û¥‡Ðß8OÂ"‹ç[ofÄëN[#ÂDz¤­¡ÃCÙ<ÔhdÏK|C&«õ„ÐIŸ¨Ýºwb›fãÍ|/ -1 œç¦ûä¹á©Ú`™?ÜÈ°-í/‰jÆ!wLŽÓ79Žæ5.C­,áG -GWƒ€5·NµcÛÍæ0<6³y3Ýÿ#TÒÝUy[‚Š¶u,TŸ2nÂZ[´âÄzUåld81æÀ;8ˈé6¬ÌôRüÁ† -ƇBãå |uh Cù‹>ö{£­Í&)7g}ălx tH33ý‹žøò‘ù7–ú²¿ Ñ® »÷žO匵nwmNßN·nlÔsckþë‡losÒÇ&÷hö!ô™¥Ø¶æÛ{ÜQ#žåkªÛnßϹ¢†DWžÏc”†pTO\Gºnûc‡ãUÛw.ºÜK€®g똵÷R¡Fòï׶-Ó™ÿ—ýÜp»Æïì:ËêæQî®ÊÛg“@þ»±wÎú¬p’ò¦Ï 8ú^4u¸ý.äqþgšîåy>µÎ`p£€’¦¥,’ß0E\¾»­ÞÒiªu×qºŸOë]ƒ_ü‹š<²ÊkÍ7õÂW™åw&ÂÀìõ3*µ½û0ùÆ]1]²È ·î¾\Éü—ø-ž/èžÚV‰e½S‡!Š/Sȼa™+ÅÆ ëk3¼xÇR,×{ºº%ííÂÎþD¼*K6&Š¶ðÏôÖi_}«Š÷uÕ¡Úº¹^½ÉD©5£ÌŸæ샂D‡§'g“•o6Mãº/í–¤jˇq¨P`{ù…ølý(â¢P}ØÔËáÖùºÎôÞËÇen9’YLeRåXìÔOùût1çyÛˆR UV’–ßS—ŠCoØ#QHéó·²!ßšu¨C1*1“uÑj©£¸ÓˆCú<3Ó¬*Ã‹Ú -ek8ÞR›÷;>"JO4 €ÖFÛ|2alÔ'lÈ -‘6*W¤Ž3¿Ñû*Ž»tÈìÙï®W³ÍlIÞY³ŸÔY³§,mö”Ai¿‚ ŒK„\'Å~îA9IJøY–EbœÄhÊ7÷´J=å1cÊ©`*´2ÓJ]Go« ´§Jí©HB=­ ›OÊ”ÍßTò'SžF»~¥ì£DÚ¬7W³¤|õ·?þãûŸ¾É>ÿxþâëÍ«¿»éÛÝŸ®yóÃÍËïÍúÙ ²¿~3¹´§OÄ|ÐW38å”>åL[uÿo׫ßm&ò¾6ml÷MÕíÇ?Hûø -vÂf‚'ã&«r‚ ý"_Ú¦œ¬–샾bð6ÐÍ”³sÕTL+4U²kOzNŒ³ñ4»Q}]ÒŠ˜{~#yú¾n–ïÖ©’j[íK}ÈLSÆÚqecò•O0«¦çÝ®(Sž;S%õöԬ䴬±‘ŽROç]‘Âó -£_#¥wE˜4©·B^,­wÓš1Ö)ôª}ªg•f»(;;RNëÊ1¬g4´¾ª&éLQŸÝ¸©HQ;¥ù2[^ ­p§©°7*¿•è™7USËUÀ¡Üåý냡lÆþ‰zÊ+¢¦#«D½–ohÓP%™ªfN·Ó:¨+¯11¯"Lúråë®íNéÛ>­Ùà)ó¦Ö·¦æî­}@:|O×TqÒÖ>L×qªšÜ§ŠŸ±þ…ÚÓ¸¾Î7^-¾×3 |µ_Í»T£›"ÆëKÂw 0ЛUÄ hò•ÛL5î'ÊýÚYÜx(mÁ.â÷úEƒ¢èu”Æ®ã"ø¾÷ŠÎZ×¹>â‹i­õÕ©GZ]¦ªÙE#¡Ö£Æ*>Ôw=¾z3e¢j„×fOçÈj£DsÒ¥1Fû–´6h¥¡FÜ@y”›dêýÃðV³¿Ô0l^¾“§Lm˜ÑO™Ú4£Lñqs¸o>¤¡¦Â@º¼ÜTSïGf¬©^iLŒu -¹X£Úd*ª}¾àcð<ó‘™òmÅn3U 7SEhhâBÑ÷¡ -*nòÃõ‚Ó­!L SÕΣÉyõÇB“ù•3`}Vòò‚ÿòÕ …éƃVZ­×²2)$FÍAS;ÿ9Èšê)µ–·íŠ^ V¡Fƶ³©ÊE•ÙPÊ¤ê µQnÒƪš®êKŠæ¡ÖªÏ@H×NUá´ÒÊ«•²pÚ¡-œ*êBës•¾pZ•à“¬j§B8•ºÀ©RK©t!™q Ôëj†¦{u*¡|Ødoô¯´jTš+ÜPªm¾]©¨Êvׄ]vóy¥ó‚fx­2~³î¦ù^³gløÃôÔ¸Z …½ücEè¿)j¹»{2˜öxµ‘Ó,»Ø¡@öP’¡‡N–D®d~à$n€œ(KS\ÄI’¥qEQ—¯@¾qßÞüÇÍõú×ï~ˆ^;yáþ¸ø³ûbáü.¾|ûmâ|™½Ï²ü‹í?˜š -dÖeu- .9Aóg&õ¾=XœÖêdª(fÚcº´©V¾YÁv[“(sña‚™K(ßwÜÔCŸaÚ&ËËÇï©OjçËV;3õP;³Õ¿]¯@¼&*s6*ŸµsuT>?{Êg$Ùç=Úçf›¦ö¹Ùp$OxY‘Ðà>«šƒQ)01SŸ‘™¹”N0ñ|QƒISe—Šq;U7Ù^5›½•ç£ò|TžÊóQy>*Ï{ìèÆtÓ&ÿí_«ï ¥=§pP8—N7M×Îî(ÐÓjjͶ;ì%%Õm}Ñ¢bÚ‘çœ}ž3ï ìã5)¤€L"Jp °çj‚KZg§“k rÍ4¡ü/¼€Y è§õb÷SÑ7ÇbÓMÄt"½_1¶=5ö¢û2ÎSÛãò5ÖSQÝÏwécV÷›PjjûO¥Šø³ñMR×o]ÐZÇÁ^RÕSÕKŠº¿Zu^¥î%µ,zuÛ\tv˜P•AËB+/žÉ¨£³äÌ R)t¡9úìëk8&þÉwë5רý;Wž1úö´eõ´qÝõ3—Hçéi#6FACUÙòè!óßþ³/ˆ*CsZ×Ç[ÖÇíµ4¬OúhïF3U?3“÷T÷Lê³5Yµ±U3kG­ÃLXœñi7DÙÛè´yLXÙ¼8)n¯ñÖ ÒÅêê -¸ÇùRpŽ¿)ªmWä=ÉA˜ø—ßößþÛÿ€>-¹ÝÊù· ôÿËïãVê×Èþåwòô#›-å–hfO˜Éß}2©­_\ÆLXÕE¸?´=ä%F{ÒÖxÊ6Õ&Ù¿~w»žÓ ÊÉòÁFvõƒ»åü—¡Ï5éÓNÙ‚AžÑ‰œÍ˜0n›f}&Z>7ë&Bõnc˜7¨‡NΩ¾ ä|>'»m™Üd‹fº×>VĶtû>º”ý'Ò -¨@Øóe39Êò(ˆ‹<¹æddLc2æo0ç;à9/½hÏŒç&,úÀUùð8ñ`äöðäÈ@ÉâdûÔ›¯ççè¸næýÆÕ¹–‡ŒŽÒÉ•nIkdÝ¿žÜc}XNÃÔ•ÁÍ3£°BË«£›êƒD=O‘²7ßÍ°ö(N»ûdÒ¾K?[õ³}ºq r<ÿwz©´i}?´mqƒÃâæö¡æfÿŽ©OW6‹û7†}®—¶ãHZ„¾ æ£5©_N,víAô¾Rɉ»ÑƹÕýÈ«ì0B4T%û©MYuvîI2ó%ñ[•F¨S5§ {B ÖVÕ´˜›¾‰„xöœ§\Iò”6Ja’<Åæ·yÇa‡=C.J7I¡È ü,r2œÅNà¥Q\¢Äó Wí -{SÉïã»Ïžl>l¶äF´òtIíëü–Ìø…'ŸõÏ£Ì2œ–.&NŽ q‚,Nœ4IKá’Q\`ì¢ÎÄæXŽƒ/s²`Z£óŒÃ÷}Ø1iä`?ÆN€âÜIý,sÊ4Èý,ö3·,ºÆ$Öqà¢`‘¤bOŸ'R@Œ=9ÈM)E…±“z¸t"’æQž¥‰ÅKY‡ÄcAη2!R¹“åAêq™:IT`'òPœ–A–£ ìFhÝ"»åízu³ÚžiŸD>Lxî%N˜G@_qLœVÁ)’$N‚(ˆsÿÀÅi~f·»l1ß\Ÿg)É’2óa_ä(¼*“aêdnG$.ŒºñÊ·.ÆY—‡ÁÞÈß+`_ Xì—±“Ï Ó4 Ý2:l r)λ8áÀ€Ù/à¤pLB»1ràØ( ©œdy×BdÝÛkr³‚!<beE^yî;AX0ª$MyNà0‹’‡y÷&i¡®sî<€íSØèiQBÏIædY;1*‹Îö"BÝbjKÞRÅvž¿ùp¦‘ÄYâ»iḸ t$ôhϧŒ£( "„;Úë‘œu© -{ŽçÑtŒØMg¥“¦(wóÜ ó¢›ª<ë8 -² 炬<ƒÍNÂÒÉST8)]€,7ub$HË,ÆÝÕzžsk®ë"ßÅÁ.lo×+œ,"ȉ’(÷\ì–uŽ¢ÁcIà=÷@rŒ³(ƒMxìqäp¶Ç'. Ê´û´3‹»åIx«:¹ä À}½ž ¯YsTe–¥ež¹À/zÀ¢dÀm¥06‡”˜âÔ‹“¬sŸÞ3–©ÒÖ £·§,Œ8ë.s,ÛkrCžex½¿±u7P÷5ûÂSñoöÊ þÆ 1ýÿKå¬Ög·xóf#ã½Ôú$+(ŠÒñªi´þ¤åÁk²¸•åÓ¼ÐúȆPÅ€,HC+»Ù\½#¬ŒðüYDŸŠ­O W Öû¸ýcJ™¸¤}6²5ÁE¾ÞÝdì{i{³Ù/‹ùòªÊkè#ës¢î׌5„gQû¬ðÄì)Gl[ŒçËúslëƒÛÕj±91‘nÈ[²´Ðhª2jßØ 3ž¯?˜ô‡Ä©Û|Eè^¬›X_hЫ¹Dü¹ÆnatëÙ•”m#Zþ„J‘e¥ùS -1Æ– Ç2h1±l89VëóDëÌu$>p~e99.B8.pá$( Ç8ó“’$èÖ®éåTn'$°ŸaD‚˜V"óý(MÂ’2ëùtÊD(vK/ œ"É&pqàà Jœ"Ëq BZšÝ0¿çLvÝTPÂ6õ€Ó÷ ¤62ŽâÌq=XŽ2+P@ºg={"yJyZ×pþæ,½/‚œÄ>L}ú9lãÔÚéÑ+à(‹„=Soöþ–¬74ãù½§‰©Y×ñÖÚy7 ÝØs}À Ìu‚È -Ê2`€ÛO\Ï Jö©s£¡§›ëÕzÊÙ×{ä’Èςĉ½ˆPcrR”`§ Pˆü0 ÃnkŸz£÷´œÀY:xaêc8i#äÃq²-[8È'AŽÃ(w“n~'²tž•Xú,ó9FàÅÀ3”5eÛ‚<Œ@܈„ ‡usü­# Î1!/Ï¼Ø AðØÌa#ê™d”çw‹´èV¶Åm#¸=ˆÔ²opkBÀyF ~‚B¶ñ±¬ùì_02 [§ô2ª‡ŒKºw@¢vA$B °—3Òí·vL—OÙ¦zˆ1ïù˜”NS¦1,©¶Ò/œ¡ (Ò4ÎÃN}SçêÕ^0²dXBHìD)U€Çyîd) Ãv¤_–nÞ¹zA¸odTÁ“/N6¸›U‹Wžë’E®ë€¸RPy%p2D5=))ã8£†ŠNL÷m#£­ñ¶&WóÍ@†uÑ-£Ó¹X'afÀ6Ê6G¥ë$~A¡?-ò0Æ8êö0KmðÔ‹µpyž%æ*¨“kî•öáHʨÈü@2ëÔÌ™{L\pÜâü¬#ó"Ÿ Ú;QÐØØh˜£gAzµ³vŸm¨ï²­7ƒ¨Oû,À¹"R8p\GÔ»šŠ9츰Ä(HIxÝôصd§„Ž# ã(Ì“(qÊ"Á4Œ‚FµÁ_(pÓ(óˆyÝ°˜tŒìôìÈÞñÅ^Xº%‚Í%#`·J8²4„…+2ù‚_ÏÍö##ØO¼9Q–€`žK™ºEáD!†zEd~çÈ‚¾›mKðæ¼ø_äòü0á„ê{²™fNI¢øèÜo&«¥í<¬ÖÞ1‹2öÕ*AzO#ãQ™8aÒŒnàvj·öƒ%ÔÓ,^3R¢ˆøØÁ•W¹†]`’Q™º¾ïÆIÞÁ‘ZFŘ6$îo0cÎ7&RF¡#‡`j„…!:8gnh®›E%°•ÁÞpÀŽ1y…P"¦›&Ž ˜ŒpH¹€]ôKßËb`‡qw` oÚ]<ÛÑ>œ¸‹ )4 q€Ø¥ÆÁ,pröPZÄ4bå¸áÈS‹ª Î6?Â%ˆZ¹Cv{Jhø,0ÂÈÌˈ۩åÜ>û‡×Ô<Û j4OáÔ%Y pžƒ–P÷;—ø.I¸Š;¡Î·A]Mrg] (õËUòc8…‚¢ˆìF4P-É -—eÝѵ­´ÆÖç¼cÉB@57tʈƥ"àó’4N`@iê•9©e7‹Ðº@[ü~µ\ÝÐD­Ô"?РxD¿kKÀã(.¡ÞçÁ ×cNÒ)JÎS·Ì˜:EÁöq3¸ Û‰¤Ýμæ`, 3¿Tn0ôoQu¹mP¾ú~…4™õô0È5iB¢ ŠIÝŒ’ƒúŒ' €v‚r3d‹IêD ö‹Åyœv3Í®9ÎÀ<Ôòd™›‚pL -4—ÃÀ’ŽQ?K1*#ø'ëN`ç´¸ÖgH0ˆ"˜½ £)v -kbšw*J¢ˆ” Ýîy‘u…gz %@9"1 -0¥¾zÈ+à-©¿UyäR%w?fÀBlÂtÑ$8*ãÂRêÁ@b9@b΀Móº·u°ŒæìV¸ØwQ:‰çžIs`—ÃÂwŠ°Ëz@Xeæx~¦i\DyÑ-¿øæ0õAÙ?âÇY˜¡Ü IS Ê)žCˆù8 uÇRæn4ŽŠK9ÏJ\``ó‹£€†”#–•t¸LÝ<Ês¯Ûy¬1‚a=˜ØÉ -X´(“ý4 CèzFphÄÐÿ,ÎS89HQi–YçN@ñ³'¬§¬§ šÿþGyæ(ŸŠí »NÐ)ü°Ò$A…×É4¢Dïøp{ûzŽœfë‘C§ƒÈFK×É“2,¨_Ú“]é=ß^ïn²%žB/4ÑN(Qû$÷¨½’rM!Uµ y‰f®×)Ÿ£:…mãépéZ»Œ<·È"êXˆ"’B*a¤ ‘SwOä§ ãNãŠõ.`×Úã'y@R¥‡i”Wæ9IY¤N‰ÝÀ+°çåÝ,Jõ‹d'ís„]”G¦^§ÍÂà—d…S”iì"@χÌ2ËßxÒCϲ {plš‹Ò£ibü2r’ˆ Ä^€:1Ezièîf)îZ£¶|”ƒhŸÓ1–4Á,°0n–˜™4éÔô!8i¸†lÝ$pu÷ûaä”E,©£JæfYôpœDYB¼ÒíéXí³é‡èöº(g7øöv¾´³ºn£ £É­}ꊀ:R"/@JDA’ý m §¢ S8<Çù`ÿ%¹ã—yè¾ëÒ oŒnZqŠƒÀÝ1ªA×Ñ%DíE^‡ƒÄ„@ès‚$9=ƒc>BØ+üÂO÷ñWê(TÝÐ9ú_ú°ƒ.³A{¥[pâ{1ˆ~®ç(îVk#Kÿ‡Ú¼{;ŸD‰ÂIϱ?‰ ü¬ã&aî†Àrå{2#¯4XCt^ØŽoYq ›e$’ñaª B’5áô/ìè Æ8ÎapÝ)47/kƒ›t˜æm¸ûºOB€G`œ4¶#ȱ“F°‘A6M½8Çtié>O³?\÷iØf¾Û²ºÖC6‹Ü,a4 èô—iá$°“`b0uêÎrÒÝZ(@4“5¨·^eoW9Îv ³´øD…^À±ê$Í𔣅™¹1ŽÂÐíö¢à#ÛzZ·5xnW»FpÊzµÛ’ÍÓ?tÂøîÎèz–¹€‰TÄTŸ—ÄIÝXã,γ=¬¥ÞùÝöšv §Å‡è<%?»4Mp™ÒR/)ÎÊ#×£q ›fa’fžŸÀÿöQ9£m¾™éA4;ÓÚe%Šá Íê°'?œAÌE9Mq'I–îìTºüîz5ÛÌVËÅ|yâ~{Øe)LiJ šfDêœøN¹ µ•v›?\­ßåzµÜÅ3¶v:ÊäP:ÍR[pô¨„ŸeY0’$îæ·\Ëd/É»“v:L<R'Í$òåR(‡ëÓU†d½ÔºÃ°¨*@iZnö¤Ž¼2"Ê”º’\'Aàx‰ãÒà Ýò¾ EÍÀÙ-YÝ#µv>)ÔÏãÈ)Š”P û±¤‰WS7JPÙ^­Òù/µv9C„Ä4Ôº¤º" 8J£´tcáºÝ“½Èè2“ÿ7³5ÉOÞõ$)²0Hœœ¤°!KZƒð‰$ñò0u÷r¯J×5ùÿ¤ÏõJB"'÷he±Ò¥6@q×Ga™{$IºÓ8S¾DéøÕbµÙÛ}Ò>ÃÑX4pšÓœJ û€¤F Œeá§qîy©¿7 -¿IÚç “£Äõ@ªÁAHm¡`K"'BÀ·&…—ù‘‰fÒ=¤ã¢Ç æ7Æò¯>ÍvË¢ªE|ƒoÍþkmÙû¸yF³m1Ã2~æ‰ßT›øD¨©©pön¾½žmv77ŒL6Ïhv@Öö†¾Æ>CS¿ñ ]êßww' €‹¶¡!¯JÄ5kc*†È3Y‡W_ÔZÊÓo¹²¦+ Øؤÿ“tj-v°öaUŠ>ý×Ý>Ìæ§SrØÇ‘tvÎ&ÒƒsA¸A¯IIÖd™7Žû“·|íVL¥ògWÓ'¥ Ê—tQ½îw0iü b´B#y¿Í—›-†§ -s(¢`ŽXìÚT¢ ì{×ùÅzw‹Ó€Öð/ŠâÓ/ÙKâÿñšŽÆ¥ý“ÑùÃá?»Bš¿òÙKºô!»Cë»ÏóYŽók˜Š¬²Á­Åjõfw;ƒBN‹pÛ…ù€cæÃü>yËRµa˜]‰ý0Í…,äM.pF²NGµ¼|ëv±cžyÑ ÄâÐè§w zÏYí ®3†6oÈúŠbàUÃî³ÞUƒƒ=S°Ê›bpHýp‹fÅ£YõÛ|ìb-äØc:—b(Êõxô¿ ]“·ó ëñúôä §2åZBßZ^ås–Ÿtv…RsÖçzµ2ú"ñÉà×áMY†‰#(‹õêí¼àÄ^.Ewèâ.0ñá&+A‚üI}Ïë/rzX­ç°Œxñ‚¿ú²nëÓX×°Â:”ÞMƒ ¹ø>ÿÏsö,øv½Zü‘Gì^á-fûDû>y%_º«¨BÊ9ë›ùF®)¤ˆ¬'UæwΑqRÏ®ÖxI¸ðu9¿Ê®®§t1_¾Ù(äó«”~€eb¥—ŸUÄ.ÐPû›UO½½*µ½-® -²|)6½A«Ymi±iш'¶ §Yš «÷Eÿªûê-þÅƼ[˜Í‹]’z¬O>ûžÅã«ëõj»ž/¯^‹¡µékå#ßá5` %T ØzÎ %…ù˜ðújÇä)e¶]N£·b!ùus6ðQº”Êfƒâ÷©Öx¡Þ ÔEäNíÖscyùd\­W0(;àUfÍN1o´ÕV˜¿šG\r¿:>—|›M(µNÄé4 jã'ûn>cÔÈú‚å™rs´Vñ>@^ø[IFâ+ Ø•Ág¢uµ§‰ùŒd¶4…Ÿñg|gÏèÓy¶QÍï\Ÿ_àEÁwJò–ç*Ó«¬Üiø[qºó1<-}P¶Ì‰¸  Q›QóÖtŽ$³ÑãŠé§2g:T&%ïd“¯ç·|y!/vÆÿ²›‹‚t±Ø2:âñ*]”XäqÍ–¡*%ç7tUä¨OÙn”6Uµ8Ev`y¢ûñD]ôÛäDø½…?2wÕWôsrS} ° ß«Ÿ?˜]2˜k‹¦^ÕoÜ—Ýêâ•^Ž<ÑÅñDt±(=LmO4Ú9¤‘CÚÏ!ñüŒC²€äcd—Xyˆ ׶Tœ ¼È*«Jæ¦_”´i_ª/yü( ©9K#X¡wd~u½•¬G}òqnHÓÑDM%ü EÅl¾` ÿ0üIdçO.˜‘µcZõ¶©™©röHÅtTŸ;„Ñz?1¾Ï>ܦ¡ÀÈ2wd»ùBtžÆÃ5¿ð<õyý}‘AÑÞ¿…§”iˆÔŠÚk.©rä@ØüÄWì6P^÷ž Ô7¥Oñç¿`ñ·îN¯uŠ5­ëÌPJ'OZOø¸RÌM°÷)kôS€ãSÊZþô/¡ÓŸþ“ýºû´ž°”種¾A«õúŸ€‘É‚=6ë>ru#W×Cï×\³‘?R>® - ïæçh‹¤û‚¿¬qrìôká×P½L>Eº• ¥G1ø -× U¦œšgÑ-›•Ö.Ï—åj?;ccOerLµŠoT1kák¬Ï™ªW?—壣óBiæ~'¶(Vìôòê—ýG#›6åJè·tYík erBôxÞûAƒ1²±b½¾crfÒõ’‘†ê©û+›/ä5“Æü7|Êá’iØû-ɯ‰‚¿§ñyAÒòfÍï‰×U¶Ïd,hÿŽSÞVF Ôã -˜öRÖy ÄIšSoþyÎYz( .ïŸÚ@îäG V“rõö:xË=­°Üò8a˵ò¢ìßNíƒv,+ÊÏÚfYH…“èâËÖÀH^ìÌnøÊOŒÄ6ùæÀ>’•æ/ê¨{M6ÛRS(¥$6µ0áè¤L8]uÚ-3.Zq’žš ^5÷ ì7OÝ'˜Ïæn®ãÊžœOoÀËF;Àùr^£sEM”/?»lþ]Ï1¥|Àæäç+<ó÷ê1l³‚}Q}ë Wmñ¦8rÂÜ‘+Îèꄵ¸ÁÕqÇhl±»QÈŽ:csS.æd­0à>û¢8;wËÍüjIW “úÛÍüWÉ..iFŸ…p Eôéù/;2‘²_Ö¼'*éxŒ›"ðmíéz£4_áãžoÉ2%0 -¢Ì‡ -Ê»ñßßÐ×à—:›\‘”ÔûJýîš[Ý~+7,n¨IåÉ ­C8}E›Ëí(y³ØXO -ÑûßðRþž”Û,™ÁY}-™4èÃùê¾!ÐçCȢܴ±{Hôú“ép ³û'ª ÂÒÛÖ ° % . 1ž•žŽ°¸ ‘ag‘m·õ7¸‡EÁ8"B´5hóØÉ>â›nÐw¼cC€mg¶D³-WoµŒ5u^Æ’o€°Š™ÙC -v^V=ÐÐõLÁþ4á! K RªÚ\å*J­Cn¡À2I´êì–|Ô%K~7[ ÒYç²"èCºíÌÓí®LÙ¤ÉZ·ª¶ZÅu©Õ— JÆh¯ºk XYW(Æ~m£\Ž&öáEwQ¨°Ù æ‰C-@:Ôg"X—m¥I¿'ªKÎ9²æä0(¿[iMƒ,…Žl_e|ÐûPÂ9Ö…³¸˜ZB¥×¬6ìIÇ»3Á8’\ЗJ“‹†{Ü–Ô3Z­æYºlKe"°JÒ˜À÷Ùòñ‰ÊBa\^¹¬ÊBÒØkØPS"Ø-Bâ¹»ù¹®¶•µšNÒ,4„?O§µÚu³X¢Q¥%ÚKô ¶‹ôz9Á7Æl;3‚¨| ›*Aã¶BtÙÙ­ZÃ]ë)cu]|›ñbTm¸95§¯0}0Ý¿Âô3…i0°û–¬JØÎœãwNçé}gF04ü2Ò¢ÚGÿˆ=1{t, %â)ßdèÃö©õõÖ L5Èu ?Ëa¯¦r,O 14î s{ö?´øº%Ñ-)—¸qrÊ¿+Br›¯)(\÷9*Z¬&{.„¹Ìïv} Ê[1N7ˆ¡#Ìä(6Š A+‰ -‚Ý\ó'…´m¹">Û[ÅG뮇<µŒpqÂÄ à•Ñ±e‘?^L[^én¿•NìÑ;æìQ&^zp_/ð‚Qì½èÅpiõ8êOÇc4šL¥±”é02Ä?HÃÐ -ÝL†ëtƒfÖs†$À,;í -§¡þÒížFTföÆÛ.ÿ6ü!œ|ìovÿõí¿q6šøùwÿ¿¿ê¿þîEôï?¾ýöû±ì6¼Û Á&,S‹l“ñh8dð¾æ˜w.iÅœq÷qözû˜ë -l ¤Ikù‰.WLTH"Qå¬R0¢Êy•€D±+œ’ŠÐbQZ£E¹"éei£Îÿ>–7’d”pE]¿\$!5Æ¥²¨ò%îÀ›¥‹gÒ± 8D©’¡Œmë19]Rüó ÓÙj`¦“‡ ºÆìüêØ‘Ø=-f§ À“ÞŸxòÐ- ‚°,‘9å+8m!:]îGÿ¤‡u¢tÚÌF±;»Êí–aPM IRÌnšHÌš(´ŠØ×£«V,,•ÐÒ¥ˆœ0ol×Ê4â$ØWnÖ7<©*®|Uâx:šü)¿SŠQ®µ¢0hgèçeµEê´…SO\…ØCª{Fr,Óê2¬32sÒŠª†ÄléfÆ‘”Ø—Ü/iû^þA8ã^ƶÄy1/Ck²é¨-­ÙQéd+!r"iKë±*UœjWÜÒÛãÈ(žAÊ.ÇË*·Ô-‰ ú&ÖÜóŽF ¼JRò"=eJ / -$M~½¥ÅŸð‡,~wî¡)™dZ:(åM -­ü„ÀHz¨?`tI“VÛöüdÀÔæBâi@þN„™¤°þtÂ? ‡lν"ôŠ—’²dÙ ¸íè@D&àÓÿáêœhÀM² À@60+é-"¢b0±Ç#=³d£c¢Ú ¨1€cˆ…A€Ë"` L|-*åó–õ”üž»Û:Úe¤„ñv@Wvs- ;à¨;+z@eÕ^; è;Pàw àï@`™ pn<ÄG«txp¨~À@á€,¼/·M:ÓÃÓHö]˜4ÌNœ$s‚ Dû- ÖB€(ˆ€7Çà¼ÁlɤÛ…1L·J0Þ)âx?bh8ƒÏÀ2KÕRXLñúÓ‚;(³$ÞÅ*ÞñÉ5ÀŽCHÑrÈ̇0T.͘OÙ‰Á -Z(/¥ºJápšGÇ)êUO6ÑcµV¬T£Õ°, §$`=)‹ÅÚ, ;}v”i2 Gò´ß;^@?È­¬¹È`†h,ul@Ë'È’ɹ}cÒH°¼Á çö°¯tâ€-h/D&¨qóŠá±A/H4ÐSÃäý4઀¸Ñ²ž =ôÑ$®a¨Œ‡–»J9ïØ÷qëüÈ9GE8åñôTÌt4PòˆT?@òå¯ï‡UÐ7èªèk%‡è‹±“g!^2Kôü‡?Ó#A—º÷¤„÷'|Ü)¶›}«tµ¸° Rag{Nâ#VN@í¤SE\Ömîw/; T€WÄ´!fì1uZ>V&ÇÀJxóKºi®÷;øÅ]dkÒh¡è#®’Ä'íl²õü|"S–ä4ŠÀuÃýu_d»¢ã‹Ñ±Wi7ß6:BáK¶£:4EÏoèùñeA£Xad:áéÃÃlü@ð‘A¦ÀÉÆÐhȵðRǺú¨ I¨Y_{˜‰ÏîTòhë ¥{Ƿм*ióœD_U9;yZêÉ ð« š¯!š¦,w0‚Ü8¡Xçz.ɾ>Z95…º”k6¹î2(©»KIUæ„/)/}ï+¡a•% ШðÐlÓÚê!íU,{¢bYwO-–AÄ«‹eGÑîAs#ÑÇ.@( ™P¦LcB œÖHË9Ú ÅÔ C -DzœQÑ¢ö–·é‘2ÞC/_róž³äÖOŽ/¹yíJnG4hÙOŠ^ýlñÌ8Æ%öÙ¶Kö”8&¯Tɲ²qŒ8êh€d‹t6oÉ “-²]«˜ âè¹ÀVV:’Åâ’,«ñé©j s”]"”ÿoâyƒM¨›ór°ÁƒÜI'“M¶Ýujã†ÝFu«E¶&K-a–Í6³c‹@ì³ç)…I50‰T0aóe@Ià€ÈpŸ±š - -ü« î³Ç ¾ ƒ`…v çˆC„4Å¢íî©ìȪ:"<18:Á–ÌáepæÚtSœîϦ<7L‘Nœ:ɃÛà ^WÒ8©…6A'Óö[(ÏŸ âDa%s-Ý‹Sž‡³ÜOÁȾ’yæ0ÁŽ{´ Š(hÈ÷\è ²Z¿÷–Ñ‚zE‹fhWóÔÑBš‡óE ©‘çQPˆòý†ç†ò8×D ²OðÔí½´ !`˜ B>›W"àT³åã3‚v«|=(‘gÈ®}·ìj‰-@ôŸ—MÖ”Éoš8”P­œNë7óäp˜LÙæ³í\èÀ—ü¹#4¶ùüºC‰Õ~'E&[|®I'†Ö•êr)ðÜ åwàÐÕÊŸNÃõ¼îqPM‚lCÃEF¼E ×Q\|"ÝÙwÖót| j.?böTé|ýN²ñl‘ÎÁŠ}“¡Þ‘+ÑT«Ï¶¤{áê4Üá/;6m¶ÅP‰¯Tƒp0éÊ:$xS6éŒ;Xq0)`g;$ýb8¾g‘XõqÏ’ïüѯ´¿ù3ÆÀ¤Zä´600 lX?”Ðq &â;#ò0fŠþL -m¹[¹|v;ˆ(ÙLÚ«çnäÚ@eTpÅ©§€Sýj¡‡ž/NA‰,¢Î…œKÆL…(Z "Øjÿ`ƒ,P)¦“ÉI«,ˆ•Á«än`„ùoµ®Ä£ÀS\5ˆO@ƒØ? -BëoÍ;_/¢¡Äú—Ú6ê¡[_äËm§Ñ0º¼oã&ÁE¨zÙ­˜VâË®&±\x;7Þp$z€ÀEßjUˆå‘ÇI$ŽHâ¢ê¬ {“Á¸p)½ÌœÈeŸ‚“ 4bÿ$nÀ• ‡¶Aºw ]‚K*¶­’܃;.Âůí7ájb r./"‡My {ð}¸"tq#n‰™âk”j¶…ûõŸÈ͸4¸ÂÑÈë'éôE¯ß^Dc¿÷¢×ÍF/ÂQ?õ§ úo4UÆY¡á“0ùIj»!Wê'e—øŽ\!T`ô›˜·ä’醒·þ±z5~>ü£÷Ÿ?Çû›èûß~]ϧËß^ý6_ÿòM4›|ßûû¿ÿíÕBiJ“/Ý”+¦(–‰˜½<¬„¾ÕÛrÉðlâ¾\pþ$ݘ;àWæR"”îÌÕÅš?I·æZ ˜ß›;/Î%C)nΕ³ÆŒžÄݹb¼¡M|AI×窫“ÝœËW°É›ÞØðìoÍ…K¨/­4 -C’áz‡î!îеݤTñÂ4Ë•^œÉ…W‡¹+×r9—T£yAn¹ôÒ­¸å2(†Eæ%eøÂ0)_‰ûoÑ67§âK»ô6ˆ”Ko帛mÝ}‹©ÃreYZ®e7’± iåwY”T-Œ¶Ñ/$´]—Ë -ÁCò’’«y!.Ðc~Þ\‚«Ý¦øLo¿mé–·ëÅ·Ïîâ[@?zñ­Œ yåír—ŽÉnÇS|VLí–S<7Ùx¶ž²%²i /×óGx&çh(.x ] ö‹æì.a‚ád¶Á×ç^EÙ6DYA¡y¢,NU$ÊâDòÍè‘É|ÕEYUJKŒz¤ -*ÝÇÛÍ+I“%qô$GyÅ|‡ÐÇ&—Τީ›'¢jÂñ±%SÜú Ò‰$SÜI˜ô\C2Í)Ì.`vá”/ýú`zÁ/©G¯ uI°ÕÁ‘ô™‹¤‚`¯"éU$­#’Š5{Á")…ƒ©Ôqy=½3Y‘G±á€CØôŲhM‹©Œ ä(›^Ø)¨1hýÒ³ˆj(>çøLôÞb2½¢É‚8–à 錽éÂm÷jI‚œÍ¶¸OàCâH(ŠªÓì. -«+.õcÞJq¶+Ý÷«…&mí¢‡ãù +Ë3»kâßòp! 4ÿÖ‡* j<öí¥ç»HÃãÇ2ñ½–o‘º¤û?­b¸®Y8üÕŸ/jßý™¿TÕÅÕÒjIÚÚhûb˜tOÊ X³I%ƶ5+úm,\âsxÞ+ñG‰j¹ƒr+ÑŸ&VWbŠ¶Ù¶…è9gŠÛ¬>l fŠòÉX¯š"²d#5®eiš<—ä)­0) -=d÷†#u¾Üd÷ØÄõ%Pó Á—„¤·ÜËN¢óOœöU׿¤×°\ÉÐôዼò¥·î¤÷œmò!ò àŽr—huÇûêȦ÷˜sƒÐM.ËÚÐrµyšÒbBøqºccB¸ÃjÃDF4mlGÇã“”¶{Íýz¾J'§Et”ºrÖb¢4ÂVQù®û -i‡¤áaD‰UäÂÀ” =£üç$Aµ~jGìiâ¦w,À[þ‰ä®ÀU( õÇ'ÐržwpzÀú¤ƒÄªF‚Ô„$¤– -•ã©D:@Õ,07$¢dÇW! -å n#g¦rJîè5ÆÃK>w±Uˆ²²òÉáú¯ü½Æ·Rù %³‹áy7ÎPÜèsæôÝ‘éû*v\ÅŽb±#ô…Øaå…Ë ÀiŸ”RîË%Е´QEÒ"ó?êEr‹ -°¨äpü®w@6¶[Š¾¡Þ  ——?A³û½Oml¯'N¡,Q…²+²’Dæ•“È~”Ú{Ç®âØAÅ1ôŒx9E_e°« V"ìRÏ*ƒ]®¶ËP‡û9¼÷óÕýåFet0^§`$³]À_Z\"X°t÷ŽÌ¼Ñk϶¹³Æ‡zí“åàÆ@Êr‘XcΉ¸ÅL¯òηèÃûùßg»‡_é@ý@P…c‡áØv¢|óûþSh³(棽$òG ûø,X~íå‰Ĩɞ—ÜC7TV ]r _G)J~S¼ !"ÔEÄ2~Â=Äá"œCøJ‘ËåQ+1jK¸[ˆ¸í!ù„HÓ¡XõPKšÒƒŠg±n ñàEúQÕÈ›mÄ»í~*¿c®!fW¨cÈÍ!°Mñëok2†þˆ4%1ºrB$”*Ü&aÛ"ÔäK’”ÍœD©ŒÞtáJÂ~«¦÷}º?¤&¶ž„RQQ¡CH Þ<2ÿlëÊ5ªã`.^~ºàµÆ¥w|§G£µ¬l¾BŠ^!¢å±+ä¢ê/¯ºËw¥¢Æ@¨ÖóX«Òºh¾Z}ó•Ýžë’LºW~ÛØd©>:粚-Š«æ«ZQ^5]Ñ´°=ÕºÔYÒ–àÅOs“hMåVqÿÎÚ²Œ¥nf±½®(TÒR³j¬&¸j…™Òˆ!­ž¼§×·ùÒ(ÉV|Ÿ¬W¹H™m²‹ô™–).“dŸ±Neí¼whêB‚®znC$'9›B61Îàóö.ÇHœÑrÒø…cBa»{gŸ*/n³Ø­Š¸Í,fª‰Û]Vd#J„En[þåÃÑ\þM$ö;FÍÜeíÁ¼¬z E‡9&?Í„5E[i”«ðÄîy"h\¹”IÚ×/àº'Ø£™‡ùh{c‹¦¢{@I´R¢t¿Ù æñŒÎ‡tK»2¹­Ûÿl":[×n+¨J%C”“æ ÙbñÓ„*àÐgVqx“ Bæ¨ÄALÔx-$=£ºÕ4gsmª¯¬ áŠ/õC.P](õKë·•+Û¦ÙÊŸý;9ÞÓílù ùƒr^.]IĤÇ9 w -Ôƒ -9ê±.œÜÅY8p‘tOÂ~÷°Ú°'ýÎ ñL\jî€eñbáÔ‘ßrØõü;92l[úøIÏx%UU{…û'*#ì^©pX6 |ü5$bái+ŠÿýcIPˆ›^ºyX -Î7›Y6?vH-£ŒÀèûlÛy\í;éû¬³H'YÛXsÃÌÏô£(cqå«®va›͉qšßéñxMÍIì 7T„â%®™„a59»t¢WKºRÑ%éNBæûÔU'AÒ?’ê$ ÚÒœ:Qc~JÏt¯Év&òE6;a=×m -XdVÖ8‡º¦KR9ëªhÑ[ _Äu”ÓÉqù€½äfø)Ù@·£O3í¡[ЧшÙmIbß+ ð}¶||¢dèG¥±RÕ²Ic¯% UÎ#•·o!õseÿqNËC“·m÷{Ékµë4lŽ¿%«²³œ%›ˆQQ_w¦óô¾ƒÖÌlœ±u>°˜ä³-ܨÌcböèXL¤’Ü-.qh¤ê´ºŸ4ìÛ_’ÎÔ))‡ü8$ÅÊ8$]½‘ž—7’›Žj:&›Îå\‹Næ¹ ÍU}†®~BW?¡’~B¡•Ô/ÛG¨†PÿêtûÍ«{гpr—su ºº]]ƒÎÇ5¨ÂJ½º]Ìr¼º=_·  -+úêt® øø.A‡4¼ºÖõ§š¸}uû9ãu–?½ºý¸ýT‘m¯.?g@üI]õÐÕåçêòSÆå§ -"\Ý}®î>}¿, ]Ý}®î>gåîSê®®>çEAPZ¥wuõ¹ºú\]}ÚÑ•\Ý|ΓޑT%W7Ÿ«›Ïstó) •5Ãö³×ûL¯÷™žþê,qŸ©L”lõü©ÍûLÁüzŸéد?¡ ´¤ûL¾¯÷™^ïÒj|Ÿ© ”—k”Ž{q½ÏTH®÷™^ï3=¡,Q…²ƒÝg -Ùõ>Ó«8vÌûLæ®÷™^e°*2˜yŸ)ÇÅ ÀȘ’þQøÂ<†«Ý+†!º´*‚4m•Æt &‚˜¢Š4).þÊ¢ßÝ%_i&z³»îW6¥êìŽiÚµ³¦Ù]ŸÒ­òABÔ -’B°BïÔþ‘Žœ•~ê!~ìK(Ì!Ét­IA¡8©ÁIØÒÁ'4¯D¡ …ŸH«E*¾œìc´S*á*í\¨´ƒêüžãíUÒ¹J:%$ˆK:2ð]¬”Ãœ@ÚQöüå~VJ¤M¾ '_HäÝù%!/æ«ñ;IÐeeº™ØOå‹üÓÿJµ“ b Ð17†f»‡árE® –¤ Ñ=ÛÅp+±¦ó”tøË3sN&êr©!îôrÄ*G4‘z4¡E¯Í¬F -ÕT]t•~.Kú¶`‚èlÕèaW1è*ˆAa ‰A*0^¤84/:i»˜è!0 ƒÓb÷µyV.¤c©¸’9<ºQHȈ´Ô}¤Â¾jÜ5%~7ÏsW?A‰MvªåÊ#žzÈLmQ¦¾3ÓžHa½™ñ.%€ -¨Z·˜ ÝP.«ç•þö[šà²L|È€Ùp‘.ÑL)ði°ý¸þür™ý5ÀãáÙ{ŸR'Ž£RÜ@ÒCr2 ÐC{,É9f @D´O²–ÛÛ/©Äv‘ “ªt‹wŠxD äØ—êg6PÍLì²T-EÀ¯?=!„ û• .V!ŽO®oÌKm ¹©I“陧Ú@Ú©4_5>e'Æ'hD˼\pŠdp‚®ž,¨…O=<ÇDÐF±R!lZCœ²¬—’8õ\ä©n\ mú*Ú(Ód ŽDéd0ëfQ;”Pk/2˜'ê• ŽhcB29·o $Ðñ°ÜpVžžîBد䥇Ïcð8¸„2®Íå¡?2ÀiðTä ;­Ê`~"ZÁ••Òò Iƒ7'ÛvrC;ñ(»µ \ŽfI õSÂ^–ú~¥ÝiÐUÁÔJ1Îc©Êö[º8 lª çÏTi/ˆP%¡¶¶“cí>#¡–š`Ʊ ‰rZt(¬²:.æ ´j Ó±3¦ö0+9Ä€µ¹óì -Î&ʱ °e·œOK¼ó£n%ùNƒ$iÊÊï'YˆXm?éÕÞOq ÀïÝŸ;äDPÍOR\,m5Yg¹ê¬Sôw¼Z¬WKhù 䮩2”µå®Í¬= ž€üg@=¯E*±ù2Ð'ÈGÐø§W\AÕ¿ýúú0&fêsÔÜÎnÕ!ö m>Ïfø"ÝùjœÎ;«Mg“-V»ì‹Fpƒû&RŠuˆ' ú·Íì7¼hôœ²¦˜Di«‘˜´˜]ˆ˜TNñõ¼¥¥€]k~zi©¾öý(Òn>üñõßuÄœ5 þPM}¶m?‘€DÁ£!Ñ£é'gÞb‚™{.ðSq³vë1æ§1m8 -xõvñnŸ7l……-h¯²ß›-;£Ç]vª ž¿:øE„ˆÊÓ.zV«y–.¢—¹ÞdôR N5[>>#¤ê…MJž!ûÎÞB\æ¢ úÏË& Ê\M§m% ñÏÓiýfž|¿ Ëü [æçµ ;¼$À$ƒí—DºëÕíŠ:Ÿÿõo¾û¢“.'°“OAÍÖùüí¯¿}×p÷Þ Ô¨ Ÿ”Øì¨Øî¬:ˆ+ð[Â1Ž’«sÚÅpQh 7Ï݆?¤ƒFH-ÏCUûŽ£¾’yÞð1InÌB‹o±×f¾tUÖqe:}ÕÕÇâBÐ2ðB¯xÐ b¿Hóp¾x 5òÌñ .ót»£÷ÂœäѬ -Ÿnä ´Ë6C°˜KwG y’Râ vЈ'±”˜7ñÕ&ðÿâ~`wƒ¶X[)Â?±í©Âˆôïfeegéf ©SæÃÞ²9JôcºF',mÖŸäÐ#Š÷2J#¹G£§ïE¹Uܤ#‚úü¢‘¸Íݤ“‰½R¹¶¯'“ïq>\D6™áúÃ(/Ïw(ËDîVa>»ªß4Î6±$ó·$ÉI˜ï ö€”½ »yÿ€R#«ÑR̪ånž"º.f¿7ø=,´M‡¯áVœ´ê+ “öbJç#FƒúWù’àÑKê©û’Píö%q§~ù‡B̟̹L¼z%½äeI ·ù'¦Yœ4Vo³»Ž=—è8~óÕ±ƒåÅR”i™^`x˜Ù»Iì £Ä´Wzx1tŒúÝ ˆö²éãÉÄA5Ø$õ]b]4|m9亘&²‰u✄ÚkxxÃËl"ÓEšLk5b1KÔçê’ü\²\‡‡sžíô vÖŒßâ”,+Äޛ﷚s†`Ö,’u„/Ï/Ë6QÐ%t\p<ë†øk–zLÛL_ ²¾ -¦WÁ´¬`ÊGüNZÝ(–¢IÚ?ÇûÁÌ›%è,Üò9H¦—|³ÜòŠhË­gÜ>¢QYXR)!IÃHíGV^³»$y–ŸJÇ+B²'ñ I -ˆš9õ]%„«„P,!HQ õ…ŠC€“!U?•èÆ.¶Š²ÌmܱTdc…é*v&Ý(¾1,cz¬Ö™V¿NR(;Œä2þ½—š6Œ‰Ù©æÍïsøO!žÂPÉq˜Ó­íù!”¯|I.ÉAR€±«èÄâ¯ýœ°žI«ÆªÛŠãŠ¥ÈÊ.ª³:L,çCŠ6ŒÙŒÓåj9nû\y‚@r?Þí7ÙK¨ô%ؽüßO/™jÑÐÕ/Ê¢+’tOeKc|b.<Ú•ëHyFE<&¹Cæó*ó²½Â·à`Úí@Ë.V¼½>‚RÈJÃO&¶)–Ž‡ýY -«IÈ`?ËG+˜Öˆ™©Å.—›åb ü_k…ý )|ÿ‰YäJ¹ÌW2ǽ¡w€r÷ÐVbˆK¤¼†y) -'EìnE¹/‰¿Ìmve“]ÙbW\¼%Ùë*溪µ.–îŒ,¤ßª©.µÔµŒŸ°Òué -]¾läry„k ÐÒnËÌïÝYÜ?éŠ{͸ïgÉAÅ3X¥ð"ý¨ê·Äù¶xG|=ù;f lv…:Ýøúª^[“YôïDXX)*¬ª¯lW»Š;àŒµ,u:»‡ÙVp¾]ô,h_ÍÎõînJmNô‹õ¤]›E>t#mÄXPkºck -AÒÖ¯ üBUâcÐÖ“X rôjC ¡cQ·š½ütÁ(Å¢T—€©X)é"£X| )<†›šǵ jh 52Æq158_ Ü]7 QÆà8ÔGGi)7ÂEOÔ_ha{ªð¨ƒ1ÆZ(1OSªaq¦KàE_Á y -4ÌüÌb{\¤fÕX*ÄTâHËCz y¦oʤQBDCâG³ðÑ\ÓeÉlƒd-n4-S¸‘° ÑƵ¶GÁ'* \RãH ôÓÚ& %½h -QØùE| …Aiè²Ë÷ÃÒÕ½3〕rð¶"ãh 'Ûl²ß÷³Øü@è軄²Ž¿ª•C¢FkZœ]Ý’îòm¬eíï,樼üÑl1³x~Êjöj­æþE~ä Ÿ»ÖѬV1’Ð]0Ä á ë¡ÁíŸ-±Ë46¥«":DºdŸÊÂ[¨Ã²$½éRèº"Ž½ˆu9/(!çñò†0~üF{£dÒWnžÂûÚ ^åýFèj!±+Èž!ÈöýËÙCîa†¿•éö 6D/Þ<¬>,;²eçaõ>ƒOøËA£l]d='õêì–Ë (%±ú`iÌrCÌìÓ„¤ü³ÌâæóÁÍ <©pz~êô>•MùÚ87Ð쇒~ -ZyÛùz>Ç(¹%—prnázž¤óùv?~è¤ÛÎÍnµšoo¾è¤›¬³N7;fg¨ µá=P:y2%ÐpS -z*Ö4?$v>-œ2ƒ¡ˆÅ¢žì73±€LL£v%5ÎKʃ^ÔûJQ¸kƒeù–V·@Uꉱ`¯ò¶ÈQQ„^½AŒ?Ïþ…vWØ\úG³Òí–½¯èçh¾ÑŸÌ¢ àf«yËŠ–o“ÁÚWGŸ“lÀNMÙ7p&šÝ… ™\¬à"`¿[^\VÏPYk ÐõMɊݺ‡W]ˆhøº'†Qw~h`¿wX!˜ž7ÀM&S·¼X¯ÀX¬³[µ¨]PÅ_v¾SE. èÔJ6ÍêÎ>h*”JÚô\W¶Áös-˜žÑÒmË -Ó3 ÀàûlùøD­Ì ®™4ö6üAïXàî¶Ïîn~®»‡FeñHÝmcÇè®Õ®ÓHר¤ïøbÕ´ÉlµàÓŸ¶M'ŽÐ»t!/PÓ•¹œ s©½u¸2— g.8è]‹gÈR’˜«©áx\ÖÔhJŠ(°ÚvPr‚ÄGâ þÓæ /ü¦,D†ýæ -©5Úk.[PH]Í”ÁQ⨼ïúÙ˜)Rã Bü/˜d;ëùþ¡TmWö›ÝQs¨×ß2Û+²ÒdK Ü/a³Åz÷Ø!¹‰q3U<íVëÎ<{ŸÍY)³lËâ15$´h.¹ŽYè¢$W^V=äÑý•™äú4¥W÷´Nå*Îí‡4@ƒ÷J´êì0 ¢7fŠË2ð3!`ƒ-ºÃi¡‘ˆ!Ív³#{k„Òëvõ   ñËu^·«G߮ԥâÉ’UÙÙ‰ÎEãß»Rû**$Ñ-ìlÛAÿÈ:1{Ô6¦Â{¦Ty_g“ÛÀ0Áº>T& äB H-º¬HàêMÀhŠ—< ˜¤üÃ,q½%ül9v¸ãJap<àMe1ªšD‡Ëî$Êú“+\úJxŒ¸”C„Ö†lJ’êþSÙ(à}ÊÌ¥(àzñPna¸ï ïÌ$ÂzÛ"\]3£ØZ¿1$1Ó»¢~Ãʆú¶`.ÄËkxûsV=‡ðö‡<¬;¶6MkúywjhHÄfÝ¢‘r^c¾?͘ïåÃÔœIÌ÷C.Äöc¾WYŠùÓóÖ"S¬]Yä¹®³¤®9ý•GŠ¸{¿Ò z»·ÀTä–ïk­PEc}½ÅàŒV¦ïy¥—æõƒ3»ÆÀzÄXÎÌ#wkLÕEc’¬éB÷¹ÊBh#ª¬x”Žè.†Z9ÐzºÉ&_KUõFG@0½I²ºCúpñ‘Àüò’u Z¤Ú&Ü*eû|Ä\g¨àqˆ¦ž€mÑCºJZ©ÙÕþ–ÈX-ÈÆœúª-Ækÿ3_(É5Œ¿jǃ°¸Aì~Ëâ«j¤s8§’ †Ÿ Cáï öè­¨ËÎT&ÈÙè?sI ðzÇ—"røt! íáà:óõ~÷€Š™tF5QðÀ±Ec²6`ˆqhºBØ mŠÛßĦÒËpð¨ØNJ‡¼$ܯÃfèî‘Æ«ý|R~CM~ÍÝŽߌŒÑ†G¡üué Õô2Då¯Æ«Åš™ý(µÄ®õ¨°? Wël“îVLÝöêçŸÞ~ýú§7´L­†.ñ­¢g+fVEUdm1É@±»‘ ¯NçÀ’«Ásu"@´öË~4ŸmÀ"_Ø!Ÿ_âÿºC ÎîEurÀ“`MºÔÌ«Š¯ ß\°UŒÄ+â- à&Kwm¹j²²®®šÅgØ^ù[=5WM1ÊUø Yü=SO#&þªþšÀU“Žê±`ápò*lDQ&,ÖµDVùMÐØ@©CwѾמÆBÅ’ võ?? ¨EQ]P«ç~à¨?çìösñ¬%×óCU:¡¬pTÑbµká|äºOlcÝwë®ûë>ñÂ÷‰ ßû…,Æ \ƒ1ݬ |O}SŽ£l°TñK¿ó¨„tДv‡-ÆïF«"®<ÌoñÈGFÈzZ¸ÙøÝã]Ï]£ ¼±×]Ÿº¾ÁkÇ [­áÐ|«j«â‹®¶Ág‚®I{è*depõ%¯ky7}U¿S“¤îNµžúí ÁÏ{’™¹¢¡9»]kÔµíZÇ䘷ÃF9T3"×Í#[æÞWnô«²ø] ¸:H^­lž£•MÔ/Bbesè;8ÌAÎ5ûú6µ’ úòcúñk -|kÿ„Fsó~†1‘³Å”2Ö{9žIªzÔ¶ 0ß%zz¾¢f,ºYŸPS6¾ÀtÙü„Ò£Rª ŒÚ+£ªšgÕ@þfArÇ"ˆv‹EEØ1eÌZÍ(•–E3òXk?nŸM= z%»y‹Wf$ð©å*SHœUëÙÀt&"L³suê£N!øyÖîãx„’Wù\©<ºÈ¯*†½4N¿÷"žÉ‹h”¦/úݬÿ"é¥ádâwÇÝÓ¡â›wÿçõ/ÿñ_ÿ˜½þñÇÝò›Åtùñ]ÜûõÓÑõÆ}ó!þé¿~ùÇðóøãwWTt¢b(¡"Y]dI¬˜áh´p>17†ÕbÁîïl¥P^¢åJ+㢚YGF­h A<ÙÐVîYcLe9Ê6/%Qcì÷&½(}ÑÉRÙäEoÜM_$AÒK’l:ãS¡Æ»Ý«eÚÿ¸øûûü×ëߦ?¿úíñÛÿ|ŸM–ñ¯»å›èÕ¯‹ï^øiñþÿ_Q£X–’ÉŸ‹SPˆ]‰ÆÞ,b…‘B]”VwõV®ÉŠ²Á"$˜¦8mÞ¥WËÕµ%“®³1äÅe"ˆ}²ÊHäý¬ëÇ/â~’½ˆü`ò¢ŸMÑ®,‹F“qâùQ?;ˆü}ýówÃѶ÷Ívø×Ëmwl†HÞ|ñq¹ò^|óñÝïÙ:~ñãö¯_o¯ RyCÖë£ÈáîN 7Vä^ªšŽ`“tWzR®ŠÃJI6æ„vD `íTùOæmržÞùjõn¿J‘Óùx‘•òI¯(û¸^mð )]yp1 ŠÝ.në ½äì.$©²ùšZSQ û ÝçCB¿Àû5¼Dßt±Ñ˜8rn÷£Ål‡¡â¿xi‘!(œÐÁãmV觵«ôp€Å€]¥'M€ì°ÌGɸyJDmlÑw½Ü;ôªÝ'ͪ:Á¢`!•®ÆÇIz8£·ÓP<ÿz¼ˆ.hqÿ\d¹§ ŠvÝA'Ya`µ6h &ÿ"{I¶Ëá -’ªwÏõÔÄüî9ÈAîŸÃDɘq`^§__Çrk—Áu•{£¸,ˆðÛ?mÝW‘^ã÷°6gDf¢ê«„m`¥VS!R’ˆø!kËåÇng~$ØžJLYÿ8c‘ø§Du©/ĉlBŸ€/”€‘߯“éRyU¤¾À”ú4Ù†ÖAþ¸D¿ƒŠG¥nÌ-€›£V„ç½±Ï@v€Ûf¾ý¾#ÓñUt¸Š%D>âw^ ð°Íàj‚!„9¶Î‰‡<9¨äX%¡fá'‰ë”^jò•æE}Å.뽟 -“¹äN#=ôíÒƒ¬G҂౞™",¦òpæ’ˆDÂI$a‰,ˆ¤:!iE¿ÁO¿°Rj¡"½Q¼K±*zbw9š²GRdEª" N2ÔB°ÊIjÑdbQjI¦ßölß¡„’†K yä´ëÅòd8¢#ù>\³lIÒl‰žµ Ñ%V•V—+‘ʼ$u¾**)‰ô]Š­8ª\’¤Þ‡D«W”ÈMÔL¸F³Dv²îw/$÷ë¸_½D­‹2/É+´u…Þ3—Å 4Š…v•ÅŸ³,.-îK”Ť8Þï -q‰}Ë|‘*ÁœXÏÚåké¤ÿ@Çšòù¦!Èi$Ð*ë?ØCXdXn«›/eÚ¥Õj²§&eöDÛ¦–"GƤ©¸”)—[EÆŒseLV +¾Äi'ó¾“ø¡¤¨3Jd"›t>Z"µ|FZ"¹*öÍ DŽ¤OšLˆÍ›T'©Xìaéé¤ì/É–´ØÝÚAû"|óûþSÖâ‘ ¨&È"½½$òço(1—é ^dÌeœ.WËÙ˜pÇ8Ô… ˆÓòî¬ÞLÓqö’MÇK(‰XôÑ%’&^Íò$ÁT˜´±¶ gG­æR'íŠx„Šx³ Ÿ`Ë,§ìçVöËyÚžÌÏÅJL‚RÌÁ'öuùÙ÷s’÷"!ïIkï’>Õ¬RÊkˆ4`­ZðÇ„¼'œ¨ËnsB×).úØh³€ñ’Nú„½U\ô¥éÐ\ôê¢_nPñL,f²â›rU ®PÈ‹wÛýT~Wú–è¶#ÔŽUg¿qP_wØ‚ªñùÒ®ÙÍÇ\ߘ1@Ø^Ë.ãÉ™mÎåûVÂiJ›»6°¤øz?è}Uöþl[ø^ÂPÄK3ºæå NØ/ 9±9lʬÑ0ëµÉ÷Ôëµ¹ÿ|¥v‡ÄÔ˜ß~»$¡—mA£O…!Òò­"Š¦)’ÐÂöªcp£HAeÐäiÊ"ݸ42ôd§à\Bw£’~šUcY¨¡KÜ$§Çy—.’Ó.‡³d¶/W•°w eJq)hº‚Ùöš¬ˆ kdVô© I· ¨K¦Šæ‰ /Æ·0xîáÃ}¿| ßÖ‡۔„G<ôsªš³ââßd¿ïg±y= EïS (q*\³*Ž«ƒ›8k -j ‹&ÜÖæ­ËÑÈÀ¡ ŽKïÚ.[òòãòQ©x£<%¶edLµmw¦?›Èâ¨1?IK ª~ÿ([0X£-â‚yå.8®œ¯aœ† ÒD˾gÒ«Œègw‘g -^kò)} 8“ZzAšmj‰ü\4Û~ÿ8ºm÷°C·Q;þÎͮϡ(Ò¼NºX-ï9n;³%EÈ­$KjRìÕë)ºÉér ŠnvL]ZXýf–»ß£—àüöëkÆ~ }Ÿ—'XyQï+E,t×æ³m>ª¢ü¢J=qL®¥9EØ°s3Kçh%O:øäúG³vÞ9ûŠ~Žæ«Ñ -ìš<ø[VtîýXbôyp_é…}Ï´If¢Ñ%ïs¬¤¯sÀÈÚ\W@ò!‹Ýâçàé!·§¨7¿`ç3DÓn7ç«1¹o¾æà¹^yBg·jQÀÌ$-—‰$Љ•”Šé±8$¥n-sîÀ~j(ø®7œ- õ®÷0_o*¸ÞTp.7«%ËßVˇµ—éQ½•CŒAL\úÓÁœ•ƒgåÓ¸;¼:\.Æçì.ìP»ÿ©’7‡ÅÏBóæx“Uwè`2…äd`«IªBr,PAº¹Ù*ùç8i ¢Ü.ÇL¤’DH›ŒT–éPR2ƒì¢\.GŸÅ—eÊÐÌF=”w¯ä„Š?Š1v”[qI9‚ÿÙ„GRÿ„×…áëòலÒJùôR1›W‡á*[­üߎf-g¬Nõì kG¡ˆÚ§óágêñÛΩòé>®.¿_]]@jŠ´J°õ§âø Aä->¾` dŠŽj”ãyÐîE|w_K|—˜(b‚ç…6f©ØŒ½eeV‘»¦|h«Ê–=N#žcÈôWŠÀcËø†'´:¬úöÌŠ¯ª; -³’Ç)‹z¤Þ-wL úîZ·ßÒD=§ìÎÙ‹(Š>Ãcér{K‚³R—Í·¸±\¨¬²2½!xà²v½ù‡Bñ.×],5åfÌ‘ã`H 2A¾‰Gn_Z»ïWãtãô(ñÆ2Ž¹í2j4سµ¤’”csö{P‰ÕÒ²Ç0,µ¦3q~KÕá8}ö$©PM|yõ&f¬‚JP–…|»z×{ ŽÄP¥XðôÛ<ÍW r’›[B6¯G¿Ï&ì>Áó•D«x$#zøC}d¹uõI¾ú$WÃGá:äVóƒiw{†ZòÆÇâÆí}ó)íê’|–tuI66egë’¬lÀ`Uµmm\è>RB ÕÉQäQ]NUœ %¯äX—\˸©”òwŽ«úªîL¹±t]„´ÐL3¤þŽF`8_•Ë@K}t#R&ý©»Þ}ÂÝ‚ÉJwÖ¹)”±¡]TJæ’ ôöòÅÀ~RZ ôVæù\öÀ0ßjî¥ç¥pLøuG*ŸïiหeXÍÇP ¶•ÆP\#Ð@ß¼ÊKA _+»æëÍQ¹.Ì^£I\Qé ñG“8ä¡ÂyG“º –¬D‚¹àL‡÷·ËÎ&›S·èUgEÜíЗmm<®â$7£[¼ªU…¢4:­Ó ¶µ9Ž>ð§¯ÎiÙ÷J#´¨³MÌ…iÀjƒð ¦íY®yH‹Ð÷VYôµW¶:ƒÍ줱Õ+„²¢" -ñLrÃh¾µ­º¬Ù‚l°¬A `6^-H¼¬zR‡~RĤŽ')J„^ycU”F¹Ê–êÀ¶F¯D«În‰Ã]\X15[ ÒÐZH·yºÝuÀ–»¾æ:GcUiY«‹¨¾Îæeäl×}Ø«¹î¯QF´U}2r2ÒF”‘%Où(#eÀùÀæð’ïÁ1CŽ`8õ¬û ¡Gb)1™(|„ψù¸¾Dfw!á\³l -,šGê6ùÓI–È¥•p>U¶õÊÃ94Éqw«ê°js -¥Ä«]4 kb©HÔ ]—jD$±ø¼ŠÌî€$!m‡Äâ”*Šb^¡1Ì> O`scÅN¡"Û¯ÖêQYüfµÌš_©êB«ð¢Ük÷£ý´u;–’Oø=,)Ä$Êh! S¦“‰äÑã17_ÜwûM&BYð =zICÂØâŽøµ sh‹gÙvImÕb9¹÷bþj¢à°vÁ¬,ºYPƒ¤Du‹eýW㣠8Ë;@L»Óý3ŒÒ—[­NÌgìÞz rR F bYò—'eµßQþ––~yy›Gïƒõ‹g~{ûßâCY¤®$Ž;"qe^¬&{’9$/HÅL -ǪŸõö:°©¤ ‰hÐ!YK_õ00’°‹Rð0¬¬*²49ز„d‘Á@%Pzn8–겤.ÄëE¸WèóÄÑ–âß)*ÈV$gŒ§/†€ñ)#Ó«Øq;J„ÇH„Ø(çå y¹aØ]å%¼¨[ -¬fãÅ‚­AÛ,‡¯²¯n¾ -)Ø,üÆʪÂWû¦ŽJ/Ê- «&Å(Ó3‰j -#–h‰ç¨ŸWbü<¿¦³„R‹ÍLJ5è[Å\c‚‡Ýbnk»4¿Bæ_xÞOEš8}´QÖélžIj´qŠ@‹Të«i± - *}…“°<˜|ï±j ש¹~¥ßrc¸u­­²…p³‹e¤ ù¬@S—(š:h̶%5]DY˜ú‚Ãá¾üþýdÓ7K’Ó¼d1˜‰¥L…HÛ×ÒŠÙ4O¾Ð­³Õzžå)›ÈØ@¡CâÀ™.èaSÑrÀ5Ö­í9Zƒ¸ÛìrÁgG ¾RÉ 5XN5­O—蓉•†´tˆ´›éÈ ‘ ¨áЀ¡8jc3pë¡^ýˆ„ÒÌ1a@@'É@:~0#¢dE4 ùÉ?apÃËIÙÂ4Üš~ ‚| °…Ñ€°èµ¨p3£lg4 ÌÒHz‹ÖÉ@±5Èâ‘žY²Ñ1QíÔàÈ1ÄÂèÈeu4fG¾È”òy<5ü}"â†GÒpâ‚L÷>¼Ìúh žUt2chznÄËô£ú2U§ùž85Èï™m­£]FJHIõa7ÁÔ‚¦§±œ9™ê¼þv@!u `ê@Õ„ª2AÁÜÏŸ(&Tɦá@}Àm“É=éÈm“žôðüñzpCÉ˨T¦H&7œ ôÐK‘YЂ­€·†í—Tb»È…IUñ>å"þ§9LÛ€úü§»,UKÁÚÄëOOáXø¶’«Ç'×À71` … ÈÜd“¿a-ŠHÞÃ2Q½‘ùô¤aÃÔÌ´ÞXGwwŸíhY¯¤ˆ _!‚†â?ÊøQ¿Æmf)©|Êõä ŽQæ¶*U˜i‚2GÉnWÉ϶µ½'´¶:›lœÍÞƒ× -‚ƒÙ|ÛI—“pxŽ+H*?6´ºA±&Ê‘R Ñš^±ö²±6ê]±ö°X{”}vÐW°¯Í‹CܤWq¸²Ã_bPÔY£DÛF@‹gQqôc¯xú ú›ìjø\§ ´‘´Ž–«¾Å,µ©ì -4¶á0‹=ZVùÄ°¹×­„Í]›¥)+¯ed‘I5-£Ç4av-#™hl€DH€x!œ( Æ€ž„På½ù‰ËJg‹; uÍcÆà“Ö¦"% q:P4:·“es(WIïà ²™Ü*X\ZlQ&…?¬6íÊ\A0ï$9h¤úT&íÐ0xj! -üEîðyÃZSXc“¤@[çó‡tûM¾h&͹7x´6«]6Þe0B·Ô¨¦n­¬[ >h·`„3Zd»éBЊž B%^%„JT„Ós–'3Pþw¼‰ç (üXi{‚Rå-¡dä€ Ây˜èô#j.~bD¾ü*d´Ÿ¾:p‰®{ ñÎþµZ>‰}g¿»–¡€z…‚FPyÜÎäy¨ -Góõz%5òÌ¡ Ÿr üFÝqS× -y„ëîñH‹öpÆÆÉ3‹õ)#EèWAŠ@ -¹iP™‰³Ä -<‰?Àã¤xî€Éê 0æ¢'Ù¤ƒÚÊ;‘Y£ˆ< uPÌê~¶¼‚ʹ‚JRIü¸DPñ¨0JX"abÿzq?¦N=ˆ]3Nòú[~=6ÎÚ¡Ñ‘øPTô5·½«8åh¡9JýTƒ—xq5ËÏ@³C°R‡Ã"Ác©HÇ84.çE46&¦ Q¥~)ª„°'†X(ÿWº ›!«tÛè@\7zd/Œ(Bš{H›¹ýÔ“Ä6bôP^°D" Å;<Ä4:¤Mݪóáa6~ ã›Õ‡b£«åýöKb úá![v°ö ‡1ÖJaGÄl= wTRóúŒonŠ{&H_ëV‚züu‡Z¥8Oú(:`¿–W¨k¬3AÀ>UÉ2ŽœïÝñ«ü¤ëZõ–[ÚÒá§BÕl"7lÛIw;à¿èíŠó [Ш¨«4ŠUXØ:e…סfA©61‡´áf¤muºoÙžÍ6áEÅ„6f›!vkj¹_Œå™ÍùRX[/Pg/0:uRPÙ@„Ø€p›O©Áð“ÊÒJqevo]Hä𒔺Ý/€§´P.‹hEÊ%w6ÛŠ-¦½T/þ“• FÒ]´Òš ò¡Ëšð"1õüp.‡K†Ps†.½µ/Ï\Ë2PJzå›CTàe²«ôÓl-ÃØCH”+뺲®+뺲®+ë:ëŠóX—eW-Ô8Zt9í›@õ,ÒZP ,‰r5»ÐžÌÛפN%5¨ø£¯kZž»Â\Ä•™wÓi:dÃN03Ûúq«HƒBuGy˜40 Œ“yÎœÕ#¤£4-Wi{ʆէóÃ7ïÔ¾œ®Zª†cº²T—ËÉX4Žé-¶ËTÞºLbÇ© \Úv¡ºˆè[· Më MªTmP}Ò>\³N@Ó\ü¦‘! MéUY¼m§ §œšvD¥¦ê“’Ök„AGjdT:rþzÊå1_Ý[Ö‘%kMp *¼ÍÐiÇHrA¦Ó)¾3§e¨úÒ°Ùêka³Úœ­•§œm|qpÍÙ ‹"”Æx9¹Ï‰ªØw bÃWCßìÑ(A%lPH¿†J«‡Cîu«jÍîU3¬¹ŽØ©´±Vwq[ºÃÚκc%ÃÛÚ,Õ=óqÌWhX‰Ñù‚ú\ÓÄ›SÞ î9Í è<\rKEº%N¦xWö½Háâó“'›éihYtð¡YCqjgñŸ9ÈÀƒýri£\æ J3)³ËÖlÅIó‰¥3Í[Õ8•SÆÌÏlØuU1°T+ªb˜êË5×›áz6Ñ»±¥K.:Ÿ˜‘7Í¿Ü/†Kð$À‘ÞòO,Ÿ Ò6ËYYì}¨ÖH.a6Ù6Ÿ8L‰HH†ÝJ@΃Hj"­VÅ\» ŠMµýaWA•ãKv#°ƒ¢/ãü0§ãVÀu!€ÙQFFÝðWþ#´ê¸³D;ï0µ&»8_Z´r†<%Š,ÆÖ435Þ’‹2mÖz†ÍÃÕfíj³v6k>øLU4Zû’ -,4âûå{pã]¡ºeÿ<Ên‹n'%¿yׯvo‡µ{“8ÁìßúZéWSëÃ4÷€‰|®4§b¢yÊUæqi± Qölu†à4”îÔc,î% Ôq‰ÚyD]°qqL™¼Q¬°qql˜+Êç)W{ì!,ac{}KɃ^äe ™\ñ±) ‡J©bOnè$ætœÆćíø³ín¸ØÏÁbq¾º¯†TuöBòLw|-dYžQT쪠jl·Ðw–tˆ}0É®†ç„ê Cg¶ŠfQUcöAPwƒ¼¯Å™îŒá‘ÂùvD µäxäKÓû ôå)éihôKÏ°Û›.Ÿ)¸JŽàMߔ؎ÒÆrlê”-laQ\dp‚ÒK£ÈÁ½Ö9¤2´éÂ8hÛ-ˆƒ¶¬……pQZåÒ À¡Zm…ã×Ó´–?lkg^ÝÊSÎnÙXmÈvm=hKŠ;ËèÕg­eÁí¸ñÓÔQ£4ã]Gnk«ä²C%T_K0:‹l»µÛK´‚‚p!‡­>›¸P'œBKý[y³ šâîÝÜÃmÖ(IB/O¼PUÏ9¢TWÐ=çñ:%éçÙ½×’tøÖO#[Ù`¶‰§œÐ¼Ó³‡9gxš¹e¬ó9\«r°°#[³€¶Õ|[á•/KêZK9ÈaZ`o°ó í8ÓYR)^0¡'T喘§ªÀ­£¼­7‘‡TAÖŸÀ‹U<ÖR:Vž´ÃkëOÝ…ëë+OfkÑSkOÙE¨kªkÎÉqè֟¹§£ÒjEU]Ž9¸þªsÙZ«f«‚-Æ%ª\<û6aìÆIÔŒ{¥ÔSe76Ïu„NEÕE¯U¼‹ÖòÔÒðT^ò'×îèªâ³ÐìLgó¬œ.‡Œ:Øå£,ÃEºLïyƒ|ÍHyHÔ“tŠ"ÚYú‘¢F,;gHƒ«¦/îËñ ØëλeØ -âi¸¦¿µH‡’5ýæLù¾2¿,yÚ9$ól1Ëñ'-?.=’J«»§õšÏ \‡ÛÊTCr¶#ÝÞÈõQ]}Oã™Âà:•Fær´Žá(p#.ÏœÛt vsìžÊ±E¾GŽÇ8>æ@æ ÈåGñL½GuØK¹Žsì7³–Æ~3kŽþÖ€”.‚Žµ‘% P†^w8Û¡å“oó‚PÜÓlìÙr?œÏ–â¾ -'öˆfŒü¥¶züØšt…Äç“Ì{ßVÝ¥:'š³g.¸´ÞZ9©ˆz `ÒknÊ8uûN4› -‹ZcvfaøË CÙh”µÆãÂüWË—ÓÚ*]¼ Ýi™qC{îѼýåF‹m¨N:8×)b¯íŽèëi¹?<»l³L±çê)÷‡'Dz¢¢Lr»Á:“u‘&ƒeæ®Ðb°â Ô`°æ2»íY©CŸë‘¹Æ£öQ8ùPVKØTBQ ýöëk¦‚|º*(OJ𢞺H}¤h¨$™ßvÓID/û@É;`ÖR¥ŽK*!¬pMx|bGÀnÿM¶™¥s´¼'<ó0&4+½êÃ>>¾)oä´ÅAÓ±eE×ñÛ1çŸê%”I¦xiÿ­’lŠÑ&Ê;TŒ´2”ŽÓä¼Ô¦6¨üúü…ÝuºAZ6ô†”úäv›l2ÛŽWï­Öf 6TØ>}á"åV‡7*HÿTÈ)W­í’¦ÎU· —ê:ÊÙ(ºÍIøÍîZ@Rj¥m€W~p(¢]"Ñ·BXLðРÂr¡ êö²À_¯OŠCtbá½çþx@Í8Y%<^„Uâ5/Íš—¢æ˜&³xºÜÜ»,{^³¥DÚSíÚÞe3Š2ã.õ}8Ý E ÝrÁ­ÒÖ›ÕbµË,Wû’jñ‹ÙøÝ#»™M¹Ùˆ ©‚^Ì WCËIúŒíšå‹teãCˆY/‹OŠ`*P”ôA*äÚ/5bš'M~¥ØšlKX•‡$–s)û-­“‚H§‹®f×wãjÖ%¾ÇjìØïcíGE×ûX O/®÷±6ñŠ*ר¨[ù:Öë]ª‡½Kõùw¨´Ôí~±ÀbvîWd0®w²–¹“Õ(%½~«ÄõyQÅ÷†£ÎþÊ–0 ùì}veTWFueTWFueTÇfTq£²Üyü+ÔøWt9üëxû:·…ZÀŒŠ]š“ãxÕIµ—ñªËÝï_†Ek¦È<ΙbÚµ¡tÃsžäïÃÙíF†„Ó½J8W ç*á\%œN$nÎU.Dê#Âý;¥sš MÖ&ë¤óùêª Í%n™à»Ž×ùŸ±¾ìøèïx¾‚Æ|÷¢„óÇ/¾ìèýjV~ûòõú ·K“¹BghÇÜQ‡‘H˜¥•¶C.Á9¢^ùMò•‹\¹È•‹\¹È•‹s‘SlwÆ\Ž¸)*ˆÄXyûZ#ºIùí«(\Ù¾ò£ôúÛ×3 -Ê☩².:¦ìÎ_uæâÂœÑsEÞ |2Ã,ÞŸ³+©²Aõ@Fçî ‡^æ餢n„Ièã¢}:ìŠN‰Ûðà(¿¨ —FXî@– |¨‚íØ4ãÜ (ë5»Õƒ2%J(pÖ;ú ]F$EÆý¢â@V¤©Å½å°nv4qh"\¨t9Ñ*å|JPIä®B:Ÿ"ÇS7d›7‰oÉ™;’ÊRõ¦ºã‹ó¾Å ] -Ðx:6Ýz#Ž9³Å¹ á6O<-5âÈ êŠc]c*ÀºöÜ\dXm×d¡v»æJRlÍâöÄÖêjƒ]ê“®Ê} cã­(ŒYüŒâx”h¹j¸‘žôâ]÷$ê”»x7žžAÿH~9") <ý¹ÊðžæÞÇà¾o¨˜}8ížWS1{À&ÕSÌ¡Au³‡nÖˆxû°ÚìÆû*—;£–±\b§ZîJgU–·ê •ïsö¤º.õg>=&Δ½è6gÌŸF`œ1r‹Y6"¶¨ýŽpdõù¹ÈË#sf©(LG¹¹:è™yå9º¨#漹ɹ²Í•Q¹^ )ð®†ÛQmòÏëFÈ¢æíÞfηè8öB ¡—K;_¥Hh.Ö¡Üò¼#µ‡Eˆx*y¨ŽKÙ¹÷*Vçb©ýÍž<ÅG¹zåG×$Î)@r:ÿ¾Äꄘ\êe‰»ôãj¹Z<wÙfQáÖD0Qòª#”·ßaÑÒ 7œH«ÅTÜu³ÂÊl»‰ë5V¼žnWgóMhJ«w·ÉŒÒ¥+ö$š"E‚z_âü‰èµâPV~ɳãÖ>QÂ'k³lñÈÇÞÂ~ùfdÙ›½uXž;æLÏ(S®º,H÷rs]”‰{Ët‘³aUî~<Âò4qÌ}e7øÈ[^nÁsº¢hÊjšjŽÆ…©›ŠG‹‹²uÊ”=Ƥ҇­Ýçã1UJ?Ðý;*`xwœd– -CÃæóß㪟j.¬‹ÒAMNÙÚzâG”ŸÄàÆ©7±µ•‹²ôÎ…‰ ø.ÇF¡êâ`Œÿ Šôš«äm;ÁìåítÝÓw®›Þ0p,ší|‹FßnP°vÜ&.ï[5qi[[æ´÷¹V/ïE‚zè}Æãr*¡&_ëR®z9D‚e}³a‹_NÇ"ÜšSÏ°Äžz_ɤ!¤5UU©ìkÙ3¸á.%í0ô!\h±uêpÓl®…t<ζ6¾ç´Í™kÐR^¥ýºû²Ž?Š”¢lYÝÃÞuØ -®q» E‡«Ï΋]êÐÊ!nv‘‰¥ÄÍ.ǺÒFHÕèæÂTBŽÁ™-gî#jAGgVeLîV5:ùâ*R´l÷È–=Õæá¢T*®YÝÏœªÉŠãfwÎð¾Hgó–°õJkkÚñ>QñžU(ïmÉ»£Žbžþ­:˜Õл%,œQ¡ŸÛñeV1݃¥]”¥…kT6Ù4Ûl²É0,f˶…ØǺªh”O6fm‹R=y´.~œ6«yæ^r>Û—âdyº¡0²Ä@†¼4€#.à°ÒÖÃkÀÊ3 Xé3Så -+¿¤„¤F|¿|PåAi)Ð@ȺÓ-Zš”üæ]¿½<ìĨ­‰ï²æ1þ ¤ìc‘Çöý¨<Ï|¥Ž< Y]m° Ç8@¤¬!xji$à Ž–XQêƒóºsB -”P±h~ôòt«6?GhÓ§ÄÒõl¼Ûol÷3Q}@åW9yÁ]u¼Ìeå²®Ô]/¨{6ÔL\ù†º„âë%w'¾ä.`8JQïün¹Kô^Ô5w=c|/èž;£ñçxÑ]_oäÝt÷d®L.€ž=?aÑ•vµ4¼Ó.·ô#\jç‡sÌSåíʹ¤‚k—|H×®êzµÝ ÷k4R™>žÙÇÙdCúÙªà 0½ÐãqÍ¡Täp“Óùx?‡ßãÕr:»ßoH4cºZ'Ù:C+m9že[îòÕ{ËìÃV)Š -­h€1‘àþ\QbË2† ûõp²_ÏAÐ͆$ Ù ’ÕoÏIÆš¸¥@mz3#²²ääQÌL à -­Õ©^rCê¹–8›Çú’d:šÍa$Ù.eëBÎÝ•"çÌà<ø¬LØb€÷8Ì2db=k62[øp„¦áC -ˆ·‘s÷isÍÜÛô=jì-áÅ­ãõfµÎ6»GÂE‚ˆJ¼DÒñNÉœN&¨oÛ-dÚd“")æÉ»[ Y˜*\PL¢QŒß)Mf[Àµ!þ²Ec°{.fÛ-8ƒd„-?zB"Ð ª 5Ö ¨ w¨rˆ¡QŒ -¡M\¦-Ÿƒï÷”Ë o¶»G”U%‘òËôjÆ‚¯ 4Q`…€eÆ×$†¥<6—0€O;•âfôAªAqj 0i\/Þ^Ïçhélͨ1 'XÛÖR-3‹Išå¨ç÷¼^7IÖƒüÁéò"ýÈAÁV§ä? ɹ)ÞO_Ñ—(¿ô²!EmVH*ÞÜ®S´T6«ÕΖ»Ïxâ¦øˆœ³eø°÷~µy”ôñøƒì}KHGº…Š¾áÐÙåøÀÁ‘pF†x`+LòqÐøBæu‡%<ø™­[z€€6‚;Ú`Ÿ¶x‹ö„[¾¶Æïð›è+)ä"zŽ±Lzóû~6~µã— Í–Ì€ßtI¶ñfE­GD.4‹ã‡Ù2rûæþWôP - ‘²ÿm¼ß€¯õ_ðKŸŽjº#EBL·ë‡5~ MÄ¡‰€®t¿[¡_ƒ´ŒSFd ¶zg¤y=¡aÜ -¿KH²âΣaÐ%¯6ÛííÇž,Å”“5Æ9 JÚ·ˆ:öhÁlßmo ¡Ú"Pù‘çEEýÓ!ú•D˜¡o!¦<ø`‚ƒ_>&4øåaƒaébº‚_ &(øZ‚ñ Ù$„xàŸ˜ ü ½ÀÏ€ -dH B¨âú@¿|BØF O;t‡Ì7ú)ÆŠ<…è—OfÇ?Âó…§OMBqº>kNìó|^(îP²^†Ž0¦#&tÐÂ.Ç°G9ì³qÇ¥·EK¸Ûæ`2°T_ì º{n(¤ï“!0¢ rÈqn†aöLuzlݪ Ç)j2Hç íœ);x™X~ )É>—§…e ÖK4-ãÒJy3c´·é eï3œ–ìJÃûD‹¥§Ñ‚!vJìû&[Ï9Ô†¾ø²Ì>0 b‹#:à(_B& ä´$‚+9(û‚GÜ\ó Ã-pïVÕ^aè–ºŽw•†”™H•vƒú…¹ ‡uøJøÎ-ݱ|Ün9ÈC·ùWe÷K|Õ T!Á{ÔSÜ«|š–ˆŽ´ÁXÝs^fWô;Žy&}öégàw·é?‘l€fø~“‘–3öw»›­·Ãt>çŒ -ég 0ë”AÞÂ>bž"éÏÜ$£cH&[ƒ -†45ô)*Èß©&~(‰X7xj:¬ƒ"±‹P¾@<_´Ï!»_Š XZð å+äL±µtºÚä„lp¹ðq+o Ã.]Iâ39’à²VØ£)Ävø†À¸^Ûi¤>"fAd[6ÖëPyOGEQ ¦yÈæk#Mh)+I¤4‘¥=Mü•"êb®mÑÖ~O¨ED½ÛÈóñë®þ:į{úëè†ðg:ä5“öbì2ò÷²ÐG©A؆}ìSÙ¦†%MDã€ý@ -ÙšNV–óUŠBŒ—4—[oÑk´'ÔSqïߦ¨uD¦dö¾ÿ†Ð1#o²¼Ð@ò®kGãEV7~@ßú”yÒoXdÅ+øöaGÄÅÄs&ùç– ^â«™Œè¶é†ÈK¤èGJ:ŸO´o7ÓÝê]F*Ðø²]K棉Ƙդ:cNh¥Tb¾ÝîG= -ÏeҥȆ¹Î&»GðCxJÒûJ‚_ÅjO¶A}2üø5±êFŒÝS^lìúlG@K µ.câ5š‡Þ-tC:âÛXôˆ$ÑWÂÚ‚¶K|dË‹0Q8 ŸËPÕMä̈-e;©a]¹½ø#~Ý“ÛKòp†àÁ-¦dL4Ó ñT¼r{ž=üCS`ˆ¢{m*¥rw*©¬vï{0Ư#Ú™“(BH/¦Ø%§Ð©—XJQè²×US°YêéYR¨eôÕ–È3ÉÒô½¼¥"UØPÞ—ðsø.3¯¥B†ä¶·_/¾ˆÿ#|ñí.GóÿóÛ_ß|ükðÍ«^ÿõßÞÏ~ùmýÍÛï~ÿöÿóÛÿœÜÿ­ûÏßÿÙÛ÷ñ߉{ãùæý÷Á›ÙC’<~ÝTy$·D¤C*8„m‡ÿÜßgÐûmÐöÈ2LhÅ­f½Q?i©‡‹Õd?ÏK²l¾Â˜˜~(M¹z+Ûb»*˜³ñj“½$¥l_’ï/áû–¿Ô2êÏ·³åtuû¸˜Ó£uìÑ¼Þ ؉8>Ý)ò:û‰V'éˆ^§³ŒœOJKpC¸ép¬UJ>Ñ?J>ŸgŽöów¼ÝIÏ^i·žÃx¡Öáó:xñ%‡…g’«…#4HïÑNã>Åš7r¡6–~ª…Är!‚`ŒA%i-U3ëÏ*ÑøFeCª®BôâÕ¬’akö6hª[÷â°ÏˆšQV*êÓzøœ¥ke›óÚ âÕÏC"án‘̪›’D{T -„r)±4ïk… ÷ðŸAo£t;ƒ÷`¥7ñYúi)DM>8¥†_ä‘~³;êAŸ–QV*BKc”MEûÑ ðb2|’™}\¯¶hÄɾ~Këb™øfPî4€ðØ&¢X€ÀþyÉ“ˆ_ê - p1–F0:,hªýµÑÿÙýp=£Ö»íÐü‡ÚÂHdGÛq¬(‘ñ±¯Ï/N›1GÎ*±„R+8©èË´¨jµ>£qCö jÙð…ük¶LÖ:bb0ÆXN¡>©¥õ´Òxg{ÝÜ"µEX^™Ól$‘Ð>¿GEÕSÌw}0˜0=©ž§câ¡‹ Òwù· ]ø›¼ô-“jk¼4f&1&rÁbŒºÖV:‹WÆÄ10+«¡HqÀü:‘É2zq¼Ù/F‚†ŒEhí³äµ¾4ÐÒð‘Ö…WM¢x;ƒ`_¤Q.Û yŒÕg“LP×Þ­WÌùÆ þYúiâ8ÿ4$FMj ·–áxmtƒØ`TcÔ"ôÓ˜‡ñx\QkõgQÕ)‘Ž FÅ>ò³¼‘±.ó2´fÊu¦€¶}´E:aà/ä_s2à­zHV­<‹ôS)X6 - Ž—Z¡øûk <³EÉëÝ#1Dj¶¦·Ñ^„óƒ:0hcžs+V*3+è©ÜèéøY\ Eó•A¶bCx¸¶+…¡÷ü‡:#]‘sHÌeÛƒF‘OJl)ÌÒ`{ yß̵ÃÒŽÓÍŽZŒ›u ØØHÅÓZ Ü5„*ãwX7Kƒ»Pšð¥‘ÕØXñ« >a$nÎ’qª—j&ƒ§óÏëô‘-1g©4ÝK=£}ÝI ¼ž‚ÎáhQ ,½QûàŸõfFè2w|pª—j¦œñÙ lããCÒ½Ô3º[ '‹Å­Å©^ª™ì0Ÿw a&FœÎQš—r÷êà¨Õ-¿2ÕµhÊÞžT¾ÆeµÊV£ðYËKCʆD•U]R&ù·Ú£P)«2†pØH–ª¡:*ªH.ÀõÞBTKÄÓ彪!::ê•óiº*“p[U™äý£*rxÆ¡P)Çótû0äÖ•´Í¾gˆ0¤\Òè2Å”J¤6г5Poš¡1.hYA›Ü­ñykdëÝñP•wûeÊU@Ñw‹AÒ¿Ç–9N -³¶Aä±¼rÕ4ƒ“é]µš¤<–W®)gÁ ±«M¹#Ág ÓT’OÁHŸÃ¢¾ùÈkÏéü`/šp—ÝSç ç&Ú^µšÑõÞEç+p=µø,ý4µº°{ú}Ÿís´ºvS3êÏúÑ -@(· cYÄ/cëÖ‚[6i<#~Kÿ˜è„_ù1_Ü5rª$©ò`r$é#óÂ䜔«@ë½½D×{W79½w“¡ôàê&ñ¼ÕÖCq7IÖnê%ºÞ›¸LÒ}˜ý+݈1ïÆF[¬ÕJÙ,¯ ‹Ò­´TJi1”lê“®EE X[?ØGþÃÐw°à \ù€§]Çh5‰öhë1ùìxy£Œ>‹Œê“~¶2a¿ ËÙ -þBþ54‘ø­FƒÆé+)@k™–Ñxa´íÌÉ -ø%ù×Ðzã·ÃÉ~±Î6ÊÀ©™µfé™Ì7ŽŠ¨¾¢ZER&óIW8Å}¶¤v÷êÉ€4<öhœ”ªŸeex¿[P²­;zAŽ×ŽÄnì²U¡-·@Jf¾1Ø3I!ïâŠgEšë.n2Û®çéãð}º™¥²eH)–mËm}©ŠC0L›ý:i$‹9 €NHJI'ˆ¾¯ïVí-)S^¹TG˜<.ÓÅlŒý"ˆöÎ*©›É,¯ h&:},5Qpâzo(ˆ²t3ep¬cQ6 Dhƒ¹qñ<”TôÝXÕ$½MŒïétä—t®/f{~Çk]”Ìt>@üm&ÜãP,U}"­æ.cûHbJ]aËMFÚ½}˜­ÅÒŽçÌ•M—\ŠË.‘Ä0ñeY6ûÉðA¶âé•£#[vû[ƒ‘ë=ÇS`L –ÈxaXº»” n%†ÞýÉ5‚"i­T³ÛßÖT’Ý^)HÎ)$ìôDÕ“öJ Êf^Ë+µû±¨‘FÒÕº¬¤s4À(ÊýÅDU+§”Å1— &ÜÈø#0Þ"LœaÿÔ²'ªŽ\ï IN—}D©ðjªBa"«ùƵªp -ŒÄuO•V•šÝþÖEÈ8ZötR‰¥¼–WÊÁ:¬Ñ10 -’›ÞlVàÉ»y?“!¨\£¼–W†˜K’pj/%ˆŠ<ÒO•‹Âºþˆæf&.H¤ÇT–óHS7j¯³¸´2i Ý¥- Ké¹\%8?èT¬²n ñò¯A*46“N¯u9™¡¶ØÌjyePŠª3¬!ÝIX·ÁâÓPØbtuõl~ù4§ùÆW¤nÅCAe„­ê/ qš&x˜m –ÃFâ*†+@N…ZvÇk]Eão̬š(ö‘ÿ0Gìƒ[qÄË°5šfTŸt³x®Êbð?–Ƀ˜ê*584ÎNZ¥§7^èznüï$Ì>«%‹"MÂŽ¥ÂrLߥ"åW*Í"›å˲o"Ÿèƒ_Ñ.²ŠÃ–›÷—%–[`‰£pâ궵lšÇòʘ©ÕfQñD‚g¿ ,^mö ;Ãò¯I–ð¶SpF‹”ŒÆ •«ÞÝÜW ÙV¢WðŸžò!•Î'¥f ÷ðŸ>œÜá g·zÂñ_úBë=ëB†øC#‰Ã–¬åcmC3«Ã¥æÒÍÍÅfÝðfq•. -6Ê”ãçYÎóé7ö×@ñ.Û,%­b¹£:-£þ¬“0/d%aü…ük0aƒIƒVƒ “Ôæ9Í7†,ART“:E駱ŧœ¥èõÔÍ–slCw$l„jöl¦°¼26‰f!‘vs ×zd/ÇõÞÕ?œËù[«&ÖLfy¥2- -6âF%8:Xp!Á¢rœ-¦óùêøQ?¤›t ¡†É.µ…lTO³Ü: ½ËY€kbùñËÈÐüÁ—Öî+ÙÔ'ÅßQß¹Ð8‚/ø]È”-Ñ !“œYÌ€/±ÌzÑ04lUy™¤—¹ä5„už:›g Å"Ø0uµBÉéxmL,OæDCWuj-¶)…pVVÆ ð?ÆŽµGÏÝ”€RmËm}ipGœ¨@VÆ­¶T(¶ö¬ËÊäÔÂ*+Ó òÇ•Ék÷žÃz"e’BÒ·!^q«5ö Ú ÊI·$(¿q TT£­¤¢ï†þNNÏÎo2«þ®°9<»ý­!à0¸x:ÇÂ+?Ö#•ùÆn#ÅÜá@«d¸u43+¢]Í/¬è»Î#pòj»žEüÒÅVüê¬#ˆ¶ñô¯‘uvÏl̬äûk8ÈÐ÷Ãñø¬_¢—nH§.,'9BÖ;\¢ØR‰Œ]‰Z-&89µ–©&+Ÿé˜D¬§2ß6,…æ½ÒÓe~6Gö!”ýX,ï ”æi„½G"¹·±Ïh¬¥:¨I‡ölhbµïÃtò²M˜Z³L%<“óƒa*êJw@ì×ÿ“¶j'…|6PXOÎ[Ö+9,F…öf˜µcY§Â7gÍfËF’^æÓ£¬Â†ØÆ2€p÷a3Ûå¥@E-ÇñÚ°Ö”Ë^AÁÄÀƒs¬7Ù:ÝdˆC|½©¶°õ"œŒ 4K¸ý=ÇW+¿ò‡ÙýÃðCºÓ±˜iÈÀ,7Ž"sü¨MªüdH¯tŸ¸ >lEéÕ–ÛúR­—›†ñëc°hƒ/×£ iºWå5ÀZLîGÄ%/1Ú¨ÎÈ“§ë­6‹ÔT"‰Ú~Þ‹»ù³ëvãOóû˜«Œª»¬â•Û´Ø¾ 8…‹ i”LóJ«FÖbr?ºVæ&û}?Ûd5W¦’ÛúÒظåU'×bŽy/¾XPWeçõe³%«íÉi`ÝÐ8¾)†ŠQþ¨íºû¾£@­ýö\ïu͉™oÑLÀüÁ˜$c]·gW[ªç3^"¡žƒÿp´æøR0‹±¨To~î‚φ|c$ÇÁy¬[ð}'¹¯ Ë,#™¬ï3Œ#ÊTÏUYÎ/ú†'ä«W_X®:Å<[eþE68(KJR>ã…"Aöbë2ó§*YmïŒ=šHãÖ¤åVG²ölì•WÓé8]¾O¥Å¨äj¿Ûgp­.5¯ö¨k V¸›[«‚~c ÓJúžq&#ü…Ž>¬<ÒÜœÜyß Ìfi9—«V©Ç,¸§,Ͷ¾UpOçÚ|eìMÐ\ŽVûåÁªUâNëºT—²ÌUˆóƒqp(H -3£§‚âÄO£ÕµÀ(D2øw¹(…¨Gt‰N£†ÿ€ùÁuG«©jŸ'òH? hBÛÀtæ®g‘ª0N;U™mït¶WîYÙ>|Àÿèø/éãÝ/Ù6šEü2–äúa½_Îrb±lgäF­î.çTÌ©›§÷ kÜeɃH|‘~¢«H®œè*ÇŽsÅŠÃä+¾aeËrB4måäq[nëK}:¥«ÉU³J]ü«øeðþÅ-ˆbÔV«Yuƒ™ÍdŠG×d¡÷ðŸá¡€ÞaôŸÏÆر ‡·ëtœ‘h:&B1¤9îŒ9ŸŒå IñP«õvõ1UëÕrØÞ¤Bü‡†ä>¥Ê[7[nëK㜆&ÂaVsøÍnÌÛØR‹¢ ¤¢ïߥ[N|ªë»·}Ž¶èy-¯rk Ô˜5vyƒÈÉh/7äE†_žÈxa(&ôT„˳ëLŒ:ôÞ¹ Ìý¨ó¦ Tƒ7mȈ™fðÎB“wð â—!¾ó/9â{^ÑT¤Óž¦¯F«Ýv÷‘ôX:ßàÄ/ƒ1‘kIÝr¿ -E¦!¹ßŒå¤·úY=»ÏÌrVO>Ñ?ß%¯‡éz¦ó]ñEúih£Å§ád„Z‹0_¡ôꓱW¾'Ù4ÝÏ©ÿO\·^ŒãµAbR2N½öÚÉjéõg¬´ït»~ù*´>ÒW‡Ð“°ƒ,Éb@¶˜+¬UË_ôÝ Ìô»¸)§W­),kÎ'ã¤PO -n›BªÔsÙßÖ—W¯粿-¬QÀd• JZßz0) h¯ŠvΪeݪyÝ_ m-M‰£À’;°Rfòoz hT±×Q€ë½!ÒtÙb”M&Ù„Ûºš`NíJnëKÃ|‚%‚îÉí'¦·b^¥<«ùÆÕMPEŽeµc¥n*¹­/]x©M­)ÜåÔj™Uׄ'ùÁbùGßõ¨n¶Ê“¥ý6×]ÃÍæ¹kqÕ-ðÑ%@<ábçÙDV^”E¬Ùíoƒ?zq<"£*’ªoh€.±-)wðWXVq -C±±Õ.÷1îVËm‰R©Q~OÜ(‹‡Ã˜`ú‘ÿ0E3®U±jÞ$¥‹øiŠ/ü“ 5£—.õ–Y6ú»K—“tƒU#›TD!øRÀ—ì+ÿav¢ow³ñÖÞaþYúi’;ÿ¤q<ýEyZ·mEØßrøã–x2äpü‰þ±äC„æÊ4HïYÔUÍ4` ÷ÜeBu^Î%×U‚óƒêCÃï:ΖR¸¨wÈŽ6­­ó£R*‘ê…×È¢"W·D—z•ÃŒ2å•K¥`o+=ˆ/˜€ÚM/*¾V&uú¥:ÆûT¡õ¢˦s­ÆÚ†hÛûMUyW Φ€A’æVÓ~™y-¯ ך!ý?³±¤•4Uún/'ÿ«¡v¡©9g/'ëˆLòoÏÉ;ƒ¯ó-‹u‡ò$¿‚YUV¢ ¥yJFõÉØ)0·»ýÈMˆEÕ©E¸ÞJw)̇ Bqõœ[Þéʺ]6ÏÖø¢yË¡ ÿ*~¤£)Y ]¥æb$«P]S8‹ÁßT/ÞR«Bͧ=êzYu­zYø€ÿ1$ÄÝC¶È´†•âÌZFýÙØ ’ïp£½¼ñ)ŃŒ¬æC{HRl÷÷÷è«bR`ÄgË©SÏïxmȲ$‡Ÿ -*Õb/yõ.[V-™ç‘~ê¶#`%Ò®l3DkëŨòemÎ;ÚB¥ð¡‡G»JOH6õ)· -¿^¾ú”[EP¯Š@}Ê­"¬WE¨>0'…-'µç.s–̶wÆZNÃ"J<Ð;¡Ëm¡]%8?¢£œpØ€XœåDG{~Çk׊ÆÉH,ÐÊ+ZÊky•;Ñf»‡a÷c½‰¦™mïŒýÐ~3'.÷Cj>íQ—$@D´Jiðÿc°,U¹NàìZ»´|Æ Ãu'#icµ®ÖৄÍB%¡8qUì,¦à³9-\1Ò5€ÅÕ5G}4˜*þŒÈÝsïªDdÓŸíÕ¨Rnéj$ùV{Ö…[^¶BŠd·xti.ã:]”·Ý"bä4ß8jÃ}ȉé®MÊi¾1Æ]J€àºìc㬠òéÏÆ´ôh-ݱÃàŠ•ñÌÖ—ZJ‰dcUP+W#YÞéG’Ä ’}ä? Y}p¯6^†­¹,@¥òdˆ…²=ëÓI{7IJ ÿÖ%áð…a$+‚¼¥ ÈÇÅ‚¿/RZOÚeŠ/ÒOc}ˆO)q[‚bhZóÁÒ¥Ùò~¶$æDz™½šØòÊPøšI$.R4 ¼"uúeºÞKmúôÙ—þâ‹?¿ø ¡µý<ÝlÒÇÏÿÜé|&nÀý¬ó?ÿÒù ŽU3”}‚}}I;×›Ù{#Þe$.&ÁLù_áÏÛåwÿýë?úÁü÷ÇaúCüõf¢?¯7ÿØýã‡×o§»~ÿ?þÙKÿ¾ð⟌âç?¼úú·¿þ×·ß÷&³ÿü÷~ÿû/Û½ß"¶Òd¼Ã»¸Ò[|“"ä`ƒ›-Ä Ü|õ -“ÁÍ·8ÈÂ`ð --ÉÁà;¦ÞÜI/¾û#zýd›Á Øå …ã€àÅ{‚@Ûð‹0@oðrljÀ‚UOþåsƳ¢äY}ŸµöVTÐ…wûÔ1 ê6Z?-z@–òàfµ™!òaŒ´ƒQÜoÑãìΧߡ-èE -èNûÈ[}|à Ïé>ƒÁ \:Õï >ìþ(z5ÉÈ&.æ\!zûö!ëP[ÐN:YÌ–3‰HqÄ:d¾:½Î‡t‹Rog÷ËlÒA·3žgé²ý¶_vˆ½Dß_†Ó夳M—Û`µ3E%-wݪ“-Öévö/ÜàŽÕ€“b‹¾Nºë@,€[>?HØí€"@y8"Ÿòí…&*­Â5I¾å3¼NÇï+âÃýŠM|¤§ |ø{·Á­gÎsˆ?} èàf>mÒÍ,ÛâYöïþ˜Ýy„™S*{y?_Òù‹íîv‡(Ù'Œ RÖ,4./© fNC WÕlŒÊÙ¥#^iÎx+½èã|‹õj‰¤'ñ:‚^̶ã—JA·$ïµùÓ§OX\¦ÕþÛÝîg9uÉTJ_EðQe†0u~²Úˆ’ØZJ&¿õêߨþv2Kç«ûê=Ž’’-!#òö’7΋ 6tzx’OxË%O.ñ…SKJ†No¤ÕF#P<Á ¹ør¤AÊòû¼,=UþlM!½•Ó}‚Æà†ŸH$.7¡ÇËÐñŽYð1Û>dhÒ´–ôÈ´¿ä3-ùsѹûD29A#ùû0à0·8Ûpäü«xÄȹÞp«nñò—MöBy‰axƒ²Ž7ûÅH¼ûF{™!Îý·Ë&âå_µ—nÙ|ÍþʺxfDÝ] Wâ™pD8—\­ù‹_Ћ{AúIF«’à¤~A2ù%$8ËÂÁÐt¶ÙîÄëïá±C?JTCyø0›L0KÑÂd3n+°D­Ù³»ÀÞÒOdšˆ(&Øã‡Ù½`êb¶Š»1«Æiš¾Ÿ1’ >ŒVÏJT©°ƒ;Þ¯gc( v#:áÑW| J)ÞÿCË‹òÞO”2?θó°ÚåŠ-<ÕízyÏÙÌúa͹Q|ßöùÓnc$ý‹ºa?Œƒ¤Ï¤ÙI]CŠÈ‹ŠZ}XÒ…&Zã¸ýnGÿÜJó‘U3}4§O(Ë2zÄÍ@òÏ'2sô i]ÀV(oÃoYTR›Î¥­Ñ<ËÉÀ@_áëvµ!¤ø"è±f’»NÆ—:#òsg™l³I™Iw!ˆ;ú£ªÕ¡P4Ó^žèQNÒÂì„€#Ö§»}:Wº‚ß¼€Ø=%C§dˆå¦á¢n©é(§åÄHâLýIª€s­Y™€ÍMòêÐ{fq°{Øjé"?·P3 ê¤h¨©A^uè Ì‘¼e–ƒ¼sÝü‘P’Êw(L±±Y­G{´-«Á™ðØb¥“(Eú)š)¦WìNKÚxTݘ2Ò¨N[½ ,Ñ;ïéØji®F’8¿¾‚xkhUf! -ñKÚhƒØsMþį‹sð'ó^9“?%TºMšçñ}“êñêP—5JßÌddhàtT4ŽEëðnOTÈ‹Íé*_m‰H“J,ïw+x„‘{î$`Ï­åãpK=%²‡–j±¼ a@×F#Ý•åd -Ì*`ۗΖÙæ¹ÑÈÓwVT”UÚ¾‰<ó,ÝLgj|w5Ž,’n„§d¨Es“ÆM›lR)sÖ„3³8û­Z- ¾Á‡ó¹È¦<|»2ÝD+AM8›85) ÷D#hí²%ÐeŦ¨”r+d"¼Ú 3©!¼LfÓiu‘ÊW×Ç-”bê×ÔÆHi„TËãžÕüÆþ…·ˆj‰õ…à©ßíé;_+۱ы֒uµR¬2|ì(Ë%Á{æàaÕEÙkÇǧ*ÂäܶŠ”©Ì5°«AñØ‹ßµC~þ–:, êõG©:ûÕÁ'¶Æä"\›WÕYØL*t:Øó‰5n›«=-'ìGç'áiçÐdè i¤É˜š ÑS3hm¦úŠ“%w›.‡êMrA4’ –";‘‘¬—l}ÉŘnVe ÷"Í]b¥ð’û,9´º¦s“2LvÀìÙ wè+\U8𓧒Î yÇ,ÓHýé³/s¨éö¹>îËFô‡l*ÛŸÒã –x›¡FP[(äW0®U’ÒCÖ›Ù"Ý<) o!o;â-nnšÞ¿aïEz| µZí¤š¿m·j$\ÊøùÓÛær³|ÍD±Šq®iÖIÌ^u£Ýžßóz×eäa1§Ø°6Ó¾}âŽnÑ‹@‰±ÌÑìMÄšÝê®ù„Ü9 s)ïÀæ|ÔŸgé|ün¶• -€TP•¼¥ìõ av³we»éÓåón½š-wRØ”*ÝÃ6W5Ƙ6¶v‚n>Ôœ&Ó`ªFA–åÀ³ì"˜²c¥b9æ5h-•¹¯g&‹¯lvŸe¯`N§ò`ž’kø€Ðsy B{ÏWô† á‡‡Ùøa8ÛBä0üºì\$jñ¹È…eKé:KžO%ú깊afÇ$î‘fá²r¸"i[²ô¨W®tFØq¬dÙ¡6K8.Õv‡§‰J¥ŠêU‰‚"¯DÛý¨Ò†þÊñPà©RžV@Å`‡ˆaQ©jl/Å{xÈÆïF«Y f#SiQß oéâô6Ÿ"S(-Ƕ»Trg)âÑtOöÍìþô­ß$/ãRÜ™ò¿!Á:E­éü¿:Ÿý¸BÓóÙ_ÈGc¦_¾/F½yì’~þ†Ös»x%ýò -¾5æóHz~ñ–gÂ^È$ýžz'ãlI¶#žõb‹ø&•Ô^)¥½©;¸Ú·¢­<”*çÞð¤³,EG›8'¥MÂu’ÜØÑš¦"Ž)²IW¥'³zQ‹¾ç³C7g)½…ÇÒ—x $ÿ“­Ò%þoß#ü‹˜°{I_ ø¹R=ÎJ_"ÜŸüÜ;¦Ã—r1ƒ¥i¤ÂxšŽ”¦˜ÅÒD¶‚^H‰êsYJËÖ -$Ç ú¬¶t%ù-Ý -¾E_;ìk‡|íp$©Êé¡¢³ÐŽš¶ -;gtå,ZƒG¦ª¨ßðg’S‹‘ÇéW9·òÕÁ{é‡ßЇÎ[­±Å,—&ú$"uŠD:®[¸.ý"eWÝùN<~£>º\9UN­†ë0Ý<ã;æØùœ Ö¼H»6쓾¬:%ö#ìŠÙcòCmWLR?ýSÆ“¦,犩}mWÌ®UN’¦òñSzèëÎtž}„û¾DËKx–%è_¤ËGÊ¿Hô‘´#nžü²³XоÀŠÍ±x@’˜ËMÏɇ$)Z‰IÂ_T‘ƒCô¿–ä`ì‹üÉ•ƒ*yµ¹¨-óö¬Ä)mPª†ñ»1–h¥¸#$~Œ'µ,0É«7o°:k‹ö_)\ÐzÛù!K7ËÎÃêøC8Ú!íè¤(…\à ‡éëü[Úy@(ñ?‘À²Û­·w/_~øðEK[mîɨ¿¸ß#Vÿ²7¸ù èŠ"P ý;|ú·—é_ŽòÄ\IlB%Ôk‚‚2'¥%¤óÙ¿d5±5Ž “k´dÖI¿–óÒ¦Ù»"»’†Ùâ(…(‘ö¤X^z¼"?^³éô+ßdHµ2ëj-s,2K)ŠìK\;= ;¯&(W”K9é¸P‘S‘¢Ž*rò=¡†,Ö’Q•êÙYÈE”·P*®}¯”Rÿ _.¦ýƒ|¹ô¶òÇš \t2«ˆ­ÆžÄ7„õ[ŒÈ±Åè7Ýb씳ö1Üõ€ìdùg¹§Ö-¨IÕÚԾɤ„ÏÉ’qm2ˆ×u¶ÒºûtÓ^x||!¼Ñ?·Â?¶ä†=ùpœ´ËCúÊ A”;ZòÚÞ©×ñ° Zm}¼,6Ë”^uQº ¹e•H¢^fæµIýàL=n2°‚xŸ±W¿*¤ZSB«¤­0¼J›o‰¦Z[WMJ(³|L—C$J´××ïås6ÌZDÎ'ûUÁfóÉð½Â£[zTx6íQ¿¶­Ò ¾T-dwÁÐRðò¯qõÅ* -/Ký–NmŸ%·íq¿x®I!ÐIàSR»òŽ^ÆH”WpþWãÚ0Ýf “Œ1.U›e´Ä2Bˆ4¬"žc`xJmnl%Øß]×Ǭ]'q0Õ®‹Œ|§e¼0î½qÈg¸óú-Gô+ÒGF×{ƒ*síÔUšc`„ÕT&!·Èü¯Æ=Š.‹7;”ñÄjƒ\…8?Ø¡ŒÜTƒ2žM{4¯ú–¹»RYO¿ã¬P`Ð*5^Û¹†‘ ¬„ªq k9ŸÌûÕå¤P'íÊ@xþƼYNAÔ$õ$4’×öθbŒ`1–I±„Zzl©w’ôÛ¼m˜šv1û-© 麂7ø%¥Wš½Œ¼oêL{Ž¶äî¹ÉDW£µ²e×È¢îmz¥z¤lñÉBé N…’+gPû¢ÎN®‰,Ù¤Uœ“ÜK'4.Ó´Y¸Ze{åzoÚ<[fëËœ;ZÝ‚tG+«OÍ¥?K7Ç /]ý -sùêNZeNyß >£[äâë× ç×oTj©)MpšÒ«Åàef ¡_Hç„ßUh[AEßÕ†u‹ $£WDmwqåR[7«a:^xúÀ-Ù†ºO«Ð«Ù!8Çp­Öˆ8ñI«Ïöä -l»E4q8 -­‹ÍBÊ × Óœj’qº\-!z=ÛÌR»¹V”WŽÆîÅc߈æÆÌèIëT“¨ÍöQ§0JYÙ}Þ·Æ5qàJ0V4Ý JáÕí4Ë&´C>Ë`ù¨f’FÁ̤‘:®Rmô¶ð[{‚ -ÔLæ`‹ˆv‘ê„FˆÑNµÏBÒ=Ïó*s^]x6-—#êAµ„Un.¬†ÍªãzÀÃŽÓ׸Ð)º -lÏ☙ÀóÚš¢¹¤ca€ŽÃ~7í-F^eúÊš-Ðì,K Ö#YBöU/–¸´¨ñOÞ¾rÈ!#ª´oËvã‡á4ÍÁÑËŽŸ¾Rê"äŽ5ý}ß ÖMÏ£Ö›Õ?Qâ!zHõÜH†óÄT€Ó'VžBs6Scsø¯™¸ójC08È⬤+¶agÏ!4i»ñáXv/ ‚°‡–µí‡QAÂÕ‚¸y_}²¿&®3³åx¾ŸP?j)­VµÛ¹†~`Í1ú†?awLE­,\'_í·£CJÌœ ‰RXu.”Þa§YªÓå/^ýÇwâqþ›KO¯øSW8òçWÒsÂÝs„7ðÇt‰&Xu,MǪc){öé]ìT )æò×ù^õM:ÂT‰üÅ·ò è »Ó˜–„¾§Øßö‡ÕýýŒ:'’› ežpÂy½$îoI¢võ|ÅaÇ1¢4ôßÇ]Gf >üé{þÔ»wóøsç·×|qP§dòðýLrlá—ïRŸXñèöt…~Q þ«ô -Īþôz!/UPFð‡ØöE5”â¥ãQ -i*y&Ú}xÆI¤ÞÓKOÉÃOìRÒ>þYzÆ$¥M)ŽýȧT›ÊèŽÄ]à¿°å¦MQøÂ+<Ñø¬a´±å¿ýö{á˃÷£ÂI<⛋Ä“äÅùÎR‘_MÇûÍl÷Ø!¤8ô—"á0—„C' ‡‡'áð$¶OÂa wûaDaßIÂI/œLÆaèu»£‘?íŽÇÝ~œx݉ïG~ey$ìý¤ç”„IU•9%“° ¯m‹ça’´»ÅcÓaì3ù6®i×†× -™ þ¿‡½”-˜d©»²¤ØÆŽfÅ\aÑ&L–e! 6ª“'}3gÙˉ=›´“Ó_b³?¶SvqÚ&Îݹ˜š”Ñßß°ß`ï«lÞèU¶n”ò¥{óò,é¦>²-­oØèïWì76aÄ›3úôJ<%Ì]ÀZ̺Mã¥àM/…?AKÅÍŽ¾=£Mf›3úø­ôˆZ7f¬}[†ßCƦ 75*gKF»+†—¤ímÞpÑß߽߳;¾£lFIhþüžþLîèŒ>|ÏP"Ø|ÑŸ¥?QëéÆ‹>ýU<¡¶àMýýz!@1ýùý ¶…Æf‹}0¶Z´6ºÑ¢Ot›E †Mýùý‰ÒÐ }úY<9¨S~i–­-6Vôç/ô'JÏ7U¬H±¥",6TôÚNÑQ&›)úð†? c)úøFzL˜­(ËÇzÂD’>¾•±åÇýù–þ3w²Q¢OoÅä@û$–ƒþL˜µ9Ãu»DSÃf‰þüþ¤Vš[úûoìwïŽo’è#Û"±’²A¢¥2×Dhº9"{£OŸªÈ:|j˜¾Ogs8Ý2qÃ0¤Â`oSHü’Çü}‰?3=ÌSSò½™²u¥@Ñéz¦lŸä|~W•Mí‚æûûõµ†%ÙÚ„CªÙ·bݸڄÀ&[FYàÙÞÁÚ÷ˆI÷ºI¼nÏe“¨nÅ®{½ë^ïÄ{=A/AY‚ r 2p¤…œÚ&Èà´OA!Aö|/‰£ÀMá$é÷Ñ.³›¤IßKzÙt%é(òâ>"Ô( ûž×ú%È\hôËR¢ŸK‰¾“ýÃS¢ -JôÛ§D¿$[çAc:‰Ó‘ßOúÝ,ó¦ÝI·‡rDã,M»“É4Ió(±×õ½8:%ze)ÑË¥DÏI‰Þá)Ñ;%zíS¢WH‰q’xI%Æow'Át’„ao’xiœ…¾ŸŽÇ~¯7Šr1±—tá‚%ÒŒé§ìCG -³Œi´ÏHèÅfLywlÒi¢Ñ)MlÒª^œJ¯æ×#Ь’ û¸Û¤¼]¬uÉ:©IÖj÷MÒNüZ¤ Å’wõ¢0î9É;K²î¤?%I:éio2é†^6õ²¨v»²½†hà îž+yûUÈÛ.èŹÉûÂA òn&?4 ï\¢>yËaЋ½ž½Çh[5§Þ$O»Q0íw»}$¦v§“8I§aî«Gý8<'òÆ“Áe»4tRxO§p–ܤqK™*™[œŽÒ±E!oG]ZïÕ¥um,ÔÖ£v\p!½èHfqÒû(ë÷34F;6/îuGñxùQÚOG}´Xâ$—ÞÑ18ˆÜܽ»+½ÛEK™¹ô~jÁ…Ñ{3Ñ¥½ç / è½X|ñÑ^®—#÷»axãþÈKºá8˺A4ʦY¿›H¡b—‹Þƒ$ -ÏßÝŒ•Þí2Œ¥Ì\z?µ$Ãè½™,ÓˆÞó¥™ô^,ÏxA˜» ãi6é‡ÝÞ¸ ›ÑÑ4 -¼°ßŸÆHŒÐ:È£÷nì‡ÉYíFLyþ­ïV™„2¥Ó”&‘+©ä­}jBØ–¥!úè7S›„uˆVí™EoÒ«N¯Pf‰e·×Ï!Õq"pöÓnêuãé´ï…ñÈ÷ãiù]/ÍUœ$±E!Õ -§>¾±©„&ϧW;Ù5yì«©Éc_F“ ßˆ$kiò”~µ£ÉCE–Ø v“ÐM²îØóül<šÄ㠛Ž°;îw³È›¦ã|Y!‰z²ƒ_ÿ¶W–{¹”ØsR¢ÐZ¦ÄÞ)(±×>%öÊpqpYuR"á(ô{qßKƒ`L¦ÝÔï§]o2õ’I® BFAp©µ%vËRb7—»NJìž»§ Änû”Ø-¢Ä¤×‹ã<õ¯ßÏú±×íg±7™„c¿Á¨ïgSw½0W_x~’'gÒIY‚Lr 2qdrx‚LNAIû™dqŽÔ8 §“I0íIÒ{ã`ÜM§cQ$ÚídÉÄÏ#ȸ÷z'3Aðoã²”çRbì¤Äø𔟂ãö)1.¤Än¯åmµ‡öÒ°ëûŠã8Œú/c‘pŽò)1‰ÂŠ‹%-Vý\‹Ußi±ê·`±ZH‰'°XõÛ·Xõ‹-V°ËÊSröÆ^w„ùt:ñ‚"¿l„h·I:šF“\¥ÂÄnxX;Á\J,i±êçZ¬úN‹U¿‹ÕBJ<Ū߾Ū_l±š$^àG=ÏI‰Ó ˦QàƒÔK|„Aì÷§=ôÚëG£nîÆ%Žƒ^÷°˜XF\,i±êçZ¬úN‹U¿‹ÕB‚<Ū߾Ū_l± -j—(Ì;ÿñ§“éh‚²‡ørùÓ MüÑ4é#Bî{^>A†QŸKZ¬ú¹«¾ÓbÕoÁbµO`±ê·o±ê[¬&Aˆ/ÏN0èOÃI7@’ß8A›cð%ée^šxÝÞ¨—æZšÄˆÄ“Š‹%-Vý\‹Ußi±ê·`±ZH‰'°XõÛ·Xõ‹-VÑ&Äïù}7“N“Ñ4‡I2JûY#D›ê íyYÐE;—|L £ûí˜ôùåLúâ~¿›ä‡ÝIæ‚^Ö÷㬗Äiöâžß§½ ñÂ<òF¥£Ö9‘7µ¾ð«™8ùeLœü"'¿5§f”~B'Ë´còá—5qŠ{I¿ß‹ÜpŽÈºóh´‹¤”ø°Ç¦9›=¯ì)•—{Jå9O©¼N© -)ñ§T^û§T^ñ)BK?Ê;ûašôG޴ߟt½l&F‰ß=µ)‰Wö°ÊË=¬òœ‡U^ ‡U…Ùè°*ê» R"–ðÍùb¹Ú±™j“ Oªâ(êõ‹vSã$žÆA·—öºÞ¨7Ò ?ž¤Ñ”“ÄÏ;3EÔ|:\,yDååQyÎ#*¯…#ªB2l´—/I†Á¡É°xó =Gž|"ÉpÜ ÆÉÄO“I€äÊqè|:BÛš|P ¼¨w÷êrdXò|ÊË=ŸòœçS^ çS…dx‚ó)¯ýó)¯ø|*B[ß$OPŒ‚p<Ž&Am¡“dâõûý^’Ž½^M“t”gÎä£-{Ò?ÙI©Wö|ÊË=ŸòœçS^ çS…”x‚ó)¯ýó)¯ø|*êö#?O¡ÙÆY?£iÚ’QÜó ²obÒþ4ÏÄQbÐkp>åÝý!Δ<| A7!EgJ"±ëLINaž)É_@g¹gJÍö,µÎ”Œî·s¦D‹-&ÉÈóH2 Ó¨öú½~â.â½Iu'AEáxä™ÁûI¯ÛoŽ’tÇu°¤}+¢ç&É#lIJd3»$™Ë¡6In`¢$ à ‡_O²É$é¡­KØ÷¼`’ ­K¥Þ8özqwóŽ9ý‘p\ß}ÒB’%cE‰Äù$éŠ%=5Iž V”Ñý6I²p3ƒ6ÕI/ïä=I¦0ë©Æ^ä{)Ú%Oô7ždq: -ót^ñmÿ°½VR¦«’æ#"q>»ÌG䯧&â˜Ýo“ˆ‹÷Aà^”k§×ëEþÔ A¦½xì{1’F{½,N¼8‹²8W£~Ï÷NYç!C€ÏX'!÷uBæé-Çæ–RµsskŠÓÑ4̧Ժd£]Ê'k},”Õ£lRr!q‡]$7äɱMFaOz~&~2õ½ ½nôâ4ÿ\2 -Ólòu"‹+·ý˜ÒVj>qáزq7;ÜlFܹgœˆ»ð¨mÑØšCÜÝ ›u=/KGÝ8ìÇ D«Ç“Ñ$ðlœOÜìîë t’qëì¤jWØJÍ'ÕS«8©6Ó$4#Õ|eBR-Ô'„½¸æy1§ã¬7š¦~7êõ¦é´ç àõxÚŸŽz^ç…¯ö¢~ˆ »mRuëì¤jW+ØJÍ'ÕS«8©6Ó04#Õ|%CR-Ô3„=¿呪Ÿõº—$ãq2š‚§i€Ïù½^O§~”§õ¢ž{õÍí¤êÖ5ØIÕam)5ŸTO­và¤ÚLóÐŒTó•MHµPÿ¢-˜÷rÎô»8ìØ$ zá¨ëý( Ò´;b/˲¼#,DàŸ4ÖÒê$ãÖ(ØIÕa¿l)5ŸTO­\à¤ÚL¿ÐŒTóU MHµPËݸõ|'©B܉¥S?MúÁÄ‹û½Iš]?ŒÒ(òr”1 êŸû;HÕ«Hªö£T[©ù¤z´£Õ"RmvÛŒTsÏa‘jáqlè…vÇMªc´yê’(èvQ²^ÚŸL»~Ê®!kî^ÐO’nsÀWH¦ï¤ÔžRí±-eZ}BÔ§#SæÒ,\c-ŸË´ã .¢Ñ €9Š›F}¯ïƒku0îvûS°ŸïMÁ(Å‹’~<ÊòâNxÂÛàT%—n5µÇ³”™K£Í#ãµC£ÍÂç5¢ÑÜ zMh´0”^õºq˜C££nèù^o:šLÂp:Íb$˜ö£¬M‚~˜¹üô€&ú \IÑ\;¥R‹ûÀJ¢Ž3³Ì\=õ #ÑfH4ÿ| ‰A„öûž[ƒ: -¢®—…YŽ¢iš¤“qæAt0A¿£‘Ã(“hœ½^}›h;‰ºõ§Vu¨OÍ2sIôÔÊSF¢Ít§H4_uÚ€D 5§>""ļÝ$š$ãi¯ßÏ¢8M‚î¨;öGY:MüÉxÅB¢qÜšoñUjqëM­$êP›šeæ’è©•¦ŒD›éL‘h¾Ê´‰jLý¸Ûï†9$Úëg£(Çýn6ê{\,v{aŠ~MCW|L¢Q­“hɘròBuÆŒPœžDO3Â2í’h¡¦ÔÃ~ä'nY4öCoEÙ${£pšv=D³È4ëN²iè0$$ÚóX•S¸âidV2>„œ¼¶ñ!Ô§§íć° A»´]¨Zõ æ¸dÓ, »ãn4Ê&½Àë¡Õ0ûišu“,vY!bÚ ï°×~CN-é|ýc±x:‘Š 2µ•«ª=ÉéHú ·¤&±&^]b5†ÁB®q=r¥E¬ï‡}´;rlgi0AøÛí&ˆp½0ôã¬ïu»Á¤Ÿi$Á"¡Á•M.‚uî»\ëØyÙÊ- ØSï¾Á6Ú5%ØüX#‚-܃y]DVyÛŸtýt:™xã,†ˆªÓiùVÌßd)‰rh°Î&« žbeö±],ÜEy~Ðóhp:™zøê‡nœu»hÃ?š„qšøY’“žËUFµ×í£²OaL­Û…ßJµùÛ'%QÕÖÙ>Õ¢ÚSìÌ>¶KµEû£°ß ¢~CµáÈO»Q6¢`äGñ¸›&ÓÔ›fI/\fÒ˜j(¾µã|Ú#·ó¾•v'f™¹4XÇê¤ 6³*iDƒùF% h°È¦$DlíaâÄIƒ£ß$Jº£,uÑv}œ„ãÞÔó‚n²Àzvô½~Ü <£AO&÷=ž] : JŒ5´|?ý%Œþš™‹t_¾µHP›úŠŒEÂ~J/vßx§Óú?º;í…ѨߟDŸa¯€øâ {Ø;îȸ -¹/ü´‘¬ýÖO³Ä<’­sh’mv h’ͽ ´É]ö½°ú9$ûp÷g/DÛl°VB{Ÿnw:‚£PhÉ¢”a·þnç!ž²rßj#d‡¡”Qb!×1“ªCÈÍÌ šr¾T}B.2‚ -{Ý°(ÕMÈ šöÆÚ2õ#?ùÓ$œÆ£)qLüå|·ÖI÷ ÎÕí²;‚³æTF‰y„\ǘª!73–jBÈù¶Rõ ¹ÈT*ìÅ~†9„œLGI6ꇽ ÷§Ýx<£iLÑþô&¹„1[Öãîýâq‡y¶‘«ãDÊ(1\ëœEÕ!×fþÑMÈ5ÿ˜©>¹1…pÛ£—G®Ñ(ûi’Žz½4é±çià…àõ¦QîözaÒoyÃåŽìl#>Çé’QbñÕ9WªC|ͬöš_þ‘Q}â+:/BèõÑ~?Ç/Î)»éØG¬ÈCLQ_˜N¦8ÀU6qDO#Äç¡mÙa/(±±wÂøK ¨ûèÉFÈŽ“'£Äð¹'äfÇNM9ÿÔ©>!:ž‡˜¾[u:îö’¶_=˜2ͦñd2é¦ý(™Œ§žëzSLÈI„þÿ L¿BvŸ_ÙÙq|e”˜GÈ>¼â„Üììª !ç]Õ'䢓«öûqâFdÏŸÆq¯¨v‚$Ýqw’Äc/ò¦QÒ‰+ú9&äÐï' .ŒVb†·_L²÷NÒS®‰Ä®°kr -™îböµÅ©¶%ðU#ª±êQMî·‹ÚüêÔF‹-:&íùÝ~7ÉqËÆ~ûÓq˜aäE£q¤(W:E¼?ìåF–úåÆÎy„<‚*ÔR[KmA ÔfAÈ3 ¶à0Ô”£¶nÑ3ß°'Eádê!æœM²Q/IÂx<"VÅI½Ì Õôúq¯ÁÅ -µùU¨Í/¤6?—Úü¨Ír,Ôæ†Úü’Ô†ö-½°Ÿ³µAPæ'Ó îÇÓI’x‘M¦I˜„ýi˜9l7 µ%qäõ[Â6¯ -µy…ÔæåR›×µÆ&= µy‡¡6¯µ^+7Ã¥ñ¸ŸŽ½Q4õ'}/ÍâxLÃ^}r(ém!ýÀ?§«>ÙdžnwÃiFäz”I=¯‡`ø«O7_þ¹Óù,û¸žm²Ï:ÿó/Ïð×~xÁg_þù‹/þüâ/ÙÇl¼ßeŸñÕŸÿüßÆ«å<"¦ÙŽ²Eúù/þ2Þ Š³·éhž}þÙ"[îñdQâ]¶Ü}öe'ÝlÒÇÏ¡®é,›O¶¸.þ½žMôWè%ôŸ´j›mféü³/Ù—åj×Yîçsüõí¯¿}Ç¿ÀœS+Üï :ݨ:Äjµúæéò~¼š°‹¾ÒEüÏgëÍl‘n;ï²GÛ¤‹„ûåì÷}éLê0HjˆÉh8„1ߧó½­[x„-·¿Ï‡ÐËtŒVßp›íHó÷»io1Š0Ý×¥õ!Bœ´‚ŸÁ²yJÔ~lêƒrg»r]tÔôý×?¼±WıV×$ÛŽ7³5Ë‘jĤâGã­R+¦õá~3;L/½È@-\á1§’Ô¸Âsi¬[¥ÎÑ|5*U¡X¦£Ù½V’ɲÍ2ׄWE»ÙòQ«i“MfÛñ - ƒ‡¯ëC6»ص\‚qbüÖér’Õ…Ó -}Ê–úG¨hn@l:¹£b–÷­÷Ê:U“lšîç»a)^P™êYZþ¹“È8CD…„ì²Èd½oü^òŠmƒ"æM}£¿MÊÁfåAñ/ÅËÐãO_^jÚm²¬Œ ÔŸ+VÄtúÈÏO¿M9äžÁ‡òHÔ´Æ‚¡ß¬Ðôøâ©BºZä@,Õš¡µv!d¿É—?òûÖ|z‹å»VºYVJo¥²ñ<ÝæOÝÉ~mðգɪëÍêýlR ?6„ØsÌöq»Ë­Jd@Þ¢ž;ZáëEêc¶ÁÓ¡™ÜB  û%ÙbnL¦Xñrððn‘4›O_<Ý€O²5]0'©~íŸ`®‹E£upžÍ -ϳYÑy6+>Ïf%çÙ¬îy6«wžÍêŸe³¦¨˜a±´ØÒþ¢X-‚·¹"iÞÁŒu7j;tÉÕ¦]¦­÷bóÏ»¶ö¥ßÒÆÁ¬øI¿¥-ZÅâwWúÝ“~÷múÒÄ!‘µˆP®¹\:ão‚½Õ4tãý¥x㋶¡6lñ!˜e õ’¥´Tº¤ùÂÕ&}3\ܸª£Ùr›mv²®΢‰Žès¡4RG\.#By õ®[;dn¾É"ØuNwªø§¼›Ä/ÈÆ?Ù–Œ.6ºmÂOlÓBÊòQ&&X“®1?DDeBRŸOÿôoHÿFôoLÿ&ôo—þíÑ¿d ÈÀDm‘YÇÏh:YÌ–ÒTH›&†t'w+%•´LŸ3åÈcÓÌ|æ˜AÒ4lÎ#fSÊ ´Ÿý|õîn¾Åf%ƒW«M6x³ÛÌ–÷o7ér;OaRì7LãéæÝ~}s‚ñFÿîæOÿ÷Ÿ¶8¶ûˆîn¾†&ÏÐ;œ—ZÓ@²ts¿_ì1K#l­_(íp $“ÚȘ ¯77_ɤ‡ßËÿMþç‡ÙòÝ·”=)jŒ²Ç—·ÝÊn›Mª¶f¯•=)e…ò6ñ³¾FÔF3Œ¯‘ï}غùLP½\+¿ùc¤>Æêc¢>vÕÇžúØW56nÎÃ÷(>ð®Ñâ -Ü‹KØßè‹Ìµœì N-ç^÷îæis› ®Õ&¾GRQ­“Î"]¦÷Y‡ŽómƒF_¼ð½6 ÈE‚àY A˜ƒˆîöc0 lŒZI—€èù kõÙâA Y!ÛtFóÕøÝöK Ø= ?Ùnü¬@¢wxŒŸFDVŒØ=d‹l‹–ê}|0J¹l€uòõz¡–,Çç‹*êM6G›c,/ T˜ÎîœuÈ ?+0HªƒW ¢g± «É~ŽÖñ1¢h`s pÜÝ|÷1ÜÉÙ"A€œ@¶ dYuèPwv«N†ßÙÎvYgº_b]Z:ŸíŸB‡GˆøY D’¯\˜Òãñ†º^Ì% „bÝf¿­«ôÚ•ÆCò{ȾÔ4—–±Ýe_ÂZô}Я#é˜ôàl¹tÒòÞÎwæ«1.£³švökpÏ&ìLŽ…þ‡ÕHöØAÜIÇãl»Í&W¦^Qº@Jï‰@Jß -)³EzŸ w«ÕüÝl×:¨ä•~°‚Äÿ×ЇíÃÙK7BÀò°Zm³Î‡‡Ùø¡3“› Ê‚=ú4›vWûÎCúý^nwé-Óio:g©ŸÕ¦!89ÀôŸÀ0é/oÛ°Í6ïgˆ‰µ¼sP‹½dA«ëïÙ¨ÃZ~ÝD´¹‰¯´…`tûÔö¾Ýo³Ý!˜Û¶"··­1cUº -¿ˆ%‰Xè¯oÞth4,i¡ž·÷ýXßGàC©Ö/ñÛå~1Ê6°·@ŸÛÎ=Àü|‰72”ˆ¼Ùv¶«ý|Ò¡ò`„·/w–j³}9ÝÏç/À{ñ9ÉÇ tbë÷ò¨ÀjÐe’½Ïæ«õ¢Ð€±²l`”|X䣢DÃψÂDÆ!ÀØfHCŽ÷ÏjCq --([aON„±[9¯.ÒË!ÏpÁâ¦J140 $§Š‹À´.­£ó5wJP£Þ¦ï$9f5Îgˬƒ¨®³_CXO¢ ]aqEš–Î.ݾ»ÂË¡% ^ز¼||±[H")Úƒ×}µMRYxq×p肤“_DÎX"e—4NÇ°©Ã@2Bÿ|˜MvXù¹˜ý —ü¬päŠOG¢§‚#vãÊùêþQÜ0Ä^úEà*êÒzbٸ٬6­ª@Û•O|]Ù‚Ýzž>‚^·½³È¶ÛôžJ)°šFÑ›ÎザN +ñS•b‹Ìá&»Ç‡w-kMÔb/T´J¥­ÆËjîÑ¢<[\‰û2®°禛_bÛ9•MˆÆv'êyV¨RTšªTTžŒJÅnÜɨ¯¢¬bƒ óPÈ^ö%€Šß•@…5ÿl% -mÖes¢˜EÛœì_«eö,MÃO²ÛÑ„­¼Ë‡Í:Ñ øšnˆu»Ûñj>'±}ÚÀ‘\˜€„ò-ê_ŽÒ™3”H°EºXèÀ›¥ÒÝÐó²K}Q#¦MÛ€òTLS}»mªf~ñZÞåÈ…^‚øÜ·™’¡´w¶ø‘(øvÈÉÛNö5äm'[ÞñϳÕÉžâ踯‚ÊSÙç0/S¤ylS¤B/S)çí4)z’Qº–0MIŠEÁ-“ñæ™ÁFÍMCØ`U>9Ø°ÍbsÙ’Èëh®«ÚΘ`78q×p HÒÉ7æê<[\é‚3¾‹4æäËN¶HgóN:AKe‹e;_ݧË/;4ÚsgŠÀe×°G_Š³+ü|U¨xÿ£c[«—:vYàcí¥ÔKØIlÎ8þFäÅì™îw+qŠƒÏÚ\í`"x*0‘ó“À~Öòv†x <¿m³MÜfšž³iZ¤Õ¤Rèð÷ØÑKýxNQË„¤év&T1ãÉlgì®Ê -ÿ°Ú¼›ÎWZµØK€TÒßi£Ï7 4(34XÀ`6ØÏ 'Z14«†ÑE »ùª²œKÝ.P$.î®_\6rþÃJvè?;´P BXÓŽYßòn<'ð8‰?QøÈ3SÝdëÕfW ¾(J9—€Ør ·ùlá!D›¿Í²:¸_2g;Iµù¬´­`BÁí$Ï#„h`73ÝîÒݾH—iYêæq‰TÐ% D{ƒÛL[‹ pƒ[:`M%mµ4ÖÒÚoî@´w€E(ñß3$åt¶r»;é)„Û`õægÛÎj‘àÈ·Ú«Ò­Ò¯Ô1þåÓÍEâE+ÊÍ|BÇ‹à‰F< 4£RÐQ<À·‰6ØxØ‹ºÔHÀÏvµžŸ¯3Pô˜Xi™ŽÇ«ýò<£B°™8…Fï‰â€f Jm¿¥5<%Uhh·È Krki—×ãk²¾Îß¾Â÷ÿ{fA!ƒ„dÂ5[Žçû (%ȵ¿_b8v•*zø}?Ûd¸wt{‚ 5˜çí3B›DÑÑ&x*AKCÏ 7eXŠ¡æ½UÎ_ö€ðô,D<r¬æL‰ö&‹Ùv {>µ7(z*B<=!!4‹P¼ í—'æl?.ïžÄÙ‚º¸ØÄgÍwµkÌCm]=›eX–Õ|u–@Ù…uÐõ¤jU2†Î ~™ïïgK2ˆ?¬ÐÏpïØPžE† ƒ§NÐV9R³Í›Îæ;¾Ç„¹y?ËÊYØØÎÄEå9å^cuÑÛì#;ƒ&žÄÙd¶;çøO]çu¼ÐÚú/ùu=ì˜}¶íÙÊp¤íåyûI“¦¶1'Ø«jÇìáF«ÄQ“ Œ‰¬³›­·Ãtn‰• !j¶KX1¯V‹5\r­¿8¹Ô¹Æ¼3Xc:ÔEöLظf G•8ËÕ$î×YùÀ&ˆl÷ãâöEXXðE,ÈPÃA'Θ…CÇMÆ‚¯,ˆÖˆ)šÖ(g‘™^‡ Æ‡Ý”­Ÿ#ï^òØägǹóÏ´BTÂË7³3nÍ@æ ÁÄdXEdÉtá“ìéò¹8ž}ÆkKç؉º¸ž ÇÖ Í(crKÇ;|¼Û6ÓÎ-û"Ö$åÛ¨„÷-ßßËm?G†Lx¦¸Q'_¾½ÙtµâÛ. 84ƒ3:g$GÆìÈx @Ðå8pq|ù¼—˜Îš{ê{&¬Y3åÍWãw”ÓÒ}V3~ì,ðÖ¬¶o ÔlÔ¨s7ïÂ+aÍõá!Ýuðp…wº^géfÛ™-óð-Z´#x/np"á^·gk/Žûu¦ÐR{?Ñè~‘f¶5^-€td{¬¼c6÷ùš¥ K“ÖŒSÌ8SY®;øa¶Ýñ3?‡Ž8 *üÀ_œ E™Î;¿ï³ýYFÀ -½H T ˆž¨ iÖ[| gî :ýܲ/Lˆz€,ÂóVëG ·ò’5ø[¡Â_M9È\Qä â[mOE4cµuº{¨eÛc5; ½Ìðïn~ûõ‡N:Ÿ¥Û3F pyÇÇûínµè &o;»U'ûˆð=I8K”€†µu.Vjhž£žJx¾H3$Kþvû¸—‡Â‹/)z7qå‚ö?lVKáÿ|±¢{wózAœÞaËòÿdÆ¢Cç²?ôÙÉnwŒ.Мώš9Ý>@Ö¶·$Ö2/<Àà µý|å ) ò–Þ˲ÜwæˆTÎR’À´Éºž6TÛo<Ñ€|‘Ý q—~\-W‹ÇáûÕ8íçéæ±m¤(SÅ%*é-íÊÙbGÒ±´o„”É>¤ïá.ièÅü±3ʲ%¾†þ<Ž0¥@«á%ô¸\ѽ/:êÚ`Ìœ†ËØ@î—“æ`a+ï0qÛˆ ‹^½]­a7GéŽÐšMíŽbà&èÆG/:ŸG^´ýâl­6„&Ç8ŒÕÁäò.í`Ò³I:#V;œdËYÖ–XŠ»$(I”~th?. -IbŽ$ÖN„W 9<Ñ(‘fZŠ=ù†ûÙ-=ý.¸ÛN]…HN‘±™A›ƒo©3#´ü|·1‰%Û•r¸^>}ŸÎæPŠá‹‰µ#gëÂè,€¤j´Q] òDíHcÍŽ”jAÉŸ!¨/ð²ÏÕ²…¡d-,þ"Æ£Ú‡óF—@ ¤6ïy£¯¨ÑòÑmjÄO6ìV¥t]ã66ÜÅ_ -lÀø_lLy£¯°qdØx*÷<Ç6ÈÜ!"Û€”y•>×ÍÕˆT©ábÐ:ә϶­:­¶k9†^üLϿ༖šé¬–t>ïI!¦õW,9°$ÖÌÇžŒZ±„˜c7ôòRÂ8½Dñ„r„>tÖg}¶û²Rd+5+=è |Ó˜­Ó&ž#šÈTu†á˜Ù®ÇOÅ5ÖlQÉIŠÀB 1zO1ì/Ãî½m'Sk™—€1Q´/:„ºÙÂì_9+¥a°ÎÖehb{©‡ŽšCüD­%ÍZ’ÍÙ-=®ñ•‡ÛÈ=1È/ó@§êøm‡6ý|Ñ¢§š)Ðö’ÊŒ+àù¸ÆOØʺ`ĪH 04;Éí|º™ÜN7ˆUŠ²ÿo8Ë_.@Ù¹Z´z{úqŽèéºÒma=ƒ„D¿Â§cÄPA“N‘t7í-F^è÷p8ZMË,ñÑ~9™tö{"Ë„ò!ˆù˜ds$KÔ]ì°ÙÍ–Žê=­~êdUnÚ»Mö~¶E³{êv8òÓåó§ XJNdÍØe+¶cDõjUm÷ Ǻ•¹øž£6>Ò]ãyVk•': 6_¥€X‰4(¡j1P;¡Ž~¨²å¯UUþz.À¯˜¸2‚+#¸2‚†cÁ.ø¡Z’ƒ6ÅM¢O@„D>§ÖKW0¼‚á Ž…´¢Š7¼GoQ:/%ÒVfc_WØ(ãÀÕÜm×ë{A”Sñ‡Ù„¦<™žLn΃ÐÙž¦=OšGVX|ötGã·»ô~{e·Wv{e·-Á+,¨sà¶Ï_ GÛšìðèJbë¶q€w˜mê9¬l¿äÊž¦óù(¿;â0ù¥‡éþL§Qä|q¸¹ã‚ɻߤ˧ytŽ]bòpã¨)Ĺ6 ò¹5¯ü!1]$ -]º™J-$ž-·Ùf§B/]È• ¸X›ÔšÂà'ÖZ©­2Kϲ2Y.2ö̬DÙÏ´ÆHHÄa†eËû3”Üh£’U'rV†A^øCmkº¡À6?çÀ÷fµÒNýG6Z9¶IG¶(¬§j)Á|¸IΉ'óÇ FóÓ ¼æÙU^Ó¢—£Ô´Þ¬«ò71E³ñ»üû6ªá–0?¦Ó)ÐÚÃéR·Yª§¬|Xj¹7îo%! Â’(¨ÀZLïÏ0¯g¢2ÛH(QßÔ°6c©k›”i`ø¼üÛ8šÝ ìKN^çBg_l£„>°‹ˆ™-hA?Âb]^‰_–h$=Ç:˜¥^²4Ì -9¨eb¾ä(Ryà<ìKñÂá_ºrÉíè0/f)Ë!Udb]E±âú/P6*mËuŽZ<ÒjG:ªTU3ñ¨‚äÐH>ªPÏU@R°÷ý… H5%–ñº§ÄåŽà©sF'–ûl‘!N°X5y­õy_K6¼%pma^Kš›‹—›2àb_.™š¢B}•ÀyÒòÁE™Þã¡ÌÕeÇàrzõWk‰«µD¹±¸ºìœØeÇ4­¸,sòââêÎseÍÚqeOÀç¢Áõà yuõ¹å(¯®>WWŸ‚JŸ­«ÏEóÏ -ëñTÞ?:/¾º]Yñ•_Ý€t¢º\ì=CÏ ß÷Ù¾Ô†g¶ËETs„ãB{ô +º´ "éjÆh¾5VÛf׳MËæåU c÷涠(U¯s œ«DLW¼Ivó?çtÐ]¨8xQÁy,‘uZ°áhli_Ü4bË!¸ùlÙd×Õ¼-ÓYÝÍNËÓÎááj¹_Œ•¯SˆÝjo· æQTÐÙÖßl¡çÃ…F<®NéV¶:Í})>Y­tÕ1k@˜çE »Ó²LÙ/£í˜pñBCø§Öf‡[™Å?Þo ¸ø_¤ -ñ‡—æcÁ‰ØJb®d‚¶?{uúw7oÓÕòqðjµX¯–(ãàW”d¶¼Ç³›»^×»û#½ëC¬íèîÚƒƒa{w7¢2’ÿaµÝÁOH{×»»¡´'ÇÊîn6Ùï{Äxm -ïÞÝ Ùîa5¡yÿý»·ÿ¿_~~óöæ«Oø«^GþöQcÔìÙ /ŽìŒ¯Ý@orpg¥?¯hzÜ”rH¢¬Ogs±EwÌî¤Ë1-Ýg¥ÃØ«ßoIxTò{”õD:Žy\&a—µLmqˆÇŒ5õŽ^·x2Ûábå ¢ˆÆü¾êÜ6rtÐ&”"°áû”$7ç×'D2\o²éì£Và N´Éî³,Èüÿõÿ¼°dƒ¿ü·ÿ‹™gåíVï²¥<ˆRÏQ+àäŸu]¯ð\ŒÖZP-kÈO´FüNÔH÷é{µ4hh•ñªÉ•ù3Y˜ö@C€á’õÓ'0Þ` xñâ†|…‡„y`ÑFôÑ’°aêt)dÀ”++|•û=ˆ0Ä ¾Â4 ðC|Kh(‰ž ”ÐF’ñBL2¿S‹ ÐÜÈ_oé + ý¤" Qr4Á'ÁØÓppѧ‡ÚÃöÁe¹Bu¼;ºÐÅ-w´‡"q(‚ª.WCÒÁŸç+°\å Ë2»ÂÊV®°r…•ö`e4_!‚ W²¥“‰/øËK~ŸòKœ½¼üƒ\Ó9œM>½ü_þõ)ŒÜýw §B¯.Pù1= REˆ ªõ¤®Ý -j¬ÇÝ.’Æ0’$pp-¨Åìûàxñõd"^ÝÝÄ»éì5nÓ¢=ãöºRö}>úÆÓwp ù{@ÜÐu¶Y̶[ºJA•€‡e¶E3F -Ùžy¡ÕCz1 žË§¿¡¿ò$œ''ÝÀŠÀ¼†lÑ°Öbµ£t» -íøÝ%î^»Ÿÿ¯_þ·ä/ÿŸÿçåÿ÷ü/>ÿ_wøn{ùÅÿr³±ˆu°‡;=ƒ32•Ìî²I±ð"T;©”¤í'HåfOEcjc\&±MæzNîôrñù¿[8_’Ëù’Šœo’-V%Y$­Ïïpî^ä%6†ÆΕÛ_ŠË.r9™ÅAµŒmѨ4cüS€Oénˆ€v9î³ÝOiŽ^“0ßP /%[eqq<­‘ åy¢‘=çÑÙ¡-½<Ž£±qD>p…ܯ›»$íì/örØ^É›s3¹ }&çdKEµñ%ÇP‹õó!ÓÆ„â\&WeB³ízž>–ãC•YÆsºµYŽßµjƒ‚À5~¸Lq™ËœfŽžé ×ê† 5gè AF}¹î–Ήs\òn)ìEÕôUùkÅdA×Íè¶òšq$W×ǹc¤q˜ Äa= &eÉm NýmÎÝⶠì[õ`9Û¹ý—ØOs+pá€~Ý -ÔÙ -ÀZ¨±À«÷ⶤ³µ @}ð­À|6Ú@Ÿ²¼§nÂ~Hm*¦ì'1¡[Ó§õ¢ê3!\›Î‡¾á<@eE¨Š_æé¸è åʉ®œè˜œ( -›q¢Ð+ZŽfæ2#²Ï“•éòù±¤Ð¹à}@®4NwÙýjó8L÷»*½ùGåN8í –ö¥5­…'fü¨¾Ò*±+­€åÔ_Š ù.3€<&ôŠV÷µT›ÌŒÔVœBSu5÷¾\Täõ+j¤J,“  6@ˆÛž±‰zª°MGRR…îB‰aÓ 9È…ä ,$éê@† ŽýhGcbߤäÀë)w“à6ÍJê[fõ|ë~Àgèli£@iÌʶV£÷ -O&ÌËqlÝõùr¬\ú}¶ûšTð–l3NòÉA÷ 0àf;ÍD 7ç™wP?£å…F„츳e` ‰°|G§-Ú nòíz³úø8\mf÷³e:n³ÍûÙ8# €ç¹c :w Ê•ofCãwó74.ÚÉq§,°0‹ÁøE™YÅ1ö0ÎÎåïhô^æî^ò°Mž™8y& EqWKÇ9 -Ä7x9yd)vØÞn$žâ -¹Öç{^3¾gjÀÐbWñ~»[-®öÆWÜo×Q¾ªÇG d™MFö¦nò{Ô‡Ùÿo30Q—w¡{"’ù%dÞÁl‚ľ¤>Gݪ.#Ž&UÀk*sNéÌL¾|kƒâ#ñ%ï.x_pF|#¨Ä7h}fRÒÉ'ÊX¢žÝ‘ÅÉXê­{Ë IsBÂfzQ 8Tv‰‹%n6Vo´[w¡W/Ãw‡c-á—žq2k†6ìoûÖ0S’½œVs)Æezà_¸ l¥ÐÔ‹Ö%o/¾†Æ¨û -ôâ´£-bhŠYfª3´¾ÂÐÆRc¯û‰g¾Ÿh`‘kY=¹ZŽv,rfœ“E®eŒZWá( ª‚÷·  gøƒþøôROiÁx–é¿«‰9¬×GõØïYÅpØÑ8›ZÐÑ -üZP î·`8•ãe§©´b©ÂƒA:F.&~Ø[ 1…–ˆäúWmREó·›)!Z:$RÌ'I¨Ö4ù§av%•Ü>S1•RÅ”Ô ]ø´h¡oâJ˜Ë>{ìkŒ†uêÓ»Úg ‡så@4¨ûPZ_&&Oê Ppðžæ= 8à šþþ Z_0ü(ÁÄÅ}°á=[…c”°eHN$”îæ‡'Qú{.­a›ÌÎÍë|©‚Gt;³Ì>°‹s·C|?Ä ÝºØÝöå&[Â*.Êçf~åŠháX;¬6^‘'¹¨-¥¤Ëà¶T傤1?e˜¦ë'Ô’HCªna"i -ÂUÙÖÕàö‚w)qÅ쪋Âb¸Ë,£¨Œ&G •šzò£ñª#ÛúÁ9Gzrùà¡ÇxçÞÎ@²O¨ëùc¹Œ”´…}LØ·FÕÚÆFwùj* Ðdø—ëìAAÛoßÏà€„B.V“ý<N²5Çr<ËßYâj”Ÿç·á³ì?øÿùl>üÂÍÇ™òG¸[_Âã%§ÿ:›‹ÐØ\@ydguƒ}è;(04ÚUˆN¶µ¥P†íHû‰DÙOpÀ<ØnBe:oÁ__þ!iu>±'ôƒ\ - e¢‡õl’ë¢ùßáÿ4D¯‰®Ãƒú¡õV”XÍŠ})¯i³±©^ÕÄ}¶ûÈüEŒP½`;‹„Ž´PA­!ðæOù[ À:bu+ñµÄ¯¾Õ¡Íûšr. -aLËjëåq–¦L¾·]Ý?ò¸ !¢så‚}ÏîúÁ¹‰¡ŸæüGèJd{a‹ÍaNéHc社—(¬”€0T©eÌUDz¯¼Óã¯Eã¼hÅqcO> cëcMywíò¤Éüoš4M'—OpH•câm!›xqzlS6 "§px;Å|Ü" ´aRÈz;™M§n“ ”âå${ŸÍWë9g$ñìS@”—ÛÇåø%ðòíj¿gŒ¿Ó+¬ñS)²õè"ÔwxMBëù`·+Ÿ®¶0¥g gEкU)ÞÈB4†’ÔˆBÆT—‚ 7ôïa³ZÎþ•u”ž_í>®Õžg?u dü•–Çq4ú×~uè -4cÀ²«X¾ÔãöÑ‹ãÜa`]Sñ@Ÿ¢‚½}ÍIÉ½ä  -™´ja¸]`c¿°1ê^.£îUcÔTÌãÛžól©,0ƒa¿?‹—Ëõ[tqP›±÷b«ÂÜ÷êLjaºrü+ÇŠ¿ß·kB>ð”ËÖˆŒäÀåå€Äk¶j"Aä× d8 6@ìQÑ ´'4D—#44RRÈF5 ÎÆa“GZ$âVÕqà”R vRS¾kYú¹"K¿¼È’}\¯6»ádõa9_¥.Ïô¦O÷óùKRÖ £¬ú’ˆ»Ø6¼ÖðoBªÐ®­Í÷«Š´Òïp*\ნõ*J\E =D{¯š9V ÇrûlRE -Êð‚Øm5ïÓéÄÛ˜—Cé¶)ÿj[à=í²œ9ݨ·Š -CjWù½+\dÁQÂÄà,p’My -áÖ“wôpå.§:GÑZR2µO“ùx=¬%Kà‘º<§§©ÝÓ3˜c`¾²E¤5w]?U¼!ùikAµ™Ù}jMé*×ÕçéÖÔ^=kÙQ(Å—"ÓÓÑØ\GGЅ̹¢ s‘¬*ÿ"—Ú)(_jníë•Ÿ]ùYÍ“Ø à2xƒd…NK!Z÷ k®g‡êկĕ™Uꌮ_•:$ô«‡?–UDZ «2_Dz f¨ðh¶,ÝKhBŒ‡:›-ÚÙh’rÚÚhÊ¥ÓF“´ëÍ׋¼æëEí&iò•1_ó™m4ÅZje£IŠ;æF“uà7šbìµÑ¤|¥•fk¼ÅR^+Ü%Š­Ü¥:¿¯Ê_\FQNÕ £Ì‡®ÜæÊmŽÅm*Þ)ÖhmYøM¯Æ¾®9ǩ߉3à9MfàP\LEj2›æì¥Å¨ž‰Õ 4,oÂ\s‹âå24¸ÆæÄÇâ–—Õ™ÆÕróÊ9DZ_SìáYmYbãDxE“žUz¡=«ëB|.wéx‡i½Ôe24CÕ«cŒlm~سʱÝh/5 <ÊÛ®…С…áwÖ aøÝ\$agZkgi!˜EYÛªÐ[buDl1^3†SNz½æz3 cJµ®H.XèÎØ;9ùšÞœÛ¤Óóœ2Ãv0F³!z¶ÞüHS䇼‘’RÇYï pU¥x…5<ô+Q€-<´-§ÔL³áÕ«•¿zƒÆ…ú7·ºIÒ™yña6É4®u>QiZf4Ï îÚr0ˆ«qmµZìX°5œ¦¸+5 Ç0®õ[Cl?±ý’ˆ:¿Gr ÙiEl’⥖ÂÝ–Ä-9öúÖƒŸ Rk)@wùÓD]µIÉ­ÉO°Y}U9T£ãr;<6ê5|ñ3Á¤¢¿Œ›Ü-we DTR7¹×QýɃ»Ç¥õ0ÓÑ|uK m’-g™KŸ²É@§¿}IÒ¾ÐÒ:õ)9ÙÜ×Þ`p •”Yö|5–|ùîOÜ€î7yíhà‰0¸‘p|Hó€ŠÌ¤x~»Zw>£ðG»×É6›Õf; ”9Ay@ÍP= Íx²4=øvôÃJqtÜ­Öèͨ$Joy˧TdÜ(Í0 (H>¡| cù€J£Y¾îБ(0,ç£ÄÐ|@á|Àð| × ÑÒåaÀà¢M0ÃõÝ= ýÈ@R 4Ìè ?PQ Áþ ÷ øòtèaÿ€ÿ@Cÿÿþ00Yë¦6!™ª`ƒ1m}2„˜+qƒeƒÇœ),a`(H˜) ®0ÙB…uë{,+FcAP\S¢æ XnÄ3ÄÒ”¸ÆÀÅ6˜o $Iaû>ÑAå\d °‘ÄGœ‘ dN2YÉ@ð’ÌLÀMpúl¨ü¤Â€B"Æ]"ÂðMƒĽ`mçfQÀXpÚ—zÚBÆbÉÖÊÉld5$•QÖÔ;Ž¤Û /À§±ßÂÏWó,Ý^X GA4¦ßöÏ3ŒÚcÔ­* ³ <£úm$ª¦…q‚ëaíõ°ö€zqçº*Ћ[óµ£w4é¬ôâÎak]/N@={ŸI˜çA:NùòügX!Þ_¾zmÇ= »ŽÁÔ;Pá4Öà$Ò±^û ©×ùm¶Kgó­ûp -ût…ö«§­°'vìæ}BŲ¥àrÇØ:—’ÌãÀ ædâHè´bæ6çÆ÷ ±ËœÚOâ.çdνcÄÐVÕL^uîA×Â=â\î—æ«÷`‘}(Ã@*ò‹"åRi6á'öËy=û¨5ã -^®ÀFÏ4âAÔðëUò¿²‡jù»/)Ì[/=ìâMDygŽ$ÂwÝœ3:­_øD°LY†ËXì—Eê~Hü%~¡&.„b[¾ÖþIàPø÷M=—ÚÆÿ.ÓøC¹Tn‡tð$*Òy¹WÿUçr¿zÕyI¹¥kUú'6¥?d ;ú—ÐXï_¦ç¥ø/7ªÓüo³t3~(`1Z¢BÖ"§oAÌwXT¾Á˜IÅ¥ä|祀I9_e¦´*^DÚÕY?lÒ-¿…–Y¢¬ÝŽMnkÞ¶R×ÝÂu·Pi·Ðó*îò–e»X¶ $C“ý‚»§ß0ä Pë;† ÑÁjsK®žÛ#dJ—[8·Ê&C0ÙIúr7¬ÎÓåýß þ(3}²¢óZþgÿ§ -Ô¾‘%ð=ëoÞnmôªÛpFE—ˆIcßá?2·¸Ïv¿É3ôStèçÛrΖ/Öótœu F4Tˆ=P¨Àñ;øÆýÍ`h?ßþúÛw§a×ëaΑ‚R‰z·ÆZN6·*Ùœ'ó½Ø)nç -OÔ*†ät–,W:\‡,]ŽLvÞèÄ™¢Wã fñkÖXå¥ÜÚâ“™¤y0Cs„F3T¦¡»b´ mÝB«^h5jšN¬ŸàLÇ- É4f}Ž½ -Z=sßZã‹~ YÃ"`5gÂ,€øáÇíÖ%R‰ pàßÀæÓ]yIʬ‹Lõ/§ íN,Àª‹ÝH’ã[9Å!RßÿÙ~EÂa>å·Ú( ¾Ýo³s’güPk`\£¥}–®…ÆeörÏOôˆƒC ä8ÚKÒ.5Àõ©Bh0 -¤ÚŽaƒaëb¾%†«¯¹Ž‘l5–{GïYÓÆoZÛÐÏp8™¥²}…ÆqÈ×—8)Úíâ—e˜’ϸ =jÀoìöÒÝÚäò†Jˆ¬®Ác°Q6a4¯¡†oqm¦Z±šßÖpqP7¤ÿä&SufŒ'a ³1XG”áˆÉpš#[t_#òìwªòþH4‘cbY£¤ì[•57«øý1¸Ü¯û?gsùŽ6p­ZGn†8ÓÆršÛ‹SðrRÖ`88[›ü¦×uºå4¸&»IòØͨ·é‘°]Є+£¹2š g4öåo -ƒdeXùLhá3x-Ÿ+›qv﹌oÇÉ1LØ·£ù -Q9ñÄØZçx¹H—xË€Ÿ>½$T‰©óß•„ª­~د8¶º,¤T¥Gåy“5Ž$z'°uçó-ñ?ÅéªÛw•ø‘¸Êv$‡ Ó°ò¤€ó$šæ)ò)’±¶¾Ýlž÷IP–c Õ/Xêv÷­¡#Œn‡_ðC=²¾KÜG–wnÄ@¢éÙœ42ùWŒ•¢\>©NA«Ê?wL´ÐÚÒÊMsþ$óMlÌQ›kÖg—í¹öF}«1§äڛ߇† 2 '79dL#5Ü£”b’ö]çÄûõ$ÝUÞ·]YäSg‘—¶ó+r:>{ j°ÇCîf—«q<[f—ãqú…ÌÎÂåš;Ë\nH×ðí8]®–³qjÞ‡IZô‡’<—½‘ :«mŒê‡ýȪzÅ­µqÌ)l|«G‰ H¶£VÆzpµ$Á 8wdßn¾ &ÿã4üËÅÜZós-.Œ®>QõäsbSQ×~‹µbH M¼_%l%ÛùRHŽÀÈZç ˆú´dÚäBl -› ½ù¼HêL¡™…etÚd>n›¾ÇNiJÕÎcÀm¬\;–¿¥Âÿ¾ Ù«ï¨,ÙÛˆ†õí÷”%Nv®4¤wŠs"XÓ¥ ö [Þ¸¿¡'¸W@6úC4™›ŠI€åWûínµ {®Î|6Ú¤›GÊw°élâdR@¡“Ùv=Oi²ä;^}< àË`‰¶«”µÐ0ØÀZìÔ¯¦ 5˜!j]Ü°Ç:‘nî÷Ð8Ä1Öb‰ÎMíäz¾Gû2: <؉#¥hUO›Ò_pú@s Øe‡—°µM†¨p¹E`²EļÅ\ÝËãöV6+Tgd¿Ø‚Ú“ƒh‹<1²óD÷ÅlPÃrh—·cÃÿXMîd+ÝÆÓ¬2ž=wã\/ïüͺ})qàFY·ýd­gsyô];­VNÒÌm’ãD-ajílÆD-×ÍØu3vá›±8´û–·¾‹üÂÍØIOÌÊlßòÎÍÎhûæærpr¢1 CkÁ@ÞÆÐÜcWUáUUxåNWîtU^U…ÍT…4ÆÊŒÄC0ý€KìðTc†¡¼´?½ÔŠ­§R6)rqBÅÔ߉uû‘uÝG†Uû^ŠóE5d"ù³©’ƒw}ïˆidz­rê=Óø)ª1¢Åq«;¢@‘™p¤ÏSK¢ÂF{¦ïĽ©¨a„‰Ñ5Œ¬Þ$ƒ£véÖ¬‹4š€…}Ævö9d fWÒ· J\8¾v±Yô…ýìVÍs¹ -È®ã²ÁKDeg·àPpìL¹×-­¥4ÌL”Vr“L²n0ùšnh’éÑüfå¡Ír¦µUÕkàÞ•‚ýP¾i+º¹bE·¦XǤá1äK(£±ä ",=\„Þ³Æk‹ÊNnN=-.ðsë^˜óž’‡§ðŽxrQ6¯Þ%6£IÅ ýÕ—‘EmÚ+Ïq1 Î몶÷Xwüºíþ«ðQ¬" ¿¨î@W~/V×·ÎÁO­çö¡öÛÁZÙ‡¶rvÛ¸NýÄ7ƒÂªÎ^{ÛÉgÁ3/Lyû<¶”gååwÝRÖÞR:OC¹¥¬ê+XšI¶%èÎ÷õX“Èjýš¸ïKw¶Ùal k…ÅÔ´ÈîÏÏÅð"ØúsÞ"_»O1¾OÊî½–ÙýAÃtº™wÞaðe2ïÄ}pÅy·…i·æÓ ~ŽŸ#Mñòú#—÷²Äí™.E5 'Žàj4­Â¦9fà!êô|”ˉD -èI •Ïo_‘Wò¹-MõK¶Y¤àgð–Üæ×+½Ž $gÓÌ.„íòWõ¦×MnŸ%B?þ¾“zqöPÏDZl‚j’Ò¸‰ÁRž*ÙùÊaÞøÖ=A<{xéØÆ*kr]JYûÆŽB¯4€µ¸ƒ¥”+¸ª\Ï’Ä~Á¬ ÒÍe gäÄ¡±œ< èy°œÇ®ÌrŽàºÁ Ï­¡4áÒ–ã:"e <'ì[ÏA¯çhdMŽƒ²|Gs[ùM,s -º¬ÃQ´†W†se8gÇp¼øð 'Îg8°¢°›˜FX¾2ÅKPëc°šª¾¬…ìdˆ>×öÔÐÊsxg4ˆ?t­w½Å6n™Î•bcç銡²³Æ>°¿”Œ:iчö¾¨hF#ԌΓ6@•OžÈãêqqp‹$,`&Áب5¤ŠvÆšØmK5è‘øí9;S˜ƒ•Ï„KZþQ™u~Žñ:òŠ™FŽŸDÛçcÄÈ!LÊY³°†b³\ôuR‡Ok™Ûð‡ˆ|{ˆ6›‘ŠÑŒ -‡k¶Ýc¢RÓ--Qå° ¹¨ˆ18Av< àFk ³ä&Ògoz¦ŒôYìO/Ño#´_ˆäŽ­Vz¹[6«ö«"ŒÜMª•lÞéÝ3Êä¡Ü2D­àÀGóÕ`K3êÖæE~Ïz C3¦õ8÷Ä3pÕ²¿{¥r‹²ž«Þ3Äò°_1NfÑr1<ÈEð¸ß”#¡u× ÖE#u`õ_uŸ¹|Yu9c÷ÔöýsI`Eôú¿V.¢ëkŽC8¿åTrÝf\·OåìâuyçåÅvÕå9¹ÑÑtyå]ÓrYUÜÞvql=y‹lA¿s»Óåv5nÈŽVíf&-°ÛSº]Ùí•ÝÈê¤Û;5»õ›°Ûƒz‘Ù˜gžµý%0ϼÛðJìžl6ú-ª—»tLxe®›NüD¤/ð#9Z sÝûÿ·÷î=näXžèÿû)„Æ5Ù´oÉôÜêzÌnUwm¹ª¸0 (Sa[]ÊT®vy¼þî—x‡¯ ã¡Lb±=åƒd0Èßï¼x˜´ˆ”„æ§Ïw…e¤@+î¦ÜçÍè“€½éEZò7½ÈŸø›^äO¯wçœÖ´éÀŽ$W_‹¹í5‰ Jzê *9mzñ”Ïý‚×vE5 ”ý¬² Éú„µýPË"h’žjÊDu¿Ã1÷.:÷¾Š—Ò`œæ2 zû«Àf€YÞþb™ÅÄyEž3S½˜Gw^UûØÖyÅã!à¼" f¸ç×™w^yçÕ@Î+ ì Wä÷Î+ XOÁyU­TÎ+¢ÍœW”@j+#uwr^qýí¼R¿œ çUkíûp^ƒL&‰“[Á'nz†Ö4Mç•Z)X’X,0t^q0"Òa¦è¼jh=œWüª¬ ™;¯@6ê×yŵ‰óJBU6ìÐy•‚÷›Î+Éë¸p^5¹­feÔ{Å©GNÈw‚=ùzòÆ•Õ'ùŠ\YZä;)â5P©¹+‹ç•!\Yè|œÐ`ndËô¾.7²b„óÙp¹¼JíÕßȦÙK¸ï_tgY/‚¬¦å#È›(qû¢xWyE{ºšñ¯h{Í¢´>5c¬6‘·ßœÕ^D -Ms´4¨Íf?Çßœw÷ÆhÅ£u]¡î©¾Â(ïg×Õ„“°t/¢é1ëØ"Z¬²|‹~Ÿm¶3<ÜŒ6ìàe\q|yÚ¡NéK]Ž›Õ¼«Ñ»å&¡a­:Ý#$Œ4?û†åiv—¦…»Ô1ÇOÐYê9Þs¼ÇÇ‹iq|–¹äø^=©cKkÊ]c#2v¼êÀØU;+ËPÅz»;=î7ò°eç…ãñ7ÅÎÊÇ·;uQD>\$ °ˆ|ØÕmÖA‹çaýØÚÊ}O˜ïWµC5ž13À[—tpØæk¼e -ú®jI]·Í -¶æŽÛ0e\ëzµ„˾0vin¼Æ» åË ¯¢Œ-ëJæv8Ç´š#øÄÓw>Gn¥ Jˆ–Þi<NPªúªNʈ^ê,\M®ðî*v\x—ö›±- !,èomî•šE®²p/"t±ediÆÌ/Z4<žÀUä^E®ùgžâB̵W²2"é~+Ð羂nÜ9]ƒ`ºžÅ2/ry‘Ë‹\^äªD®å - Ul¼«¾eSÕëQ B8Äß•4Fóï£6jÅöF-håv-Xø {þ¢¾…?ËíæÖa&¾×BÂLŸN3HD¸ã‹xÚ¢ëhqk%•XÙ,®@¬"ø^ÿ - ^Õ}Ñk7©ÙÔ§Óì¸\Ý"vVÎʱ9¹¬œW-Þy1n:b\šŒ¶;KìJðMØ(öÜ’xkä’VÚ»œÝù‰5ú–.}¾·²kIW ˆêœ5\,ÁH¡Ì8øõZ®¼dã%/Ù*go³ŠjË/€ Økò¨ n…bøü1?<îó9‚¦Ãñ¹¡ùL»“Jt‹ºS%(¹Å­‚w²é\»5 ýÜ–€VýÝ©ww9ˆlJ‚.W! -y±ç -Äž85,PjŽ5m9&J•B½h†”EKMç;PùÒHd¼Â ^M¤¼š8àU•]EcÞ¬&:½6í$içøŸ U7æ»¼æ” žY=³zfu jÛ¾¶ÅÀçrÎu8·“9ÀA‰4ss€ ŠW~§ÑÀ’–؈] µº—h`¼/7Û­¬˜im(¦wƒŸ¢3FM¶óÏ<å9J]:äûTò~i¾ Ù +—"ùãOÐ7h=ÚZ_o·”L ؃™:,K€®óãýît*Ë 5¯Gú:zù4ª—¦í%É9Éù¾ˆhž3?±:¦xÑ9>f÷ØDk™ªš]€ ,0ëC•0N­(ºxÓÄLÏü̆¢çÖzÈéÙha”Ü }Œ¡¸ºù!â¥A‰ùî°ßçwøDt f;nFƒv.3„pùð(ÑZõnT»ßÑæ0¯4iuú}I±§Q96é5S¯'«I’UÁ77„¶Zƒ£iábEYXgµg8Y6U4XÌîÇRÜ-p›ïó¢–w¬ŒéjöûeN;¶ÔÏ*—0Û›‹ŠÔA‚÷RÈCÝá½-Õ¶PÛêŽyJAÿú–ü¤­¼ÅõˆŒiU>¦Wß¼ú¦dDlûæ±zt’l˜Òz¨Õ ÜlJ «rÀ„¹Œµõ7&N«9Ã*H‹ž^‹xôy*<³‡×RQXÙpQ废ðkVUYSýkÐ ôO ûÝ‹Žä‡¦ÚL㙚}¡ö‹Z0ì™Eƒ|‡~èô/Û'}OúO”ô#•½v`ÒÏà¼I¿WË­ˆÂ5]«×BázÎU-ÂÀ†‹#¥«(®t°vvIßÏíbÄ_Ê6!ui‘`QZ€Îê}¸à,ÝÐfìøöZL¯Í}@!ÙaX,òl§lÜ›µâµ ¯ªÕÓ`®ª…œ±šo¬[j‚âÚ€$‘T’ôÀ wÔØ}¡>Æ?áï¨M+¤¬:$£¦Pd˜ü]øã©Àê± ¦›7M\ÆP{–µáÃ:6»»ý/ZS…ñÃtq墓äÃfÿ0{£Z2À"£ªƒÛ— 5ÿÌ󸑹DgýÚ—ÿ“E÷ËÿiÉVK(HÃÕ‚h [:1ï6–¤¼ å)/H‘Ëþ™"¦èˆÔ7±›º["VÀÅâìe,ÒŒ“¡®ü·ÖOnˆjŠtvwüÅ"슿‘Îr‹9½ìŸ”A•€°E»è +€¸çú¦?'Õ… ÊørÕˆ?³e”;YÇZåQY-ÀÐH°ˆŠÖë]±ù+« -_÷!®áŒ¸VŒÔ» &dìØâߊ -vlS/´B›Φ#œ¥‚0×F¹WvO Â_áÚf,<ÂW -§Yj +-GWOc²¬öru*È˯›FAÞ檠ŠzúRÛT¯.¾RXÑ·Jiñ¹• J´6n«©Ä°OOãci¾òD­L^^ñòŠ—Wž°¼²\Ä:•uÙ=mjFê,ɬR’Ìs5A‚S‡bºjÁ©óV¬² -dúË C{üîøêò¦ ®ðç²,t45ê »7Á±QSÆë]±)ÛÅŸ¾^ܱ¸ÇrâµÊn+d*¶©—©¼ãî*e-MÛ»×$*¾î½‘mˆƒZ*QÕÓ˜¶mˆ[®N¶!~Ý4lCÍ/4®m&íámC¼cb#Ò zK¼FnmDpl’ÀFÔå•'j#ò‚Œd¼ óœM£»×Ô"ŽÐhd$âîd$jT$vn"Z¦`âòXUñz¯+¶Å´Bu/^·ˆ¤ð0#IO|n@rªe¦›¼Øt•bSª*„ËŸX0 -U@(°üÄpñ5A±ÌS?U£OcäÅ’š{Úd S˜v¦Þ¡ =Dòзî¨8ÚÊ°¯ˆ[³ÎÎÖ–6}׉Zt¼ðá…/|<-á#S•ˆå󩽦£X²‚óôê‹%ÏÔPÓ’‚dFšŽRP§1˜y2<‰Ä¡3\mt}+Yµú.¶q½[Q¤ÈBpJµýaÝ^ýŠÍ;øö>·Kzñ˜ñ·÷¹ñÆò—‰ªDK…ð /‰yIì*%±t¥J)¬â»Ê´Š·CÒ×ö•5Ñ‹XÀ|*Q¬‰Ë¦¢ç}nã¼u¤pECZK+’}L·ÒR)˜jfVKãÊM6¦NâƒåI¹xíÄGqÚ=ñQ–÷[B5#­ÆDmS^rò’“—œž§ä´LaZ¨$[ãð£Î2U€ª¡êz ]bÎ.6I"ÃIC”:Ëp¶ÛÊiº£8KwP¨’Ž€Èw½&;º  V˜ÃîàºÑÚÆ.ç+‰,ꦔDàM¶(SUÀ¾~Ûú#þ-¹«ú»S!î²o‘ õ@®BÂñÒÌH3q K3⊘&àÔÄdK4Ë;°)Š©?ÉÊbF’0“m0e"eÊÄSª ò)w0o(:tYk+.‚¾ÜD­ž+=Wz®t:»PøLôU{;å®P+@ª‹Êî V–¹ÊnIÚʯ0P‰,&jVEe¡÷5KÊn¶Û.u-‰²Žž­j=ÄbQÒ²êÒ%—G o""d5_P‹ÍÅ¥,<ï”ß ÍähW}½ÝÎp+B–h9Öùñ~w: ò—’‹×#} -}zje,8×)cÉ4Ÿ ?±2–DŠc©—Ýc-e¨bqXÀÇPt"Œ0#g¡NË -k˜–Å̆"åÖz(HÙda”´ }Œ¡*WBÑ"^”˜ïû}~‡ODj¶cáf¤eç‚“Aƒùõ#¨B{ݨv¿£Ía^iÒ,êô%ÅžFåؤײž¬&IV± ï–ØЪt3+|¥ #+«î ²±âÊ{‹ÙÀýXŠû±îoó}ŽOiG¬ ¬jöûeN;¶ÔÏê Lo.jY_f„ÂÈ:¼·¥Új[Ý1O)è_ß’Ÿ´•·¸‘7 JÆôê›Wß”ŒˆÍÜ#VN’ ÓU¦PÝÀÍ3e ב&Ì%œšÒߘةæ ë‹äôZÄ c[h ÖçðZ*ªï.ª\÷~ÍÁJïjª Ú‚^‚Ï äcGŸ{qÀ‘àÐT›€QK©Ùj¿¨%ñ ]¯ß¡z ýËãvãIß“þ%ýHe¯˜ô³Ì%é÷j¹Q¸Ìv{….3àÆf Þ§ —†%PLzÉ— ¥?™èö¦5âɧùgv]”~i-ÚbúŸ,:-‡AF]­ÌJ›/–x‰Ä µÜW¯;_ã¦Ø -¿R^ƒáL†½ &¨½ HI%@ôx,ä -š“›oêo~ÿe)Ðôóµ -UY¦åEÈ[{P ͸©rWÖ°¨r_*nž†¶#ÔÎÑ^l¹Nß°ºÀÕ}pÁ>ø‚]ÍôÃËïˆuØŒ.Å7$å7P¿7‘An%èV:}ÛŒ™Å¹×L,º p1˜{ …Ú9Y -ÉMVo‚rŸ·4êà’!Ôª³¾Ûì÷·›»ßKKa)•Töæ{ÔÙ›ïñ¿¾!`ûþÛ«Wïòó¯¬ehLI°4yIÐK‚^t~ïvYMS„Ãû“{½þÉu2ÃWC®³»ñ/–ëdþŸ–\‡Ä¡\ÖMÕ’IÎÙ͉@w:Žh"C‹tób\÷&:®c76º¼M±2üÔæ‹cg¤Ãí¶üÆM‘¯7­1Jî²Õ£Ü³ -¼¤ÆIjøÖ ôÁIf ‰­ùˆ—ÜÆÜÄæöbÇ»"é Ÿ‚aíxÅѱ0äáèÍ -Ľ%ïÚ%>©%ò+‰*ƒ™òRÜwóÊO2ÕqiOn}°QT~×0îv.ÐïšA‘ñÝ_~`/+áN2·ku¯Š„Y©ßúc(,Y|So`{†âØ i‰¢L{“› a‚z°,¤ ¯,x5àÖí­çç½¥kü²ŸX!]i}S¿º»ÊmÚLq\:XRV% f8ãÅ'}ƒYùÁ‰Ôä²ä^¸Ò¾¥Öáu¯Ü§9€ÜÕ³3ÓË]^îz^rW¶Š&*w­àlåŽÄ®§ëš„„(iò+¢¤uø ƒ”PH¤'gwú@éÉÜáØÅþÒÁ½(–3a—¢•ù)oýgPÔ˜Åëâ@´’†€\3 ç9,ºîÛgø$¢«ö>/iš~Âe¢Š÷Ï8çôqeœò.@ožjw-ŒÌSb÷^_ö©‡óæî¼FqÂÈÝÅÍGz`D Ú#~Ø¥›¥W7_†n Ü|]_~`76k5¾õµúûdâT½úJqŠmêíK>üjÂv'M»£ˆT,¶™úû8\¤"U=?ïïë(P±Ÿ¸›@ÅS JwWìï“‹#ËS&v+c‰åÒï×ÔøýŒ_÷Êý~C -bãÜfô‚˜Äž¨ ¦éA[‰€Nä°'îlHU€W!Uup -¤…€¼8ÕÅhn¡éä  =8S8vv~ýQnÄ#à.aÔðrCŒt›pš’ÒU{½ätõžÁQÌX"Ï 3–÷ zC–®gP!G fÉzÀµ?ÍÝ>O•¸A:q{á G?`°ÊPÌ‚>[§·ØˆþøP×õz"n¿})qU]‘šiçÍL^Xš°™i©JµÀïz3!)„ü',~ L (!qÀ‡åŸj^ÞÇg<8ÿYb‘Æw” -Eú{h0Ï^¦bÖñüzŒ4¤o{2“ -Aî¼xÁj–#M¡fïy弾ŨQœv^ŒòbÔ“£²l191j¹ìIŒz².º–P$sÏ]§P$uÌ)Í #¸åÈ™ûâ ­$Üp"i±'ܶAÆÊnï=Šÿ­»tÜ 9ŸîwGÛÔ¤ïa»zig¢¶hzÏ*íËpä½jÞtTJIPp±BÌvtÞüqx8Ü#žEÑÅ¥V<_IU‡w›ÛË~süôe~ø€Á=ÿèÎÑÖöEkÓ-^EÝó¦£}ˆU+(<ÍẠìŠÃùÒ¹]ñ´œrxÀ·Å›ZôŸð&&/tMØÄ´ -T7óDGÁ0²Iÿ¡M\¢¹ žXÊ&Z [M}¢î<|šïê æI´ T¡OZŸ]ûÔeºÛ4 ÛPÕ–; ®Ÿ$èg`ör §8ÜZ†°Ô¢5xÝo ¥Kp±Wî>NôçöŸý¼è÷,D?u4ûø¢œœ¡/ÑoR.H¡ gw_P"ÈI¯ >A bANÇ>È!#Ùà:¸.]Øšº845„aعie…KÀà¯üåpeFqyºÈ”Å ¹Fºnx ¢™w^½¨6M×è*˜¾¸&ˆ ëËRwíþSo«ÒV—‚húâÉ`ƺ ‚rm/+}fþ˜÷ùÁÖႈÝÒ‡*ïTà5 ÂîWÓôš&µW¼Ã{ìEÄ_®%|UŸ¼7” Z²XP®Ø-P^„™¨µ)MRP|©§¬+Ÿ¤z˜Ë(›fJŽ)„Ѥ„úëQ½âs¹ *—„K%šÄ ñ´õYηÊ8cBiÖœÝ ë´ûź4˸$A'®¾roؤ߯̓¾'ý¾H?Y-§@úijMúb¶‡w ] …§âka‘®j¹XR)u§6Ô­ëY1ÒGµý&*aö”XiÞKXó^uÓ¼G¾úeÁÅÊë_¸ž\|-~ÏÍö)¤Éj -üœÅöJ¹Ò ÔÊÇõ\ §KÕrÍ—Õëå -¹;ì÷ù>=b?æ‡c5S5eCí+fÎ:órE¼ÂZËæÖbܰɸûm.f²·©&]^¢*Ïè£J E”·²£Gfä¢ÛŸ¨elM!¯˜ý|÷ëÿýùï¯7éµæ)HOµ£+*¡¹ø¹â Þ -ÝòÖ ¤TÏ™|«rZhÜê«9e¬h _¦sƒ.ýÊL›ŠBVUäSK ¢É$ 4/^Æ%jgBÌ–.Pš#)4G&ÐŒ ø7ç—ÛÝ «\Ó*NÕœ>Sg£àºú2oö¥Rµݾà;r£jep]¡E“4Í^µòWºV€÷ð5ÚÐöØ·ô·ÞÜ3Ú^Á ‰S:¨ ¤ý„›Q0jLT­ŒjŵŒNõÄHËÒÊ94a¥)\q'`¿JcëèêX0Nt¬¤­c p†êXÌŒjÏ'=¥–JVuÖ­•,`éLµ,Ñʵ,ø›§f©X¬_5‹rM»©ÅY³¸C¯g ’7soÀèÍìHZ¶—]æ÷ Y¿'~½êÃùˆ•áã›ïÉ_ê?Çç›Û|߉ÜÍÉ•LÏížÛŸ·/ÂIp{šÙs{¯N§Í<œSåi#§ˆ¦útqîîiݹOû\mü,æyèd3'OÞ'5ì ŠGk º»† ¯2jqp{væQ¼;˜ul«Æè™ðï³r4S»(_ÝmÇõåÍ¢Þ,ª`¢8„£k…fQÝ3Ó&›hÙ&æÙ7ÅÃÖR½¹ d8 Äj˜î6=–"{Ü Ùµ/Š´§Xi(LÆWEÄÝöq[$y mH5{Y{¬ýEZTþñm}‰c$ŽèUµjr%#º¬««zµÊZa6MªUs› x®Ç&Ä݈èŽÕ¯˜iMôÎHkíVS“E”+dÐWÌlÚÒÇÔ¬Õ§á”e M³©&¡¹ m‡¦ÓÅ4FéÚ’§Sž§KËi+Ì_™1ÛÔSµ§jOÕ.ö88U§+TÝ«! ^©ôzˆWb[7%´3”)ôíþrzïP_&ý9Q—™žåVHõnx½ª% g< W]r,œ¼úÓ÷ôÏ¿ž=ÿŠTe•r(U1ê *,°Ð”±ë°À¯(wS”3E¹Âî¾ôd÷——›íV/Ñ%nþ¸5IRÉ?ãÂUÁIÅC(©x9º¥.1Ñ…j)úíëív†—s)Æβã»c¾A ZöÄt„)1h5%€9ƒŠ9ËY{Êì…2S0h§Ø?SeÍhk­â‹$ª£ ¸JáôÕåC6Jä“ß7ª\­¾œ¢Y ™ünÀ¥¦ƒÿñ¥T„Ø&’4èL$I -Þd$ Õ‹Ð -Fÿ»* ´ô©–{¤ËZ`Cúú‘ Eÿˆš¶-«QÍE³=iÑ™‚ŒÂ?7)OO“¦§Àˆžž*û$™ââ}µsd•‹dŽ?ÌGI,æ#F)Ãÿ®´1)O)u±˜Lsk¯‰Õë!×ÀÔ #U»¸ewj-ÏF+ ü…€3ÙE g*cCùəң»‹ñ1˜ÚŸ¹ÆÊÜM«*#?§išÄŒgé‰/h0¦É. -•ð´VY®ÏÊgsñ½} ßùÜ\|oNbJßÛ Ô×Åwµ&µ“™Þ¼2Ï&`<¦Š¶®Ê'/|KRPX¿Q—øwv©a¤åláՌɪþêšBY*2sö£€À¥|¥ -Ȥ"'Ÿ²’)ÕaH¤[MD¿¨Y›M:³bƒ£Ew:ÜRZD¹°ãÁUÁQ×Á‰í²“Ùòp“"¶oNï¸çMÏ›¦¼cð¦Ä‘$àÍ>ÃY”…/N•£…˜¡"QQô—Hé/1£?ΙñònópxØ!ìÖãÂÝ9¿§DÂuóeŽ Á˜Io/˜g]h‹éth%"m\þNvt‰½”í5/m+‘qq)@Ów%HCcNÎ5 MJÌQeË×äÍ0(Æ«™‘Å|φ×Æi¨Ê o"7¦2€™1›-)p”¼ÈÍ R.1„X¨–X¤§(di(X(…š©X1yˆ¡øÛ ¥rB嘛ÌÓ·ºÙÄ~CÓ¬:Zi‹7wm£M¸Ìƒü ˆßË’wAÙnSÎvë˜x§gÍõÄë‰WI¼‘êz|ïÄ ×zÖ%ÞIYuŸ'ù -í‘ K¿†¦_¯îzu׳®g]¯îzu÷ -wlu÷á°Í%eüóü3þ_©•4kúK»g‡‰P3ŸÈÎÈ€ùÚ·p柒po¬³óoèßÿØåY‡çôo‰û4^™uw–úN£âÍqO¢`öfû¯%·uE›¾,'9|è¨Ð›J_AêM-ßÒ”&ŸÀU…+c»XÅvÕ‡ù-)0Ìd!½‹@N8&-üAûÞ¥ã²?鱦 Aº ‚I@‡dŠˆQŸ9s,ú’¿°]@™š³Ùß?`•ˆÅ)™wpzæÌ)¨>à(6F[Y#…`±gíÑÌ®êÛ­IŽIÊfbò5v^ºKÚ «p!”"”Œl ­Y›ys;à\ü†¢×¬Kz­ ðÆœŸðŽïÌ'söÉœ•ÉœcÃdÎÒƒ²À‰6É6éœ%Ó?Ÿ³túGc“Ô!Âx ó¬! gžóäÎKðz–Y”‰“(ü”õî¡ø²L•‚¦rEyrQ!Ïšv®,pò:#F&•&ÄGŒ —ºÆaý” "úéΦî’BÇ+؇¥½‡ -ï1ËnÒ›Cè=ž(Ÿ Q^¡~–$ŠôZ=’e§øP“eŸŸ[Ô'Mû+F3dÅt&PbZ¹`}EÕ±@­¶ú“«„{¦'}ÛŸ¤Cý/»Ãz‚°ŽkÉv{AK3à’ƒü~ Â1¦¢á´ˆPr–•’Ó H¯æx{à«4†cÿê÷in1˜¶˜¤vb˜Wröbµf&Ó4¶—KnÔ\7yJCè¹ eÓ/SÞSƒ:Τtœu¤ãÝ 2k*ntÓ‘‹Ù^Üq“qÒŒéä ظú½¨yŒvÎÆýQÍ‹üCb;æñ¿—¡qDŒÃ¤Ypk5§œ½jpvýzž´¯…´ŸyÆÅ4†ï£ ÈÉÙÂ’“é±³ eì~ªqÀ³²!+ë¼@MMCѲʉ§ËZv„ÜŒŠ±¸Ž rçeÆ}[ìyØóðóãáDqG}ktbÇÃè¿)áÃæÆ;&‰<'›r²–eôEï{#æ÷‡ãùîr–TÃã&{A0v³C0r|»¹Ëçåãs\K1VñO}ó´´?‡vêÎ]š´¶“æ :°V—+/*;Óª³ò¤0ÒM˜þkÆ]ÖýÓ¿uÍÓ'sh8©i˜y_höéš•WK9õr;¦Ý¶$;ã=8mó/îå*é·œ¿ròéZHy´µöY—ã–mSÎ"½š™k× Ö$Ó hùô d¡b°ÍûZòjÂñªM‘B båú<±zb½"bM“tÄšEÖÄ:jø³œŠešìõP±LM3." -ºÄgÍX+¯Òz•Ö3¯g^¯Òz•Ö«´ â¡Ö…^»{ tçP³½itéDÁå:u¢çf 0í_Ú2ãwz{+WnT€SvÏùr‹¿±Þ\:xùËhj?ó0rl¬ Ó‰žŽoéù(Þð×_~ûÎóõùÚ‘s7TÒqúYãg¼U¦ÊÕi¶šW/ôÝ´ä7ðØ8ãJ]®PÌkÍfZó²“ÖÌFßÊóú”Ÿµs/ &oKíî22…1¨*Gº$ÞM5®’3…õ>ÃëÚR‹ÑV*)ùdž‹pÁgfª;òÉ™|r&Ur¦6 “3™6‘Åæ^‹œM³?}“Ñ’ö–ɉÃýËé|¸ßý·;³ -be:þ2¯z¶Vûª@©F—n”¾ä‹´·ÛñííL­aƒO^rýòyÿP×?"b˜a9BÅ-âtì` àmñ+ ·­Zz[IÅÏ"„×[ešÞJ¡éµ7™@ÝÓ¶äÉâ}—@¼¯Pácc™VÁ¿<ØÖºbpÆEÙãÆr*?ãu•ÇƒŸs0ý¯•±QŸæÓþ¬#š`t×Ô_žÇlƒäoúÍÀ÷¶t²6ÉXã„ÛÑ §JœU›Ü’ÿ'˜Òó¿ç[þ_N‹ÿ\ùZé!Ÿ7ñkç ™6’…wË )ûœ‘½Ã¼U‚ü‘v¾%»g ª-“XñÜžÑ *÷Ìî5{ÏìOÙ#¸þÀHÌÝäíÊ콦¬‚xZ‡um<- Ç2ÖÏû È:oþ8<î?­Ñè÷/7Û­f¸â±Šªª~>î6·—ýæøé zjkT®Ñ鋺EVS¸:ã/ïð~¬ äËHj+`£¬~-þÆFY¡1¿/8£n4ä×Ûí F9ac|. ûî˜#Vfx'Wã¶Ä+ðÍ'Åã+fÊõ!:ë’tàÏ„Õ]§ÜÀË -v±»&Ë݉"VZ¸±Þk°26#ÚTnm`fj`>•*ŽÁB§ »u „ —M‘}Ckýä¼.ûb£Vv…˜m8Zçߨ&†Û1,‡ÿ)U­ù[Êswy -’t„]DÒÉjq* bœ8¥€Œ»üã©šÖ?п~F_Œe`„”Û}Û.^ŒˆzÂ]¬wäûbüææY"ÀvwzÜo>ÍRü¦ïòuP¾ëšôQ6BáÇ‚< -_{A‚Ô™¹Xç&OB]GŠ7ª÷Å%ú—µj½² `Y®Ìæøî‚g†øZ ô÷õB°ð_h¿´û âóâ3Äô3”¢زžö²±g~& ŠO½ù¹èÏࣦxíl<œVÐ99ia!Ú/ ?‹¶ðSîHÓsPh©å)É&öqs%8¼§¨jP€Û:HÀ4Œ‚à8jà!”“(ð_QþW“kÿÐ;ÊåxõœJBïì&=TI©>êJõ2Ǻ”?5|ç—xǣ#°Þ‰aÔ™»eäÛ¢±i„ð r€KµmÉ…cÙX È0æ]&‘æ:e.òfñQ¯!§ŠÊîîém¥EoKéS¡LIž"‘ ±ô%  €œóÐ*ö:ËI?gB‡u{'dÂd˜(É°ôìZPaЦ'8éƪð»#ÂÚQì‰Ðáµa¢ŠürN„™>b ° AŒDk< JI0H°éa(ðí.ßo×—ÝšüÇÉ‘{÷ðûÀòóF¯\½`gLÌuw&Í– ˆI³Eg¿oc®Zd‹ª…5ÿ”Ÿ‰5Ö~ÿö ñ*âËV¬ÍßF/ÚVPѶü‰ÌVOïÍ‚~ ÊKìÓ¨³ÛKiã&ochÆß…¹6Ì PM©EÒÙ³w£Ž×娤 #DZl'V'PH§þ’æzÍ´éJ‘Èr01wg«»‹¸\6w¶°•³…ƒÞw¬Â-Njq% G8‹ß–¤C”X×@°vü—E¢Ž8ï^…+Ùš›…x ®U x„'í˜p5·^§0.É >lëZö†Ï9r•q]±À·*L;¢mJÆ'@FÉÒp,e–IŸ]Dkåz×pfR&•jO³ /58)ëLIÁ¦¤D²®Ýè¨Ê¥IG¨¿_«¥÷€ˆ ¨þ™²Oe à×—4*¨\bôV¹Rä¶AmùdBìL تÅê=H…kuS»œnú™nµXÜ:ɘñ!èl}tì’‚4 yɪ]ýDàïSŽëõ¯Ÿ…ËôDÖDúŒ™»dz¼#štsB¼ù{Ñí¯ùñþ$#ü°ÝÁ|Ã|_.„gûçÄöx•Méþ~z\Ÿ©.{¦÷/FYhþ+&zÈëþ¶º¿½àHgHíÿ˜Ÿr—êÿœth'$0]8I-•Y+Rp.É;Z˜o«®9?jüK®ÎöØ›·×3úµ3ússU§i<^wL€Á‚ÔqHp.žÑí]/¸Bò¾èg¦|I!I¶ù1?<îó9:Ň â íÄÌàsN*ó…`f&j žAG­œ¹ÈC’®~M»{Ÿñ¬N`ÖFŒ¿E;œj™44f` ô oZýù¸«!ÕÓ+¤2›˜YñRÄ̺‰™MjR1³â•ë+f–àùÞÎ{Ðqƒùgü¿_æ´ ÆIë\à -·»ÃvûUñ‰æ§Ö­ëßJ¼¬P«yMšY7y–ƒ˜¶ýÓ¿±™ -)òË~ÇŒ}2KiP½)?¨ô¦r|þ‚«7]ÆKEÈRµ#`šHŠ#+`ƒ€°9ÓX7ÁÿA3УfYTW›ìõ ÊúM¥Ê·^.GL8$[‡ÔÃ8 ô-‘Ro–Áo5±4¥{A–(Œ~쌺™ÛJ“ꪀó·—ý^â{‹ë´¡DK`ün¿¡³>7ü»ÜÛfÊ9廸ÜܨžX<±`b ‰q¬ˆ%ŒÄâ0LEL²˜”±iB\–$«X ‡PJ¡)=¨néQHm@bÛÕÝi‚h·h¢v¯Ñµx"é1Õ8úÇÏÕL Ç3ºu -©¾ž°“¤ã ÓL0ÓžÙ à–¾ÓƒÓc0õìß‹bÁ„Ù¿‡Oó<ÒqG1\ -Dhþ!¡ÍCoAZ˜·€A2g‰–€ Ñ3y<œ7w‚xÎh·v‘ê0†–UÀH‡í¦²”I 77Yœnã‹.tÓ0[uëO㘱®<Âö¹]‰²ÐÐÉ >B—w»¹ÃA4ÑóJ–¦Oqœ¢­:o!;§êš_Õ~žB¨÷ -“ Dæ8×Xü>–f¦”mÒ›ÛͳˆÆ™Ê]Ež»ÃPʆ*Žó×½}éUºPx:øÝ%¸Û‘Ê>L?éB@?ìÝÃjäifl¬ÜF¥Z$©åªýºWÉ1}ˆü€5öª²*X§#}ºËÿ—,`{ÖR—7- 3ã‰L^ Ó ]N/5Ÿ§KO—é2‰™yú¢Ë$êB—}&Ùk‘Ÿ,ŠyÂä'I¤ʹ×z ÖclG È´îD€ìóMþ b‹ -Õ`˜[”5—Y0}úc¯ÙãJïÜ5{’ù‡ü\ƒ |¯ó»ÝÛÝxïÞÓ¢§EŸ®&ÅHq5G‹[ŠFÃ\pbØæD9&N‰ò‘ƒẌR¨†ÑY&|âåí1ßü¾Þî~×KG.WÿÆÿûeNz¸Á=˜äƒcúyÑê‰I5Y*Lªz/e©!&ôj³Îm‹*êó¯øçý¹r£TÓž -ÆtvŠ;æ¯ç¿g¯®àë@läY‘¸&¿LzÌÔÌáÆ &@ü•õ”¸7äÄÙTrÆ$Èž][;j½: -ªj™TÑõ73-›€Lú´¡¸5¨uI¦hLC?@Ciåê##ÛET;£øñÚ»aàGãk5EòáC>ä!K8C¨8­šôHQ™˜4l©I¦1zì‡|ú -ÿ kR±²-Ö›W§ä¨ÅyØ|ƒ,$&zKý$(4u´GMõ†ÊI{¯˜xÅäZŸôª˜$p±H™b2©°Ž§«Ž0AèRÎè]ÙîNøstáÄƓƤÈ>裸\®9 -ÐëÐ"pUiQ ¡qU‰è0¿ýÀ^QÚüsóÇß‘8¼)Q&Ä,V]5'Ù=[{†%{ÖïEg|:¾¥;¹xÕ2Ã'×É’«£t¡’; LΚÙ"О™.±ªóœº'V‰ò&"Vz-3JÔˆà©UD­ò×ÌÓ?·^÷»»…ÚYvÐdùÜ8ÈÀŒ¬q¬G³å„,õϸ¤7¶¿VšðoË_»k¡à@ž+'Ë•^UyÈÆPDáJÅR¾,Ï› ;}˜ƒëISHš+%i²ø×+m’0Ë2ÙfGæÄ}Ì?×IS5".ï ¤~²ÑQW`àe¢§£¶ÞÊJ[McmµLœÒÌHû7ûîôB0ZŠÌs~ÿx:£ÎJn3£ÚÄ”jË2=‚u›ðÊø3‹à{za ¾kbŠCV]†Æ¬Šð¿üû+òC=«òç?ÿ»˜lcë ÌÖJ¨ó­W™«BW´¹¦m“ï>™+T1a¬LÊãYïÆß]ÙÚÝ Á8ɪ¥¥Ó×¢åÀ5-{ -öü,(8 G0ùÆÆ*lŸXJ“Þm˜¦&*»ê§ÒDÞrv×òÖCGhãAcMóÁ­?4Y±›šQBt6Óq‡’[o½¡%ÑÕoå¡WjàõÎÐë2¢ÇÐ2ʨ‚oÕíeTãa¯&]´ÃðÿíjÍ-wcÐ-:sdzœL&Ñ»1½›¥o´ ý)ºî`°íç"…×G¢LáCÇ® ßî›jqԯĴ‹#™*pòÖ]×ñM î;7ðVéØË·¿?lÕºrÑø76ºÍ<èàVcˆ#ȸ Ýåf`§/kŽ;}B4zÏ*ïÉ_X]˜¶ùÏç§üáòW|5µ¬JÙ*gð-欘¦!»ãÄ »oùΞùuÉ Ò¼øM[\Å5 ´ŽP‘ Ö%Ë¢¬ôQ›Bóýš¤Þâ9¿.YA;£OxGqkñsüìœ}Ìë=¸(b ’~Bgx.VðŸ-åul¾#«^àøOh\– ð ðß~EØõ:/’´ˆ§ÉûæýápÊgø‚ß3ú5gTóñ¼àyÁ%/$†·ä à†ƒu#ž ª>l˜Âd¦¨jc¶°ÎhMò 澎äAÔ+òà{—<ʹŒGxFäðäáÉãúȃ=l]É£ì£_ò¨gzäÁ.läAÿí7ïò5õFcYß’L“ÅaSÒ iMÿ÷¦x¦ÊáÏõDŽí—¢à~½òŸ&Ä#ë… ãŠÂ¤;!-£"¤%Ýa»ZÔ·Ò=g‘”Ϥdçkú•¿ÞnEižÑO³j|¸<'Æfî Š~êBd²æéÄ_€a.nqµÎ¬G÷V°l¼çšRr;,g³-<[Ð=‰L¤Ðhä2E4õ9<É:¤™ i*Øs09Ç‘ðÀ½Z‚Ító¦ `ØÝÕžeå«¡ì Å2›ë„ØóÒÆFÛøá:ËÃQŒ\ž"ûØ.¥DyB1$…nÁñ+ ,¥ÒÉÒ‰t‚Nß½Ž\R´«¸·ø·)¤Ñ³Rò¨{¼KzÏRh?š½ñtå ÂGdêN LÒŒ€QtÝ·h!âbÈVï,60oÂßth1Ëc‹iªÈ¼ÝÞO-Ò`x…‡ ¾¡Ñ€ ,/°Ó¸*I¡½„rAk-årøÕœ¹#¡D@žP%×õø"‘Λ»ó»úIC ín¤Ïc¨°•¸žû•à\´iÀä§+ ຯíÆî5Änˆ‘,aý®tbÛÔ[¼x`$°›ÇH<`ÅP<à0‰Šõ4®O<à–°“xÀ¯¥†xÐüj#‹ -òI[¦÷cÄ„}ÁbÄl0Ù0WÜÌ/›Ž—í%è-Åùðïóϸ½FÉ2ÒØa`L ˱KnYŠÙ Šž`ž=û2e§pÈ#[žŸ¡}BL£¨¦ô®!êv ’ÐÅ(L:0 ¯Ë@ö‡ˆ‡§~Ìïw8„þÓËwùyŽ÷™ÜÏ_ƒa4EÓ9nJZÑÙC°…ö÷ys/7Oè=ëBD^‚AÄ™ š„ô‹""ÓŒ~:‡þôO, iü Íâ4‰_™9øÐHè¾I8ŸŒÜ7©s„¾IÕö¾IõäF¨µѽ˜]À5 L¥RN‹¤ù2Ç u€ùÓ²‚áîAQ{&ÌÂ13´B^Ö„¬‡¼xÈ¿‘Œ%°ÄÇ"#À˲´d\'?A»âÍö_§dC®&ä/ ¸ü%ÏÔ`|ežÆxÇBrrjµ±Û迬ŸãCãË$!AûúÏä¤ZÜ×Å…Àéa7¼™[ž«ZÀ§¯(¿†Ë½«R¸¯Í%ƒˆ#-q,^{{ïw÷Hõ™¿}›ß‘ÐJYéù"Êæ>ßî6sòàÍéüiÏd§"\“?~ÁÑ7å_hÿ†å/H·MÓO˜,ºgã€?YØŒ.êþÞú&#öNmÄ( ¤;z¡öüŸß‘ŽE÷i18â@NòÔŒNÂÜZÄ'Ù¤}Ñ÷6e°^#9ÑÌ™å™lY1×ÒGqš_÷}’JÒRpƒ þ.ÍMV{>Ùƒ.L¯Ñ -›b ̺\½vox„Y™™n•e#Sý³Úäæ ì}{䶷˜¬×öOÖEï[î þ»VA2õ—‚d†n[Æmå…Pªˆ3}R+˜:ì“tpRÇ6ß#Hw#sÐ.O þ7†°?Ê^pÖñ¢ûýUçkÅ9;YnBI¼P %ß’Þa¹í]ú³M¼hâEÑd9qÑ$X¬œÈ&%V‰ä“µÄbJ¢2/`î+¡ÏE -ñ–D£26¯X !N¥šøiK5ˆW…R “6»ÎJ*à¬L|'Þ¡]fu·ÂKûJ -:\³Vö»÷ïhcYªÄ™ïÐǃ…„'øG/ÊxQÆ‹2:¢L˜N]”ò®õ ÊLÊÔÒL¼¹Å¹% : &=š\ȘêÀ4M²hÈw’H#]6‘ŽHaŸK#ávš4“Cç^2ð’Ïá$Œ[ˆ S­šœuà‚´&Ñ[fÒОã’i¬§ó|,7=w6€;àô Áà=IxšóáõÂÏtOK5a¨—muwÙ™š’Œk#Eèõ_Á*Ü —‡çuZ&Øh¶¯ñhß>>ì›-÷¶Í÷»’TÚWr1Ú%%=ƒ·k»¦ð?•2–o"Ò Iô)pJaI©S:Õ"ÍÿNA­ FÖº û¾¶ön@±“–Õ®d-®ñᜪoK!%âü¦"ÂèŸ/·ûÝ]›wg4â|Z“¡¸³6'¦Ý-ÀIƒÕ.É1}!;j *€ñÌè™ñé1ã¾ícÏŒ™ô¬Â™Ñ|é’#îyRµ®£ËTlì$E²å”°¦}ý Á\uÍãwâjU˜ÄOÌqóùgò0yòqy·{ø2çz:¡Î^0ÏÖ´ÙÝÊ™Âé‚ÁbÞÊWêèM+Ø)–™úGBÿø !vŽÆ…s?6ó1¿·špöOÜѤìž)Fz~©A>ÛµÙ_R32}V> ‹çóò…¦¡*#$¸mäœÊA ¼&`ÝÆG07'P{8Ñ2X^ô¢ dÍ·ð2)HW±^ò”“Âã”gµÒ‹Y¨¦=æ§Ü’jù. ¹–yØÙfÑ$ÛÀ”lɼ:²m&gÛ_p×0Ý¢nȯ|™ñ-ÁÞ»Ëé|¸gtÛ$­éS>×W¯ðl~8‘?œéÁö,îY¼dñP‹ÅëÞ¹&t_N—äam|8’‡‹3k’VÐ|E4½ñ;R/`ÕÞaÙ™˜†;ŒÀéé«KPJÕ¨†(Ü%‹¶8‡‹¶e@XR*Oë»Í~»¹#Tõ„s³þJ50)fc"ïŠÓ«0…iRšUæUc!L;sܤŠ™ÃáIÛ€pXw*]­©ŽT(–¸³;ti©¹zÜm10Þ–ˆÇ*UL†©uùwSGãSfž Á<屟,ïdŠ²ü®¹hÅà„€v¨fSI™‡Št;DÙÆkÈïXðï#Õ;ÚË3P2Y›ûI%[îÝ5˜¼\‡«LÍ~Í ¨GN¼I. W˜œ«yeÆ”Ómâ: áà¶75ÁxŸ‚G¦Õ,ÕhÄZ[(j$4ÏkóÕ§s%›…ŠRH«@os{Ùí·T¸Þ'?æ4 -ÒF6çËi^<¤¶ÇÈžsbY© -ÙÃ3зÇpÞ”UµÝ ²÷Ä/´ÇŸ+ýýô}ežö•®Ìuð\í3âS¢°ÏÀº±Ïˆ&5)ûŒxåú±ÏÜ#tÚ=îó"Ç™·‹ÓFÅ eüÄNÁ‹¶Œg¾#\7/¯i¶°ŸŠe47Ž§œq÷ëÁÙƒ³œ!8+€Ìµù” ,+¦3LV.X?€|Ì?ìðÎS2™LU€>s*LÖå¿uÒJ’~^0]ÒF†a ðvMœ”º‰ækt‹YbóAÖ°MËÖÐþ%ù 14ù óÍq¿C]ÎJ¾D, -¨p/S Á½‘]õ…çgšRÈ@ÂìƒIRD(’U¯X ¨0ìò¼M%å±Dôdµ%¥Y{¡<Þ•-¼üÓDS(+"èÁËQ¿§qEq•YîÄú{H¯âè}n§7WűC„]…Ô°«ýÝUž]Ñädz%»ÒN Ù•}È »f–ìJgÔ»þBz‡Ù5ÅAÁøçÙùà˜`/Û'XO°ž`9‚¥gÝ’`KÀð{u[cý0{>nN{ -w.Èvþy¿yxw‡ÛvâÝV Yv¿‘³„³F¤†Ì˼S7Æw€tHø×úc€|ŒÕÄ|<;¼mfÌõí zʽLb #}Ħ´†/Oh7Î^.í9›4(§¡ K­Èø·–Ç5¤»½ T KÒ H±© é,Øï1—‚BŠ…¥LPè)#‚yâD¿u¤:n¨™ÞWø _c”¦ -_#0¼>£ƒ©|#&ÚNä›rQ|³:,Ó$Z$æ¼l_ÆÞÈ>/Ã6º¡K°:ñÚ>‹o9ÞsËâká7n…ßxÊߜΤü¦‚sî7Åoû’BeÞøÒjîÞÏñÏF ãÁç\dŠªCxú¼ÂÑÅŠ²Åf¿Ûœ -¹µ"›0©áCÕȪ„¯)§„§\Ž{:ªoññ-½ŠÏ‹"ø~ÐMð¡hRãçU×Z9çÆB³%ñ€ áÖóÏ»­~=±Öã­{¤Ým€QzßÚÉêáwèˆâxoäu0Ž§Ž×™ð<{  -È“H‘Fuƒ‚Ȭ-TçÆõ$ã:9Ø †Æâ2fõ–r3šÎëJ/g²«éôZ¦Ø€„âUxÛ‹‰¡|‡ûÃ.ÿ¨M#]¸Ã!I$ó'’•ÔbŠ¼äùÛ/?²ˆ ¥„‰ŒÁ\òüý›¿ä‰&ø÷bÁ‹Yýž:áæ™e²—<¯:¢Uf¨¨Î ÿ/¤}Ö¦PžÖÔÆ7æè.a?öœÆm#%˜ÓöÖœ¢—öœ¬«°ë½G·®p ™l$“0Ö“ -ÇnoÕ̪Ãæy]«Ž¥dWR±l#úâ$Nв£õÊ“³íÄ°×u¡ØÝïØzôÍjs÷þžËØ[RKÕjµ¨Dò@ɺ0ÖÂ#k±…0‘/s÷¦êýÍÿÆÿ…ýœœÏiÊ>Ív7ûÍ]>Ã#¡7¥ŠØ Uxq~sÌŽ¦›c¤»¾í!âÁ'l 1’iŒžžK¾FΓuÕ Z„²6Úòz=Újþ¹hM2À–ÿ’Jì­.Úå:ƒîBzƒI_ð]DÝÉ[o¼Ò^:Ük´ÌòÛæ¸K¦ŒH¬söFeäËú‚ÅTŠ{VÑ™Pì&®dYÄnrŸ¬ˆZê)~óz¹Äª, ›xzT“ÆEB™=RNˆÙ_0%€0åÇZp‚U fh® (ýû@A«7uP”[KÕLx •e@ÕßË©ãCrã!€h.þiïô¨)÷í.ßo‰ÅG¸øgeÍ?Ópß_˜;ƒóÏÄ“rÞ†´Æ8/Êÿ× æUçÄúaW)ËøMcÿ–vü½Ôæo2iØTGúÆžÇÔ«9T×?ð¨Å+N­B·'ñ‘H%³”/š×Híî†6>½aþ…eriTKŽ’Ý7$E }>\Ša+q=‡°ýþµ@ˆb™TËŒD1ƒ¤o$‚X«‰Tœâ[»°$/…9`X;i(Ó–†êñ¼ ÙÛ;صw„6dÉ~ ÈqƒœËæÖcáF7K–ƹݘzýHe¼ë5#<ÞÑ;ŸóÏô/ER•Ž*ïËa¨G²UÕX|JüBúQà-D…e—høžqsó!ÿ8£mI%9“œ6Å`wÇ|ƒ ‡1ܨ¦8ÜkÑëæÔ€«þËJÓl¼„¿ìßËeÿf - n[M•p’ÕB]àºyš;\Fz'ËÊ.™–˜‚•½æD†ˆ_,@ç{Jïd©4–}ü[KÕô×RPéû|ÿH³Ñ?´(µ˜É̃Ë(n[qdÖ=2)’¸šƒjQ`$ -e©3í— ZMþÂê!´Í£¶bäé³÷õ'(rÈÐ>f]ØÇZéá/Ë;PPe¸Üâl…½«°âês«ªðéõªYõ$E¾ÓbªW¨…¥†‘<Âóè`Ô@Úll£Áƒ¤ebýK´(Ϋ’²”qA2«‚2p]Êh´†2ªA¯ˆ2˜u÷”á)ÃS†epç]EUcG”Á >)Êà¥/Ê8滇mþ‡ºª_K*žìf¨ãvrÕVeG|=™†¾mŽ«öÇÀeÁ/E}VÒé7tEA.ùfÚÏŠ± %x‹0ײJÆñ7²ü,ùeÛÈ0ašþÙ®Û®­âi› ·šÓ›À•[í…t~é¶@y0óMCGªÍ¨üî½³#×”g%í§‘´Ì·mïÎô—Ÿ Q”Cê´ú½‰ÈËû^ÞoÈû¡aždþ˜‘s¬oÁ ì8CåÐB?ÿÒ x¤ð˜Á»®«@ÓKà,L) -Àt øk³ãYA?ŽO2€þo=Ø{°÷`¯ö±©q8ÞägMW€I§5äøXÀ*ôyE8@Óö¯iö’ðxçoà÷à9 ”Ç[Ÿ# CNŠÊUpÏïÇóÝåüú»ºÄ žÇÍ”ãÛÍ]>/ŸžßoЉ.ÿ€ÐîüG:Ýà~µ-ýŠî_4zdò=tO˜œ… Ť­¬lÝÞ]ßCù¡™ª)e÷;ãÓnnÁ¬nKãKçÔ9°ÃO9“Wü+›ÒM¯A¾a=M<9uV5ëpMŸI˜¯ó;#WÅ›®àJÛu8ik+Á¤·lõrÀ€Im™´Ý¸Ÿ7ä!á½Ì «Kž -ÞÒH!"Fzc¡Ä2ë„íÅ”g„0_Uyl0ø1Ý&‡§ÅNZi±µ  ûK‹-ò_ï5÷ Ü4ºv& -p»‘–àýÈÌôëÉWBK0Ý«Ì—•D.x7Eƒò—ÑD~(æÑA#]ñLjÉE'{:¾¥'§xË.‰&¼|ð$ä]Å–D§°?ãM4U©!C/3!©a¤®µ—ÞHe!=)#>TÀç¥)"m]/2åÊ~… ´ Ý x¦¨k1ëÇE˜`œÅà^m¡ ˜‘=ºÍ›6ˆWV¶»l8«¶h·»¼­ÝîyüšxÜ_çÕ‹rÌ`JZ©;} í|hÀÝ„›QW–îÓ?²ÓZ»‰d)îôqwœ¥$öþ3þß/Õ¤¤YãÉ/šm+Êê®ÆÆ)4IÒBƒ³Ô§&.˜}ÙVEI4ûk²@Œ*Ú"*´!^׃K£Ù1âÜ]NçÃ=ÃL  ÃC¿zEèëêQËú y©{øOèÞlÿUÂvU[€ä*ñ«²»+ð{ßÒ@鎚*#% E%”j?À•梮A¬ âÿ¨tÀ -lt?œÈ[­¯~[¹²W¿¶T‰ãÏ%‰57rG«‰÷S9¸£õétÎï_Æ‹ ÍC~š³?AÁ?ÆüÁXDň­úW¿=l.èàwÿoåÔ”Ucaëô‰çJÝaÑ€èâ³O££N$Žmiow ´%¥¡-U3›È–æ€ã¶´—À}\K €‘#-Œ œ¾€[ŽhpŒÚˆ¾"•gÛüaçÐ#`oé!`ä £É!`Ô/ÆbŒµ0vˆ€+5ƃ#`ÜF@|\6ïòÙÃá<{{¸vPÖÙAw¡@›Ö8àbHËù÷WÄtÏ”—úó¿÷™V¼~y&qè­T.¡z•ƒÁ•ïËT<Ž ÆçéÆß¹«I”Á¶Ñ¨÷¡…ä´®¡™˜|ø€£¾èktÀÉ-‰MÄàÛk -ZRI:¿w/>{ôïËü—4› SˆÑËVdš ¢=èøFh!z5C@±.¶»ßîÚŘ¹iñMT¨Í´v!cÃ÷ -ƒV¥P2ì4‘}çŸèì“önÅçò|ŒŽÊ’Õ“/;“L¥“º3MG0>+ª•L§ñŽø ÍsÆÌÓ¶lÇ—c†‰=uç¸yKñ/RÁ—^L¬±¦ÜìÛÝéq¿ùTüžâ7{—¯IÖ=šº&—Nï ì÷Oû"PD ^LY‰vVߤla6š£ Ð^–¯²9¾»à)"|}¬žÿªûË;ôštYbº,dö© e=«eãþLÿ(žzSr¥î"S8æçËñá„Žÿ íÓS^ýfDJ5Þ?-î©`Ï!½$¦ñ… ·'W<­X^Ó†ÿþ$¸ý^ Ü=ló?äÁÿ&¤¦™‹«ë!L5Å’ñ¬„÷X*¼!%Žj@ŸÌÉËëƒßFïRí»qP„Õ¾™v¶Õ¾¹!LJR`úÒcþx8žEa#Í_…`Ê5t§1˜Û‰¡šbÄiZC2s]ÌÏ\ëò³ÓîœÏ˜÷ô úÌAÕBJe¶‘BJ-Zº‘R«aLJVp-úW$]î*'Ê ×þ]°¦. NŸTIë1§ ²8Xºž¡—a=Ü:†ÛÔ4¡³àèÖf6…^ÕÖrÁ¡Ç]ÁŠô»·xg“œ¥/ߟïÛW Éï2°e8H÷.À|vxQÈ@V¸*Ïc÷WÜ? «dÀGƒ¤ÒõÝf¿¿ÝÜýNºÌºuù+…dGÊÜø¸tÛ¦2©£g -¿nªËŠàÿý᰾ݽ[?î°±VW¼9:9ô¹ÆlF´z‡SCïkËÅß%—tu$…¹¤I Ë\ÒÅ(“È%]½q_¹¤<þçéÐN¿?0/Và•n3<œã±ÜÄ |b«ÇG |¼; ˆÿ8ÿü{þIšSŸ´zрư»5 eª'd,¢”‰zfAñxQy£Võ9¤}¬ñìlñþ8 Qò§¤´YÖèZOÓâ(§¿GÝ =,Ê~Ÿ] °Ó¬›ä$à<÷¨£2Í}ŸIî«)ËsÜ×s—f¶gÀ%ˆ†BÍJôxѧÖGXŸò3Þª дÖ‡»z—ë˜gjI4±¸bâm;[3º¾¹ )„ÃÒÒÉ£î÷è½ßM8³*á›c—¨ì¸*L©ù‘:¯îø¬÷“NŸT¡ûk4¹® åRåyÑKÅÉ<ä4'7™¡DZqéyåj5:–"tl€Ð§ã[òí*¤9ÙsþW¨i»¡‹Z¤ h ÎBnD;Ó@*3 |ƒçW<+ ß•”ã°Ô<àKŽ>u5¾S@@k_ ¸–¶aÇ÷MkÑ—ŒºÝàƒAÍ\›íV/ùå?usÞÝçsúèiÎ>«›SÖM…¡iwá’öqÜdù„ ¼aX¨C3Ù?Ub.vi1‹ü²è}Mpìëv†ÛÍJãéØb®ß9Âñr&úŸÎŸY”ê½ðùüôH×ÍŽ.å+®e U>ÏE :U[2™—ÇßևãîÝ}Î2ùÅÜê™—tYŠïDÖŒûk—ÉÃvSú’OT*3Ã`Þ.'¿MB ¨sý¼iudÁQæsˆÁR1…uYçÁ¥R‚K îv}yÄ£¶¨þùåãûÇùçãԨ]7uæóÕÄöýÆÌôeü#xÑ|÷ðö gŒ £5yl³5óŠw[_Žû5{!ôŸTGû€gOJf•wŸ‚¼6åýÛêËLŠ¸Ê_ýJtg -Äÿ€Ûôû½cA›½ÁíÊ⮇ÇaJ»–ï (ìÚ|©í›Y—aü‡ÀZ÷¥[”Öå|À[jŸ \´A[!?æèÀp­çŸÏ›ã»œÈ/óϧ|Ÿßáýº¦—ÜßJKûZ墔ùÿ¿Ì/;Ã|ƒ¯–¸ØA_ïneÊohmúŽLùkfží+áì¯ÞJä­D"ÎX îâU‘8xw2‡ Â5ü*ÍÓPEß„ì챑¶»Ë¢ÀU”g‘ŸbÌOÌ;”DEþÞz Á¯ì[¨½»±=ÏÉÖ’_ç¾ï nnÓms«|Á“´ÎG‡x»×½éRX -€(UR¡À>ý.D”à…Ó‡üˆÈ •”ÈÙœ¹^ÂNbˆ¯À‚34°wçÓ–uþíáãÃþ°Ù²äº-þVXéàY>w6žm=ÛJ4´¥" ‰ÙS--jœ˜ãúh˜†¥¢FûFYc_G¡°µßKª²5jÀbðÍÅï+ ´éÅ/‘Rmdb7†)ÂOºˆe -#°ö~X1‡nMÌId#š0 Óë¤`\Þ,¸É¬Êzìã›Æ÷¥<¯ø¦84tØkž!¡Oðè›ëlâZ3?äIsûÀw÷8ÏÞùpØÿ¾;a?­÷HnˆÙEµLÍ5t©™ør7¢Œ’t0Í -—ßýpa[ÁK‘Ò £ÅTQDÒõíÎïgwå,É`œÌƒ2÷Otj?¢uý¾ÙLPwÉ ÔÌ›z)ÚKÑ=e¹ev™"ËmÑÒM–ÛjØÑ‘^‹!À—Ö];ŠêMç¸é¼ÙT…ÈÀSnü– >6ßͲ*”ý†v9°7çõág'è»-ñtv9g·ù,Àû­‡iÓCÉÕI¹Z~¬„rµø1[¹Z6¡ñMkÖ›QƒÅöü´!wL6û@Ã>ß õ.œPÀ -4qÇ éºs“éÆ ÃÂðÁwÌ2nÀrlÛÃ=x*óRšø~°áñ‚S/¼á:±¹l4×ñ)ÃtmûæËÃîá„Æj'cç'Ùn§ä‡Æ#.Š1 ²²µ´ªz쎎Ε þ+;=ú[=ºyòäf34˨ d0ÐÔÏØHúÒ©Œ_‡Y±R}…Ÿ· ZS´¯Ú›rº‰V­9Q(^\K“NûJ„á2Ù_c+~Ÿ]<¦{L:`ÅІ£{˜ñèÂgmÂU´¦6¾|®»„}ÉåhW’Œ@ø2ªy|"ót§ÅÖóN?…ïe²¸ f&ExØoúsݯðÒÏìØ>PÑãþи›â¾ÉQ^UÕéÀ†ô'90YÑÞ¸ Ì³Ö‚þ¢DêÑÒùrš³ U5 [Ï8I—C<“к=º¬ ƒ[‘èLvzËô‡‡·6J‘&¡zªh¾ Í}£UV|øX(²â·r“šÌøP¬\­Þà ·9æëÒS$‹1¶˜Yf柋ÈÛm¥)]]5³E‹îÙ¡—°‹u)у/ÔÝÕú’Ôéòöšq­eyTJMãŽ}¾z…§%/˜êí<^ÞwJ É2•ç¤Á¯ÌŸ5a·@yla‚ÁÙÃ% âÄãì5üD†(³¾¾<™Ö:HÓÛˆÖÜi h9ôÖ”˜öK¤ì—˜°É¥µ&Ipʤ[Š\eøÿ൳•µˆ,µ(æ G‹Æ­|eÕ,­4.Ë„B®,ñ® #ó~õ§—ÿZr‡OWölÓ•eŠ„Òܶàë%,ÃÉ< ËÞ—Ýÿå¥S”/68Exþ-Üæ)k­ÓìÿBÇ’iëút—•4U!‚Vsíª5ü“nþá„­A­9ttÀAÿ¿½ ]ÂeƒY=ü“µ+y­a²Ô™, ’•ç`†TRé¥|Ôi®2`bã¢4ׯ/sÔíÍ·y¾=éÖÒ¥UŸNsôàÍãåv¿;½7É]#}Þ_ÌiÐv½fâôO§ïñâ †ùåõë;¶G|øƒû…a;‘_Xr”¿p”âe:xÃôàÔ1,œåHÀdI{£‚ËÚ«‘.õ£Ö7zÕ¥º|0©|´¹xÊ)Ø™jÂv-Ô'k£Aãü´y¸löûOr3MWh§Ó:ß®ÙzÅ]l9N -RâyXßmÀU˜?!.pdö µÀ¾.YÁ5Ák²L^éÒ;a -Ñ¿ýä›Ëšì:óšèk­^_heËâB‘lÉ…üOmOøéæi}ù_ö¼2È`sO›aá™t”ÿ— üÿuþCÝ7¬ -ô×ÍiwG1Þ[¼.pÕº€øXiêuoØÜê¢YN€L–´Wv¸ßìðA#·îÛvbKa(+ód§­çeÁLº1VÌðSÝ÷Ohyav@ÿbÚáø}ÀSÃÕ_hœ+óëL½]à&9Ef¬hoÌ@T-‘©iÈaF°.p.}d‡. ´£B•·êa[L^“Ÿft‚é§jºf(–†%J¤Hé 6ïØ\)Obüd²ê+8ý4ÔæøI?Ùn œl´uy±A[D[ƒZpœµÃòM˼®ð^«&#]9ùœ#'£Ô0±¼p»°ÉÕv­Ûd+†?a±hQúÊY|&›=üNdÄØ<>æhÿj,šm]d‡óصÄ_ª–¼p‰~ÍuÒQ˜e•.ìÏh]Í/6eœ¨z.ιOŸ½xÚ c¡S"ÄØfc[Œm> Œ…¥WŒ]Ëo±Ö3™k'~=ãÀN.àÌ °ts“Ô˜‘VH]Å È‚«*5˜(tDˆ¬îÂE<î>³ØheèT"E:‚öCnÒ@“ß~ Z¬Þl´¡Ì”ô/ör‚Û 'ÛÄ£w ìŒ ØGÀúuѵ0®£–·»Çux9Ù;ìºÕê0µò*Ù Ùî都3>h+×kÔ^“êc÷ü3y@#S ôpón}w†ñ(S8Ʋu-g?œ ÒÀ`c?ýD¶XR—ŸqõRíÚ‡Ií¹ÁªwJŠ*º¼ßêã•êɵ~2êÙ[˜7”_ìïB#‚utæ‹ye)Å?迳莊YÖŒªi¥ÙP‡M¸g\(‰!§r1u2£c"ŠÙæ4+ÎÎ¥2¨/eõ–É­ü·´×_ë}çM?Þôsý¦æØé›~Š‡œ›~87óM?Ìbõ«D¨òN2s2(Ö$~Ê؇ptäð0,Ù$L ܺÞ/quQß¾‡³ºS5’¢f+ô˜›š­ð„Æqõ’õã»ûü¿P -ƒ‹ßçŸ7··ÇüÃŽ„™>¼}‹¤Mô»Óz»ù´ß½{^Ÿ6ÐZã‡tÒ-òƒ;ˆƒIW„íiÊ u~!- -ˆEж±PLŠ¥wù¹üs‰™ìŒ™) ·£“Ç;ã&(@HðxûE £ýRP–5ªV½µ 錸=ª¶  8¦0]AÊ;ÿåß_3;ÁÒšTþFgÙü«`¦e³?ÿ;þbŠ­ Ròå¢6ªÎ3ç nb“ö¸õý¿à$NàG…(·‡=6P¬”`ß:Ï‚|>ö·›ãËÓåö|Ìó¶Ã½h0/Ì?¿ßœä™[8Ì~œ‰uHöcÁLíÔ,ÆXVôÏ‘,ýg/+FÿúŸ›?îŒów—ÓùpÏÐ#›Ò_oD¯/·¿¢a¿®úñÜÚ[±Ó†W£Èç™*µÆª„úxߣ3 dÇ 86mŠúZZg 3bKý6ŠÌÉðkIý*ÜJ ”9yV?Ù“/ÛÍ9yG ;Òô:’»´ùüˆN¢ôª–¨u²hía;úÞƒÜhoÔ÷þùï_ÊŽù ª'FF¿Ì·}È<“oT;Þž?nŽyÑ9@aXý3ÄôÅŽÞÒ6´cÞćבkRœ¼âãUD?MB‰2Ãêê’ã\uˆ‹ÛÜ沃h£[à$KӼߓԎk­„ÖÌÉ.ÕÏ‹<æ$Î*åú:ðœ@G9þ44 f¹³ª7@`%ò‚%œrçl!¡Y®%Ùæ“cïƒQù`V†>£¨ x{ÎÆ £œÒørt–ÍyèTI¤ –â\YuKÛ“>àBà_Â…­Ú…êMüçíìg ™ÌÿÓ~¨Gà‰õ^ü6{È?µ½üïåÿ'"ÿ/M=óÒÓ ¨P~Ñ?^2Ñùõ¦ Pð§ÿR•ðå©ëô2í]  -_ž ZëVÚ[:{VÀÿ[5‡ûèå/ê=Ô? ¨ïžr­})×øܤ\kNb|œ—-P_0O• -…ŒßÔ<´e}éƒ.ì>Q×Æj"hLaá?«dÏžž Ä|oϤÀ -p2…Uw¥Oº­¯ÒšÖøÆ ½ÅëËTP…T#hNKW3=ç„'KPEX Ô« -ž$ꦴºxbãûæúõðAƨî®VŠ (­>„Cþi÷螶ç¯?lv{Ó\ îÚ§ÝsÍØmãªÎÂUÛx«¶5ñMøÒ5ꈯ“§š´Ñ7ÜÍ]8j3PÊk³7î: sÈ[b®J>–˜(3M|$9šä³Fz®½ à §0>ÜKV§_°—áé\tMïíÖNn_!9ÌvXoe÷Øî±}Ä»WÍè¸{Å6ws÷ŠŸÀèÀ.Y÷¸~B»˜žÉ»c.FõÇüð¸Ïç6BXš; µ„ƒìk"äÆ5°¬`dB#îΟ*€Ç°CV}l‚¶-G=}½ÝÎp#óTÕ)专)(§N@™6xù¹6Ou£ïU¼><bËÃF×êmRB ‚Ëb™Â è´úëKú=]×Na»iõzOÒZc!¸·N¤BpçÚ»ÜSße«Ó'Àï¶ù|/ - Óù¨ñhî¤Î8œ§^/n\+Ëy*M$Ý®ÌHÛ|gñSþpùëþp÷;­ÓØî.¦gj9¯®`ÎJj óNvaLONf÷vs+$nsíÝ qc -SBâÖêô‰ÄõFù3 b€ª„îÖ3N¼šª‚íÁ;ÚU˜¼ xÅ -« -ú¯Ÿë®áaF^fxSø 9‘¼ñ&Ïy}0JŸIýᣣHêß~ÈMRh2ãã´j±úë;¼m÷ë"ïX ©q›ùgü¿_æ´é¼h:ÿŒÓ^žÎ›ûÇ/4‘c¾E38¤™'I/]5£ ƒÎ¾\€yþô:½Š¾Çí‚/¨Å7´ï:ä‡ËÃyF‡Ü7RÃð‘.QƒØ8ôo.§$íþÒkaŸ¨ÞïE¹Mëש^Aj‘k;Qô÷DöË6ßç•Ù©´àyoÿu -öóƒV"Mö§Ç=˦‰´§_“N¤yBè4À¬•XÔŠªLpjMüA›ÿÏ L)“LW³hfŸffÂfœ3\bž³½–9¦ùU.ÒL xaùEªIëΠš*Ýha˜Æ!˜â‘ë/*MAÝu 9 M-Å_AèÈŸ€tJ¥ƒTW:ØÞí`¡€ÿIDõL+¥‚4žáÕf†ë¨”"¥ìGÜ)¨Ž¡ g»…"†Æ^ã>×»ÓMñÚ>tšhßýãë‘|Õ+<âf‡ 流îŸ5+5Ô›¾ÈÑ8U>ŒbÃäÀJ,¤5¹‘f6¾çæ€iX’”ýí%h f(EÍÐ5_¾?Ÿ'X%§ t -Sñ¯äêË×—ó{,eÞˆUfÊ"SK´1þMYªóŸ'(Ÿ=–ƒ%Ú¯ä ø‘hQL–k\ `É©î”Môî1óybf±eTÐÙÌŸ,EP®±N{¿äªÚüxš&VxZÞ€’¡ª´ð—–ÒŽÇÑ‘k†MùÓ9x¦p‘01x -à“Z´¶RÁðã#ªp]zVô…hÊþ&ÁѪ™]$`ª˜ d5µÂÎ8Õ7¥—ÃuSá;F›ûŠNO@7¼à íp@ Ì80Díl`°5äø¬BŸÐ'—&GÀ¿ ƒ¯î¸Ä¿ta!;ÊÐ06BCP„4)Šá5uWõ1tpÖA™Œ!Ôx»“†Ý{N»Ç}¾VÄ–ðá᤭þ­¦¹‹Ø¿,Ö¼uSÅ[˜{˜âfxGåaú©X1ÍñMíÕkÿÑãÝÇñaÿfåqºÆ°?7cªS£y3†´w{3¦˜Âøq~’Õé'Ä,#ŠQ ¾Í¸< LÅFÚt¾ä/õ5}ü;x¡ûŸ>•±zÞàM†iš€Ud,*YÔåaO}äÕ‚ûº ¤ èƒÜ©}Ï„ˆ»ø—‡ãV©æó {tÅ¥$^ŽØMždÁ¡q¤è¾C²Âõ‘Oùyöép9Îê9È@Oê(òQKÃÊ–¾¢ÁÁ11Í›&WµÊ^¶´QÚaÇWÛÁµèGq/³@À8ÚúU„£|C8†pìRµ4lú -MA²S6 ,ú}CÜuZâ"¾KPå*ÂRcc²ãé3¹91|ö‹cëÏþäPšÝÑr”.[:Ai~E'‚ÒìZô…ÒHvA4úiþù²Û~ißiSßË£¿Àÿ¯Ýaܼ“ôvá|ã:“¶³ ("RYÛ™ÆÏŠò¨—ó€²²›ÄGrYïÏÃúnƒ€èI弸2ù8 aãAÄÌÙ½¤˜^K]i«£8É.‡q: XœÆg’ÜoÛmËëið}¶ê2[ù1¶ÇÖ7Øê÷ìãæZçÞÊTÜfS‡÷ŸAzÍð«»$º03]Æã6a €ì)Ù%FdG4c%ãéÒ[ƒÚR‹dÛ°Z’ÌfEc‰A0Û»üüKÉd°ùÇÍÜ_^óÔö -äqÇM¸³`°(T0˜˜šBkjb8 °åpQ\|*Æ÷¨ïýù%)¶K®Ë5Íkt MWêâUgHáÚÈq¨§Ú˜ÞV†˜¡éÐQp~,‡õ¼àyal^È2¸¾ñÐÊOæFùQ]LTæ-l)/ÿYê8¬²d¥Þ´”%“”2¢”%í¸e)^ É4l’iÍB­:ÊÙð¡ÞvÛâT.è·:ÍÙfªËÆNŠFÇpØeÔ ‘ªÆ¶ôðdÔ¹±ÆýÕf!8ç9n3b‚Å>3Ÿ¯˜e=)çè)Úµ½=)úP[2—ÇßևãííÍ~žú°»Ë_6|A4i™] ¯ÓŸ|¶ôkŒ ]® cBåG ]¶ÃB«Gl"Ce¿þ¨bœ×ý°Ë?¾¼Å‰¾×Åy!á¢ë@À§óñrw¾ó9yˆþïMñ¨šJ4wÁ+I^Ÿ“ÆD´H&ùœ²êáÅ=U“ûú>eu2„Û*•“? ùÍåt>ÜÏÈÄfûÝíqsüTpîw½Û–ê:÷ùÊÓ´Ý÷›OE³/þ¬*”…5é£ltzøXÀ/úd¿Ú’éõ¾n™•1ë¡©» ½eù†›ã» ž9BþÇú(âSƯÀãþ‚u¥])`<QÂØ—¶¬gµl|ïŸIƒâÅSoʨcݵ§ôtÌÑ}8!Ð9¡~"´HxoBté3Ö¿ŠcÃÐ  jSc2Ô>ÿ¦ìÀ¦`·öÇgM“õì‡BµÈS›&aBì@Ã÷/HÔ -7âèÌ—‘ÄÉåTx®«AÊÉ-Œõ» -fÅ\f‡X×É?zªëBu Ou×DuÝ¢[#ŒäZÚF 6†F”`k-œG BB»>?iÑÑœ4Õ&%¶¹ƒ›×q¦ªwÈ;:AaçV9žž¼Š_ÆÑÀ°ª '2OM^ {FÔdW7ŒÇuÝ°º½³ºaì¦tO½µ:ÎãAš”êPÖürBm矺¬Òð?ñÃÍhÀhÑ=$kÏD-Ò‡f?:¯á]…‰mF¦Õ•ÝBÏn…‹ ­ù²ÅÚÿíYϳž[Ö+®×ˆã*¹Í±`*Ã'PÖ8TÃa1dÔ!"/™7”Ç^ª^UŠÉ¯£S…q!&ᥔ<ú ¼§d|Dãa$zù6Ï·€y<^þq/ÍØÅ5qF&‚k'ã5*†F‹yîD ZN!ÒeîÓ?7M—¦Ä¹š†VˆWÊ%?~_ôgÏžÇÓþBCí¯€E2&$‡Ú¼Á,´^†€”g°÷`ò…ê)›Ë@ŠéŒŸgA½`½ø0(W\μ)ö.¤QÓÖœm=?oÞ©ÉCùp-HwD  $ÍÜ’LÃJÀNÆ€Ö´)cŸ~û±™ñÅÃÛÙXȨ¦Lóäê {Ä«82 ºÒ?^³WU$OÛdÊÑœÞP²½8œK!{¹TBp ·8=éšÚÛÅæ`~ùüÏÓL27ÅcóÏøï_æŸkÛ1αN£ÆMÐfç/¸žÁHQØôWpöTL¦/kE -q -©"ŠÍ-o‚ñŸt¤®Ä÷U}J€¢¨K]£V2ðÀÔÛò¸%â#B­Wúç©ßÿ<ýßRל SÏùýãéŒ:+éÃL3IL5“òƒLOqÍa8÷  nL•¿VY òWåÁ-vw5 º%¨û¶éîªRuÓ­$PTBTLTA"ÑR°wúŸ§¿TçîÏjÞTXƒÆ ¹çõ”ù„èhÒjwê¢îS±>–ñdÍå·M^}]Ué'ú+D¯ÒŸëŽÌ%¼Øg_0?KÔJÉæDWÛØiAª( -5±ðý ^„›¥T¸Yš 7Ô?ý·HI…¹ž>ñ|'i¦è®-ÇA÷ؼåLp‘$ -9FünvÂKÓeÔ^è°^rñ’‹—\Š#¼ŒÅVL ߨ²ŠÌ$•L4…B,.E Ûr-•(!‹t')!è2c‘K²r,¦RDç-åÔ”ˆ ÁœÁC&2c¡X¡xı¤ìÕ¹$%‡T,¹i¾dŸÄ·t4/@x ¥é#…#j¦dúX %Æx«GV,ªãzƒ‡3ƒG´”H.…`ìȲ¬·ùy³ÛŸLüÜMñœ+³קcÛM³×’`r Fõ–vòK&•_¾CcK‡ö2Œ—a¼ SAØ}3¦de$³`TySÁÊ36…+,ÆzƒHwƒHHÄŠ&µ`颗˜î([pN¤–h§qWÑ"\$°h‘ÉE Íwµ“0VR ã;íCD¼Œáe ^Æ‚‘Ä®‰y‰tàN B³€ÛXòÙ$³–MÊu²I*[Œ•í•L©¬$“W°Ñ€ >IœII©C)©—óáR‚BL/– ÄÖ€–P+©µê*@­Ñç8n:ˆQ7äÁ…©b€Dª%xÍ"‹´D*½÷¶¬’X_°úÏÆKW^ºòÒU%]­®KºŠàŠÍ -éêMD^Ⱥ!‹¤ØâhÄËZ=ÉZ²ðP¾Pâz‡0ù±‹ÄEìS⢸—¸øb«®Ä¥õÞZWè@âú<Fâ¢Ûš|áÓ™PóR˜—¼ö<¤0 -N^ -»N)Œ|=/…(…q2ÇRØ1ÇmÞÝÀªrR]÷ë<¨:†¯•Çr‘KçE휆‰TÒú¥ß›´¼0å…©*°¾™5¥Àj3ñ©ÆZÝÇ…rìkªÖØGW»»N.sâ5Ø|€øêjÄk;É47ôYWqÖ­~ÇZÇ -I[°‘¼­Ó.Ðl¾'Ã{ñÆ‹7^¼)c®â͈1×ÁÂìæy/oJ|yÎ×+}Ü”çÄ_w¾'Qùv€ìc~8b|+ÖÄèzWñìMù¬;Ñ£ÑïDDõÛö+zñ‹ëþº—=¼èñ¤Dr¼ßÔøâEp½èÑ›èÑæÛ~Ecþx@O"Ì÷[‘ÌQ4šÓFt¶7'„R…òaåB¬ÙÇd`–LÃ.Òº´%ÏôN§ò}56Wi“Òo§|;Û=”9ÜR…OïÁ›%‚‡HtÁ+NPùœÍ =ý¦xÜM&xéüƯ䡿’ýUô(‘žV©TA=W³­äÇ*xϺ£{¢{¸l­*7¾®ã\#pýçz𰓇fÕô<°{`wR‰ieX‰Iãàµ=bÒ ,/´)ǤœÓ@0ž Q\gÙz)œMðû”ŸñÇ?¡ƒ÷ooÝZ~åsóÖsÚ†@ANJ4-SÚ%náÖdôa©^Uµ¿ªÐDm|E¿¯‹Ê¨tÍ1L” gÖˉy\wë]ªða[Y£éÛÊ.ûô`?MmBØ7=T€T/Ë[Ðê ̦:~©'Ó¥í¯àSE·›ÓîÎ#ºSƒCSN¸M9â|I5ðv!‚H˜uç¯x¥,€7ƒþ#€hX}Uóübªù6V‰MÀ„£·~Ýì7ùùú¬ÿòçûÿã¢Mòßá]ró²ë6ÿò盿ÐbÀ¿bË¿|uÊ7Ç»÷ëíæ¼Aƒõ¿f5%–uÜõGôçÓnÛüú+>—t*»‡3™%ùóÃá<{¸ì÷ä§_ùí»ê—Óî¿‹ÐÙÚìëg -Œ¥?.ê¿_N»wù¶Ñןéÿùj¿yxwwØæÒÉ}Ào»9®7§»ÝNgšûüá]IyA(˜äWüLªáz™EqÙ·;épøŒ˜}’ÛÝ»Æ Ç|÷°Íÿ˜Þ—ÿ34Ž»ûÍñÓì÷ü¸a›{„ýRu/÷ŸNÿg¿ÆŸfs‡íŸ2—Ëùíòþ–2³ƒEWMãX}<åçªØ4¦Û%YèmZ¬'v¬Owˆ´¥ã½Ý6¢òý×?¾V~ÍD¶&³MôÙù9ÈkÁRÖ·»gàfÞá=Îx¦hï—‡ó´öHå~óø/Ré±½Ò0Iô> ѯ'0üÇŠè‰êÝA¾ŠD«Fÿ®ùfÅ=ãÄÿ¹äH1<élIõ^8åÇK•]èÕNFªWØb±vèEÎìê`„® -cj*Ç‚ Qõj}tWjˆÆ­õu.}Ë= -ùF%wYŠ6ËƱÁJk¿Y©’§v÷ùé¼¹Aî¬VŸîé n÷‡[C5ÈRò‘ã£tŪßø7„÷÷¥’´úBHDØgthuŽ âôŽøÁb¶Õ+÷r2¢°ùmTàãøð¨Kiî{nÛ_vˆ8p;@k(¿ÙCë5^ºõZD­p 5’FßìnX¯Ï›ã;ôÁ/Åí7ç©"ÑòZ¼^{õ«³ -LµÅ+}}‘Jè¬;&¾K²Û ˆnonóM|G›ôf³V7oo³·wËxû6¸S ÏåÊ©„†SÉ7áÝ&Û.n6·Éò&΂ۛMz·½¹Û®V›0‰ï–ËD>cÙ‚ß,Äøfq½KãÜЀCxð¼×O‹Òa¥«ëc¾{÷^¾žâ«¯}ãyì~G wÜõóf‹¸EdÀ!“ŽXø"{Èj±p­µEçy÷ð©Î†/MæZc6l¾ÒZör¬©­µõ'ãÿÒ‚gŒ t*ÙóÜ?¸ãñ¿ê?FµíÏýp3ˆ4Í-lZä? L¡¸×âÎ$ó‡òÈ?ŸÒùìÉaíW_o·³ÂGϽùñ&\4_¨¨ëUðò¼ÁRêP¯Á~/Yƒ`¥Xêæ:èi!:Ë<øx_И†e¥£G ¿D¿&HÇ£¤¦„‹–Q@ò:ÕO½ªúç͇‡Ãý'}_çÃDwÆy¢óÂÉ«/r™ÈíÔ‚&5Ÿww¿·6¨¥ ËÈH¢¥©ü\d¿ñqtµøvÖ3ååÇûõƒ@îde³âÛ3ÿ&Ÿ¢úw¹4Ãq2m]Wuœ0ì}èÓÀæíyà'¯[Ê zü–êÁªð÷/ÓO>ôm‡¦åê@õmEö4`<Ò Mj[;¶ùéî¸#ò»xÃk…ð™˜<˜1qDóÆÞ8˜¹LgWâÂ{œt«ëY12ÌMÍŒtîdGâAÉܘt¶²&H Ŧá‡ÑnÈ¿ƒUPýóϲQÖçc†š°oÂØbÜŽiH€5ìºØ7k½ßåGŒ Ÿ&AZ•ªÇÍ1WÏM4 ™9ãÅK¨O¸ðm™zÛ=—ã~½Ùï6Zf£Çñµ†Óár¼ëYhîŽ&Òås ¼V‡G-…›,hÍfà.kâm±g¥€Û¦5fJÍ-e8~±í'ÐÑFÇp½>öz1·\RfÝX±«·ù>wnI2°di;GVäŽù‡Ž{{ýcŒ–)žî Å-ªÞ¿ >KRÛ„óàqM€­÷lãqkg®uA¡øÁdϲ¿š®k³…à,Å,R‚Nbæm¹•m¬{ë>äú+/û?™@¦ÉÏÁ¯l•Nãæ')ÿ{Jë#Vö -}š¯Ê+ìÇÍùpüª£Ç’.:ùßǹaëYʳ”g)ëµ`”&Y :¥Í^˦ilÍLZ¶b~%z ” aóf(7òÇݶhÚ“¥Óð¼ï=&R1¡§.ÏhŸ@AÃÞÕÂi©öì³wÕòÑE2W-ÙHZkñY 8W7 îi{š§»wØ^ú”Ðu/ÞOä -¥Úqì$VžšÜQ×.U •ÄšíkH*wû Õ¬.Ür\oŠÑ&=ßfñ$c“ð8Y~<æ[=½]„dtšoŒ9ôã’6›“Ë$²ä~³Û÷4TSùÂ÷¬ÿûðв׊²ŠüÕ@ÝálGˆÍ¡‰x§ýáÝNžCÀÑívý˜7Úû|jM *¹R}…Ûp!5`€’\: LÕo-µt> … †¾¦'™´ú_õ¿%¡JlçbXÂÎÏ -O_ñCj¢ò>¤'ÂBAãï º&¿V[‡2}‡rkž ÿb¢ø¹¥«àüƒY™SŠ½·+îƒißîkª¹°GF ¿âJu­Nͬ×¢Ú£Õ_8ýŠ[#vÚìþû*ˆ—Ár±ÌÒ”_:ðGf÷UkP¡tù— -N«y™Þ ljøì3iÕXì¯þçëÿù]ôý%ù퇟þßÕëÅËÓ_ó߶»4øÿÎÿû¿ÂþþëÏáü×/?,¶é÷/ÿúÏßþ-Úü¸ÿîÝWüújó°=æ»ÿgs>?Ý]^–›œÿdß]Ž‡Ç|þŸùþ´{ø}×þ‚Á°_PC[S0”æÕ»m)Á!$½´¼p’XýÔUÂýÿ’Œ§Bz \ No newline at end of file only in patch2: unchanged: --- a/core/modules/system/tests/fixtures/update/drupal-8.entity-data-revision-metadata-fields-2248983.php +++ /dev/null @@ -1,162 +0,0 @@ -insert('entity_test_revlog') - ->fields([ - 'id', - 'revision_id', - 'type', - 'uuid', - 'langcode', - 'revision_created', - 'revision_user', - 'revision_log_message', - 'name', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'type' => 'entity_test_revlog', - 'uuid' => 'f0b962b1-391b-441b-a664-2468ad520d96', - 'langcode' => 'en', - 'revision_created' => '1476268518', - 'revision_user' => '1', - 'revision_log_message' => 'second revision', - 'name' => 'entity 1', - ]) - ->execute(); - -$connection->insert('entity_test_revlog_revision') - ->fields([ - 'id', - 'revision_id', - 'langcode', - 'revision_created', - 'revision_user', - 'revision_log_message', - 'name', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '1', - 'langcode' => 'en', - 'revision_created' => '1476268517', - 'revision_user' => '1', - 'revision_log_message' => 'first revision', - 'name' => 'entity 1', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'langcode' => 'en', - 'revision_created' => '1476268518', - 'revision_user' => '1', - 'revision_log_message' => 'second revision', - 'name' => 'entity 1', - ]) - ->execute(); - -// Data for entity type "entity_test_mul_revlog" -$connection->insert('entity_test_mul_revlog') - ->fields([ - 'id', - 'revision_id', - 'type', - 'uuid', - 'langcode', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'type' => 'entity_test_mul_revlog', - 'uuid' => '6f04027a-1cbd-46e3-a67e-72636b493d4f', - 'langcode' => 'en', - ]) - ->execute(); - -$connection->insert('entity_test_mul_revlog_field_data') - ->fields([ - 'id', - 'revision_id', - 'type', - 'langcode', - 'revision_created', - 'revision_user', - 'revision_log_message', - 'name', - 'default_langcode', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'type' => 'entity_test_mul_revlog', - 'langcode' => 'en', - 'revision_created' => '1476268518', - 'revision_user' => '1', - 'revision_log_message' => 'second revision', - 'name' => 'entity 1', - 'default_langcode' => '1', - ]) - ->execute(); - -$connection->insert('entity_test_mul_revlog_field_revision') - ->fields([ - 'id', - 'revision_id', - 'langcode', - 'revision_created', - 'revision_user', - 'revision_log_message', - 'name', - 'default_langcode', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '1', - 'langcode' => 'en', - 'revision_created' => '1476268517', - 'revision_user' => '1', - 'revision_log_message' => 'first revision', - 'name' => 'entity 1', - 'default_langcode' => '1', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'langcode' => 'en', - 'revision_created' => '1476268518', - 'revision_user' => '1', - 'revision_log_message' => 'second revision', - 'name' => 'entity 1', - 'default_langcode' => '1', - ]) - ->execute(); - -$connection->insert('entity_test_mul_revlog_revision') - ->fields([ - 'id', - 'revision_id', - 'langcode', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '1', - 'langcode' => 'en', - ]) - ->values([ - 'id' => '1', - 'revision_id' => '2', - 'langcode' => 'en', - ]) - ->execute(); only in patch2: unchanged: --- a/core/modules/system/tests/fixtures/update/drupal-8.views-revision-metadata-fields-2248983.php +++ /dev/null @@ -1,35 +0,0 @@ -insert('config') - ->fields([ - 'collection', - 'name', - 'data', - ]) - ->values([ - 'collection' => '', - 'name' => 'views.view.' . $views_config['id'], - 'data' => serialize($views_config), - ]) - ->execute(); -} only in patch2: unchanged: --- a/core/modules/system/tests/fixtures/update/views.view.entity_test_mul_revlog_for_2248983.yml +++ /dev/null @@ -1,435 +0,0 @@ -uuid: 25b89168-a8e5-4ae1-8fb5-c8efb91f0938 -langcode: en -status: true -dependencies: - module: - - entity_test_revlog -id: entity_test_mul_revlog_for_2248983 -label: entity_test_mul_revlog -module: views -description: '' -tag: '' -base_table: entity_test_mul_revlog_property_data -base_field: id -core: 8.x -display: - default: - display_plugin: default - id: default - display_title: Master - position: 0 - display_options: - access: - type: none - options: { } - cache: - type: tag - options: { } - query: - type: views_query - options: - disable_sql_rewrite: false - distinct: false - replica: false - query_comment: '' - query_tags: { } - exposed_form: - type: basic - options: - submit_button: Apply - reset_button: false - reset_button_label: Reset - exposed_sorts_label: 'Sort by' - expose_sort_order: true - sort_asc_label: Asc - sort_desc_label: Desc - pager: - type: mini - options: - items_per_page: 10 - offset: 0 - id: 0 - total_pages: null - expose: - items_per_page: false - items_per_page_label: 'Items per page' - items_per_page_options: '5, 10, 25, 50' - items_per_page_options_all: false - items_per_page_options_all_label: '- All -' - offset: false - offset_label: Offset - tags: - previous: ‹‹ - next: ›› - style: - type: table - options: - grouping: { } - row_class: '' - default_row_class: true - override: true - sticky: false - caption: '' - summary: '' - description: '' - columns: - name: name - info: - name: - sortable: false - default_sort_order: asc - align: '' - separator: '' - empty_column: false - responsive: '' - default: '-1' - empty_table: false - row: - type: fields - options: - inline: { } - separator: '' - hide_empty: false - default_field_elements: true - fields: - name: - table: entity_test_mul_revlog_property_data - field: name - id: name - entity_type: entity_test_mul_revlog - entity_field: name - plugin_id: field - relationship: none - group_type: group - admin_label: '' - label: '' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: string - settings: { } - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - revision_created: - id: revision_created - table: entity_test_mul_revlog_property_data - field: revision_created - relationship: none - group_type: group - admin_label: '' - label: 'Revision create time' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: timestamp - settings: - date_format: medium - custom_date_format: '' - timezone: '' - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_mul_revlog - entity_field: revision_created - plugin_id: field - revision_id: - id: revision_id - table: entity_test_mul_revlog_property_data - field: revision_id - relationship: none - group_type: group - admin_label: '' - label: 'Revision ID' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: number_integer - settings: - thousand_separator: '' - prefix_suffix: true - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_mul_revlog - entity_field: revision_id - plugin_id: field - revision_log_message: - id: revision_log_message - table: entity_test_mul_revlog_property_data - field: revision_log_message - relationship: none - group_type: group - admin_label: '' - label: 'Revision log message' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: basic_string - settings: { } - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_mul_revlog - entity_field: revision_log_message - plugin_id: field - revision_user: - id: revision_user - table: entity_test_mul_revlog_property_data - field: revision_user - relationship: none - group_type: group - admin_label: '' - label: 'Revision user' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: target_id - type: entity_reference_label - settings: - link: true - group_column: target_id - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_mul_revlog - entity_field: revision_user - plugin_id: field - filters: { } - sorts: { } - header: { } - footer: { } - empty: { } - relationships: { } - arguments: { } - display_extenders: { } - cache_metadata: - max-age: 0 - contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url.query_args - tags: { } only in patch2: unchanged: --- a/core/modules/system/tests/fixtures/update/views.view.entity_test_revlog_for_2248983.yml +++ /dev/null @@ -1,436 +0,0 @@ -uuid: 5a8b00d2-67ce-415b-9e7d-6c013bf7f6b8 -langcode: en -status: true -dependencies: - module: - - entity_test_revlog -id: entity_test_revlog_for_2248983 -label: entity_test_revlog -module: views -description: '' -tag: '' -base_table: entity_test_revlog -base_field: id -core: 8.x -display: - default: - display_plugin: default - id: default - display_title: Master - position: 0 - display_options: - access: - type: none - options: { } - cache: - type: tag - options: { } - query: - type: views_query - options: - disable_sql_rewrite: false - distinct: false - replica: false - query_comment: '' - query_tags: { } - exposed_form: - type: basic - options: - submit_button: Apply - reset_button: false - reset_button_label: Reset - exposed_sorts_label: 'Sort by' - expose_sort_order: true - sort_asc_label: Asc - sort_desc_label: Desc - pager: - type: mini - options: - items_per_page: 10 - offset: 0 - id: 0 - total_pages: null - expose: - items_per_page: false - items_per_page_label: 'Items per page' - items_per_page_options: '5, 10, 25, 50' - items_per_page_options_all: false - items_per_page_options_all_label: '- All -' - offset: false - offset_label: Offset - tags: - previous: ‹‹ - next: ›› - style: - type: table - options: - grouping: { } - row_class: '' - default_row_class: true - override: true - sticky: false - caption: '' - summary: '' - description: '' - columns: - name: name - info: - name: - sortable: false - default_sort_order: asc - align: '' - separator: '' - empty_column: false - responsive: '' - default: '-1' - empty_table: false - row: - type: fields - options: - inline: { } - separator: '' - hide_empty: false - default_field_elements: true - fields: - name: - id: name - table: entity_test_revlog - field: name - relationship: none - group_type: group - admin_label: '' - label: Name - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: string - settings: - link_to_entity: false - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_revlog - entity_field: name - plugin_id: field - revision_created: - id: revision_created - table: entity_test_revlog - field: revision_created - relationship: none - group_type: group - admin_label: '' - label: 'Revision create time' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: timestamp - settings: - date_format: medium - custom_date_format: '' - timezone: '' - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_revlog - entity_field: revision_created - plugin_id: field - revision_id: - id: revision_id - table: entity_test_revlog - field: revision_id - relationship: none - group_type: group - admin_label: '' - label: 'Revision ID' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: number_integer - settings: - thousand_separator: '' - prefix_suffix: true - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_revlog - entity_field: revision_id - plugin_id: field - revision_log_message: - id: revision_log_message - table: entity_test_revlog - field: revision_log_message - relationship: none - group_type: group - admin_label: '' - label: 'Revision log message' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: value - type: basic_string - settings: { } - group_column: value - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_revlog - entity_field: revision_log_message - plugin_id: field - revision_user: - id: revision_user - table: entity_test_revlog - field: revision_user - relationship: none - group_type: group - admin_label: '' - label: 'Revision user' - exclude: false - alter: - alter_text: false - text: '' - make_link: false - path: '' - absolute: false - external: false - replace_spaces: false - path_case: none - trim_whitespace: false - alt: '' - rel: '' - link_class: '' - prefix: '' - suffix: '' - target: '' - nl2br: false - max_length: 0 - word_boundary: true - ellipsis: true - more_link: false - more_link_text: '' - more_link_path: '' - strip_tags: false - trim: false - preserve_tags: '' - html: false - element_type: '' - element_class: '' - element_label_type: '' - element_label_class: '' - element_label_colon: true - element_wrapper_type: '' - element_wrapper_class: '' - element_default_classes: true - empty: '' - hide_empty: false - empty_zero: false - hide_alter_empty: true - click_sort_column: target_id - type: entity_reference_label - settings: - link: true - group_column: target_id - group_columns: { } - group_rows: true - delta_limit: 0 - delta_offset: 0 - delta_reversed: false - delta_first_last: false - multi_type: separator - separator: ', ' - field_api_classes: false - entity_type: entity_test_revlog - entity_field: revision_user - plugin_id: field - filters: { } - sorts: { } - header: { } - footer: { } - empty: { } - relationships: { } - arguments: { } - display_extenders: { } - cache_metadata: - max-age: 0 - contexts: - - 'languages:language_content' - - 'languages:language_interface' - - url.query_args - tags: { } only in patch2: unchanged: --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestWithRevisionLog.php @@ -0,0 +1,48 @@ +setLabel(t('Name')) - ->setDescription(t('The name of the test entity.')) - ->setTranslatable(TRUE) - ->setRevisionable(TRUE) - ->setSetting('max_length', 32) - ->setDisplayOptions('view', [ - 'label' => 'hidden', - 'type' => 'string', - 'weight' => -5, - ]) - ->setDisplayOptions('form', [ - 'type' => 'string_textfield', - 'weight' => -5, - ]); - - return $fields; - } - -} only in patch2: unchanged: --- a/core/modules/system/tests/src/Functional/FileTransfer/TestFileTransfer.php +++ b/core/modules/system/tests/src/Functional/FileTransfer/TestFileTransfer.php @@ -46,7 +46,7 @@ public function createDirectoryJailed($directory) { public function removeFileJailed($destination) { if (!ftp_delete($this->connection, $item)) { - throw new FileTransferException('Unable to remove the file @file.', NULL, ['@file' => $item]); + throw new FileTransferException('Unable to remove to file @file.', NULL, ['@file' => $item]); } } only in patch2: unchanged: --- a/core/modules/taxonomy/src/Entity/Term.php +++ b/core/modules/taxonomy/src/Entity/Term.php @@ -229,8 +229,7 @@ public function setWeight($weight) { * {@inheritdoc} */ public function getVocabularyId() { - @trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.4.0 and will be removed before 9.0.0. Use ' . __CLASS__ . '::bundle() instead to get the vocabulary ID.', E_USER_DEPRECATED); - return $this->bundle(); + return $this->get('vid')->target_id; } /** only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/views/argument/IndexTidDepth.php +++ b/core/modules/taxonomy/src/Plugin/views/argument/IndexTidDepth.php @@ -2,7 +2,6 @@ namespace Drupal\taxonomy\Plugin\views\argument; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; @@ -107,7 +106,7 @@ public function query($group_by = FALSE) { // Now build the subqueries. $subquery = db_select('taxonomy_index', 'tn'); $subquery->addField('tn', 'nid'); - $where = (new Condition('OR'))->condition('tn.tid', $tids, $operator); + $where = db_or()->condition('tn.tid', $tids, $operator); $last = "tn"; if ($this->options['depth'] > 0) { only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php +++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php @@ -194,7 +194,7 @@ public function getArgument() { $taxonomy_terms = $node->{$field->getName()}->referencedEntities(); /** @var \Drupal\taxonomy\TermInterface $taxonomy_term */ foreach ($taxonomy_terms as $taxonomy_term) { - $taxonomy[$taxonomy_term->id()] = $taxonomy_term->bundle(); + $taxonomy[$taxonomy_term->id()] = $taxonomy_term->getVocabularyId(); } } } only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/views/field/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/field/TaxonomyIndexTid.php @@ -145,8 +145,8 @@ public function preRender(&$values) { foreach ($data as $tid => $term) { $this->items[$node_nid][$tid]['name'] = \Drupal::entityManager()->getTranslationFromContext($term)->label(); $this->items[$node_nid][$tid]['tid'] = $tid; - $this->items[$node_nid][$tid]['vocabulary_vid'] = $term->bundle(); - $this->items[$node_nid][$tid]['vocabulary'] = $vocabularies[$term->bundle()]->label(); + $this->items[$node_nid][$tid]['vocabulary_vid'] = $term->getVocabularyId(); + $this->items[$node_nid][$tid]['vocabulary'] = $vocabularies[$term->getVocabularyId()]->label(); if (!empty($this->options['link_to_taxonomy'])) { $this->items[$node_nid][$tid]['make_link'] = TRUE; only in patch2: unchanged: --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTidDepth.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTidDepth.php @@ -2,7 +2,6 @@ namespace Drupal\taxonomy\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; /** @@ -73,7 +72,7 @@ public function query() { // Now build the subqueries. $subquery = db_select('taxonomy_index', 'tn'); $subquery->addField('tn', 'nid'); - $where = (new Condition('OR'))->condition('tn.tid', $this->value, $operator); + $where = db_or()->condition('tn.tid', $this->value, $operator); $last = "tn"; if ($this->options['depth'] > 0) { only in patch2: unchanged: --- a/core/modules/taxonomy/src/TermForm.php +++ b/core/modules/taxonomy/src/TermForm.php @@ -85,7 +85,7 @@ public function form(array $form, FormStateInterface $form_state) { '#value' => $term->id(), ]; - return parent::form($form, $form_state); + return parent::form($form, $form_state, $term); } /** only in patch2: unchanged: --- a/core/modules/taxonomy/src/TermInterface.php +++ b/core/modules/taxonomy/src/TermInterface.php @@ -87,9 +87,6 @@ public function setWeight($weight); * * @return int * The id of the vocabulary. - * - * @deprecated Scheduled for removal before Drupal 9.0.0. Use - * TermInterface::bundle() instead. */ public function getVocabularyId(); only in patch2: unchanged: --- a/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldAllTermsTest.php +++ b/core/modules/taxonomy/src/Tests/Views/TaxonomyFieldAllTermsTest.php @@ -57,7 +57,7 @@ public function testViewsHandlerAllTermsWithTokens() { $this->assertText('The taxonomy term name for the term: ' . $this->term1->getName()); // The machine name for the vocabulary the term belongs to: {{ term_node_tid__vocabulary_vid }} - $this->assertText('The machine name for the vocabulary the term belongs to: ' . $this->term1->bundle()); + $this->assertText('The machine name for the vocabulary the term belongs to: ' . $this->term1->getVocabularyId()); // The name for the vocabulary the term belongs to: {{ term_node_tid__vocabulary }} $vocabulary = Vocabulary::load($this->term1->bundle()); only in patch2: unchanged: --- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php +++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermTest.php @@ -77,7 +77,7 @@ protected function assertEntity($id, $expected_label, $expected_vid, $expected_d $entity = Term::load($id); $this->assertTrue($entity instanceof TermInterface); $this->assertIdentical($expected_label, $entity->label()); - $this->assertIdentical($expected_vid, $entity->bundle()); + $this->assertIdentical($expected_vid, $entity->getVocabularyId()); $this->assertEqual($expected_description, $entity->getDescription()); $this->assertEquals($expected_format, $entity->getFormat()); $this->assertEqual($expected_weight, $entity->getWeight()); only in patch2: unchanged: --- a/core/modules/tour/tour.module +++ b/core/modules/tour/tour.module @@ -54,7 +54,6 @@ function tour_toolbar() { '#attributes' => [ 'class' => ['toolbar-icon', 'toolbar-icon-help'], 'aria-pressed' => 'false', - 'type' => 'button', ], ], '#wrapper_attributes' => [ only in patch2: unchanged: --- a/core/modules/user/src/Plugin/Block/UserLoginBlock.php +++ b/core/modules/user/src/Plugin/Block/UserLoginBlock.php @@ -6,6 +6,7 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Routing\RedirectDestinationTrait; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Routing\UrlGeneratorTrait; use Drupal\Core\Url; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Block\BlockBase; @@ -22,6 +23,7 @@ */ class UserLoginBlock extends BlockBase implements ContainerFactoryPluginInterface { + use UrlGeneratorTrait; use RedirectDestinationTrait; /** @@ -92,24 +94,7 @@ public function build() { unset($form['pass']['#attributes']['aria-describedby']); $form['name']['#size'] = 15; $form['pass']['#size'] = 15; - - // Instead of setting an actual action URL, we set the placeholder, which - // will be replaced at the very last moment. This ensures forms with - // dynamically generated action URLs don't have poor cacheability. - // Use the proper API to generate the placeholder, when we have one. See - // https://www.drupal.org/node/2562341. The placholder uses a fixed string - // that is - // Crypt::hashBase64('\Drupal\user\Plugin\Block\UserLoginBlock::build'); - // This is based on the implementation in - // \Drupal\Core\Form\FormBuilder::prepareForm(), but the user login block - // requires different behavior for the destination query argument. - $placeholder = 'form_action_p_4r8ITd22yaUvXM6SzwrSe9rnQWe48hz9k1Sxto3pBvE'; - - $form['#attached']['placeholders'][$placeholder] = [ - '#lazy_builder' => ['\Drupal\user\Plugin\Block\UserLoginBlock::renderPlaceholderFormAction', []], - ]; - $form['#action'] = $placeholder; - + $form['#action'] = $this->url('', [], ['query' => $this->getDestinationArray(), 'external' => FALSE]); // Build action links. $items = []; if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) { @@ -143,20 +128,4 @@ public function build() { ]; } - /** - * #lazy_builder callback; renders a form action URL including destination. - * - * @return array - * A renderable array representing the form action. - * - * @see \Drupal\Core\Form\FormBuilder::renderPlaceholderFormAction() - */ - public static function renderPlaceholderFormAction() { - return [ - '#type' => 'markup', - '#markup' => Url::fromRoute('', [], ['query' => \Drupal::destination()->getAsArray(), 'external' => FALSE])->toString(), - '#cache' => ['contexts' => ['url.path', 'url.query_args']], - ]; - } - } only in patch2: unchanged: --- a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php +++ b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php @@ -3,7 +3,6 @@ namespace Drupal\user\Plugin\EntityReferenceSelection; use Drupal\Core\Database\Connection; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; @@ -229,17 +228,17 @@ public function entityQueryAlter(SelectInterface $query) { // Re-add the condition and a condition on uid = 0 so that we end up // with a query in the form: // WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0) - $or = new Condition('OR'); + $or = db_or(); $or->condition($condition['field'], $condition['value'], $condition['operator']); // Sadly, the Database layer doesn't allow us to build a condition // in the form ':placeholder = :placeholder2', because the 'field' // part of a condition is always escaped. // As a (cheap) workaround, we separately build a condition with no // field, and concatenate the field and the condition separately. - $value_part = new Condition('AND'); + $value_part = db_and(); $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); $value_part->compile($this->connection, $query); - $or->condition((new Condition('AND')) + $or->condition(db_and() ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + [':anonymous_name' => \Drupal::config('user.settings')->get('anonymous')]) ->condition('base_table.uid', 0) ); only in patch2: unchanged: --- a/core/modules/user/src/Plugin/views/filter/Current.php +++ b/core/modules/user/src/Plugin/views/filter/Current.php @@ -2,7 +2,6 @@ namespace Drupal\user\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; use Drupal\views\Plugin\views\filter\BooleanOperator; @@ -29,7 +28,7 @@ public function query() { $this->ensureMyTable(); $field = $this->tableAlias . '.' . $this->realField . ' '; - $or = new Condition('OR'); + $or = db_or(); if (empty($this->value)) { $or->condition($field, '***CURRENT_USER***', '<>'); only in patch2: unchanged: --- a/core/modules/user/src/Tests/UserBlocksTest.php +++ b/core/modules/user/src/Tests/UserBlocksTest.php @@ -2,7 +2,6 @@ namespace Drupal\user\Tests; -use Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber; use Drupal\simpletest\WebTestBase; /** @@ -78,29 +77,9 @@ public function testUserLoginBlock() { // Now, log out and repeat with a non-403 page. $this->drupalLogout(); - $this->drupalGet('filter/tips'); - $this->assertEqual('MISS', $this->drupalGetHeader(DynamicPageCacheSubscriber::HEADER)); - $this->drupalPostForm(NULL, $edit, t('Log in')); - $this->assertNoText(t('User login'), 'Logged in.'); - $this->assertPattern('!!', 'Still on the same page after login for allowed page'); - - // Log out again and repeat with a non-403 page including query arguments. - $this->drupalLogout(); - $this->drupalGet('filter/tips', ['query' => ['foo' => 'bar']]); - $this->assertEqual('HIT', $this->drupalGetHeader(DynamicPageCacheSubscriber::HEADER)); - $this->drupalPostForm(NULL, $edit, t('Log in')); - $this->assertNoText(t('User login'), 'Logged in.'); - $this->assertPattern('!!', 'Still on the same page after login for allowed page'); - $this->assertTrue(strpos($this->getUrl(), '/filter/tips?foo=bar') !== FALSE, 'Correct query arguments are displayed after login'); - - // Repeat with different query arguments. - $this->drupalLogout(); - $this->drupalGet('filter/tips', ['query' => ['foo' => 'baz']]); - $this->assertEqual('HIT', $this->drupalGetHeader(DynamicPageCacheSubscriber::HEADER)); - $this->drupalPostForm(NULL, $edit, t('Log in')); + $this->drupalPostForm('filter/tips', $edit, t('Log in')); $this->assertNoText(t('User login'), 'Logged in.'); $this->assertPattern('!!', 'Still on the same page after login for allowed page'); - $this->assertTrue(strpos($this->getUrl(), '/filter/tips?foo=baz') !== FALSE, 'Correct query arguments are displayed after login'); // Check that the user login block is not vulnerable to information // disclosure to third party sites. only in patch2: unchanged: --- a/core/modules/user/src/Tests/Views/AccessRoleTest.php +++ b/core/modules/user/src/Tests/Views/AccessRoleTest.php @@ -126,7 +126,7 @@ public function testRenderCaching() { $account_switcher->switchTo($this->webUser); $result = $renderer->renderPlain($build); // @todo Fix this in https://www.drupal.org/node/2551037, - // DisplayPluginBase::applyDisplayCacheabilityMetadata() is not invoked when + // DisplayPluginBase::applyDisplayCachablityMetadata() is not invoked when // using buildBasicRenderable() and a Views access plugin returns FALSE. //$this->assertTrue(in_array('user.roles', $build['#cache']['contexts'])); //$this->assertEqual([], $build['#cache']['tags']); only in patch2: unchanged: --- a/core/modules/views/src/Entity/View.php +++ b/core/modules/views/src/Entity/View.php @@ -5,11 +5,8 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; use Drupal\Core\Config\Entity\ConfigEntityBase; -use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Language\LanguageInterface; -use Drupal\views\Plugin\DependentWithRemovalPluginInterface; use Drupal\views\Views; use Drupal\views\ViewEntityInterface; @@ -293,13 +290,10 @@ public function calculateDependencies() { public function preSave(EntityStorageInterface $storage) { parent::preSave($storage); - $displays = $this->get('display'); - - $this->fixTableNames($displays); - // Sort the displays. - ksort($displays); - $this->set('display', ['default' => $displays['default']] + $displays); + $display = $this->get('display'); + ksort($display); + $this->set('display', ['default' => $display['default']] + $display); // @todo Check whether isSyncing is needed. if (!$this->isSyncing()) { @@ -308,45 +302,6 @@ public function preSave(EntityStorageInterface $storage) { } /** - * Fixes table names for revision metadata fields of revisionable entities. - * - * Views for revisionable entity types using revision metadata fields might - * be using the wrong table to retrieve the fields after system_update_8300 - * has moved them correctly to the revision table. This method updates the - * views to use the correct tables. - * - * @param array &$displays - * An array containing display handlers of a view. - * - * @deprecated in Drupal 8.3.0, will be removed in Drupal 9.0.0. - */ - private function fixTableNames(array &$displays) { - // Fix wrong table names for entity revision metadata fields. - foreach ($displays as $display => $display_data) { - if (isset($display_data['display_options']['fields'])) { - foreach ($display_data['display_options']['fields'] as $property_name => $property_data) { - if (isset($property_data['entity_type']) && isset($property_data['field']) && isset($property_data['table'])) { - $entity_type = $this->entityTypeManager()->getDefinition($property_data['entity_type']); - // We need to update the table name only for revisionable entity - // types, otherwise the view is already using the correct table. - if (($entity_type instanceof ContentEntityTypeInterface) && is_subclass_of($entity_type->getClass(), FieldableEntityInterface::class) && $entity_type->isRevisionable()) { - $revision_metadata_fields = $entity_type->getRevisionMetadataKeys(); - // @see \Drupal\Core\Entity\Sql\SqlContentEntityStorage::initTableLayout() - $revision_table = $entity_type->getRevisionTable() ?: $entity_type->id() . '_revision'; - - // Check if this is a revision metadata field and if it uses the - // wrong table. - if (in_array($property_data['field'], $revision_metadata_fields) && $property_data['table'] != $revision_table) { - $displays[$display]['display_options']['fields'][$property_name]['table'] = $revision_table; - } - } - } - } - } - } - } - - /** * Fills in the cache metadata of this view. * * Cache metadata is set per view and per display, and ends up being stored in @@ -513,61 +468,4 @@ public function invalidateCaches() { \Drupal::service('cache_tags.invalidator')->invalidateTags($tags); } - /** - * {@inheritdoc} - */ - public function onDependencyRemoval(array $dependencies) { - $changed = FALSE; - - // Don't intervene if the views module is removed. - if (isset($dependencies['module']) && in_array('views', $dependencies['module'])) { - return FALSE; - } - - // If the base table for the View is provided by a module being removed, we - // delete the View because this is not something that can be fixed manually. - $views_data = Views::viewsData(); - $base_table = $this->get('base_table'); - $base_table_data = $views_data->get($base_table); - if (!empty($base_table_data['table']['provider']) && in_array($base_table_data['table']['provider'], $dependencies['module'])) { - return FALSE; - } - - $current_display = $this->getExecutable()->current_display; - $handler_types = Views::getHandlerTypes(); - - // Find all the handlers and check whether they want to do something on - // dependency removal. - foreach ($this->display as $display_id => $display_plugin_base) { - $this->getExecutable()->setDisplay($display_id); - $display = $this->getExecutable()->getDisplay(); - - foreach (array_keys($handler_types) as $handler_type) { - $handlers = $display->getHandlers($handler_type); - foreach ($handlers as $handler_id => $handler) { - if ($handler instanceof DependentWithRemovalPluginInterface) { - if ($handler->onDependencyRemoval($dependencies)) { - // Remove the handler and indicate we made changes. - unset($this->display[$display_id]['display_options'][$handler_types[$handler_type]['plural']][$handler_id]); - $changed = TRUE; - } - } - } - } - } - - // Disable the View if we made changes. - // @todo https://www.drupal.org/node/2832558 Give better feedback for - // disabled config. - if ($changed) { - // Force a recalculation of the dependencies if we made changes. - $this->getExecutable()->current_display = NULL; - $this->calculateDependencies(); - $this->disable(); - } - - $this->getExecutable()->setDisplay($current_display); - return $changed; - } - } only in patch2: unchanged: --- a/core/modules/views/src/ManyToOneHelper.php +++ b/core/modules/views/src/ManyToOneHelper.php @@ -2,7 +2,6 @@ namespace Drupal\views; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\HandlerBase; @@ -269,8 +268,8 @@ public function addFilter() { $options['group'] = 0; } - // If $add_condition is set to FALSE, a single expression is enough. If it - // is set to TRUE, conditions will be added. + // add_condition determines whether a single expression is enough(FALSE) or the + // conditions should be added via an db_or()/db_and() (TRUE). $add_condition = TRUE; if ($operator == 'not') { $value = NULL; @@ -327,7 +326,7 @@ public function addFilter() { if ($add_condition) { $field = $this->handler->realField; - $clause = $operator == 'or' ? new Condition('OR') : new Condition('AND'); + $clause = $operator == 'or' ? db_or() : db_and(); foreach ($this->handler->tableAliases as $value => $alias) { $clause->condition("$alias.$field", $value); } only in patch2: unchanged: --- a/core/modules/views/src/Plugin/DependentWithRemovalPluginInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - 'container', only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -2115,7 +2115,7 @@ public function render() { '#cache' => &$this->view->element['#cache'], ]; - $this->applyDisplayCacheabilityMetadata($this->view->element); + $this->applyDisplayCachablityMetadata($this->view->element); return $element; } @@ -2126,7 +2126,7 @@ public function render() { * @param array $element * The render array with updated cacheability metadata. */ - protected function applyDisplayCacheabilityMetadata(array &$element) { + protected function applyDisplayCachablityMetadata(array &$element) { /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache */ $cache = $this->getPlugin('cache'); @@ -2139,22 +2139,6 @@ protected function applyDisplayCacheabilityMetadata(array &$element) { } /** - * Applies the cacheability of the current display to the given render array. - * - * @param array $element - * The render array with updated cacheability metadata. - * - * @deprecated in Drupal 8.4.0, will be removed before Drupal 9.0. Use - * DisplayPluginBase::applyDisplayCacheabilityMetadata instead. - * - * @see \Drupal\views\Plugin\views\display\DisplayPluginBase::applyDisplayCacheabilityMetadata() - */ - protected function applyDisplayCachablityMetadata(array &$element) { - @trigger_error('The DisplayPluginBase::applyDisplayCachablityMetadata method is deprecated since version 8.4 and will be removed in 9.0. Use DisplayPluginBase::applyDisplayCacheabilityMetadata instead.', E_USER_DEPRECATED); - $this->applyDisplayCacheabilityMetadata($element); - } - - /** * {@inheritdoc} */ public function elementPreRender(array $element) { @@ -2346,7 +2330,7 @@ public function buildRenderable(array $args = [], $cache = TRUE) { // of cacheability metadata (e.g.: cache contexts), so they can bubble up. // Thus, we add the cacheability metadata first, then modify / remove the // cache keys depending on the $cache argument. - $this->applyDisplayCacheabilityMetadata($this->view->element); + $this->applyDisplayCachablityMetadata($this->view->element); if ($cache) { $this->view->element['#cache'] += ['keys' => []]; // Places like \Drupal\views\ViewExecutable::setCurrentPage() set up an only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/display/EntityReference.php +++ b/core/modules/views/src/Plugin/views/display/EntityReference.php @@ -2,8 +2,6 @@ namespace Drupal\views\Plugin\views\display; -use Drupal\Core\Database\Query\Condition; - /** * The plugin that handles an EntityReference display. * @@ -133,7 +131,7 @@ public function query() { } // Multiple search fields are OR'd together. - $conditions = new Condition('OR'); + $conditions = db_or(); // Build the condition using the selected search fields. foreach ($style_options['options']['search_fields'] as $field_id) { only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/display/Feed.php +++ b/core/modules/views/src/Plugin/views/display/Feed.php @@ -106,7 +106,7 @@ public function preview() { public function render() { $build = $this->view->style_plugin->render($this->view->result); - $this->applyDisplayCacheabilityMetadata($build); + $this->applyDisplayCachablityMetadata($build); return $build; } only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/field/EntityField.php +++ b/core/modules/views/src/Plugin/views/field/EntityField.php @@ -23,7 +23,6 @@ use Drupal\views\FieldAPIHandlerTrait; use Drupal\views\Entity\Render\EntityFieldRenderer; use Drupal\views\Plugin\views\display\DisplayPluginBase; -use Drupal\views\Plugin\DependentWithRemovalPluginInterface; use Drupal\views\ResultRow; use Drupal\views\ViewExecutable; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -35,7 +34,7 @@ * * @ViewsField("field") */ -class EntityField extends FieldPluginBase implements CacheableDependencyInterface, MultiItemsFieldHandlerInterface, DependentWithRemovalPluginInterface { +class EntityField extends FieldPluginBase implements CacheableDependencyInterface, MultiItemsFieldHandlerInterface { use FieldAPIHandlerTrait; use PluginDependencyTrait; @@ -1078,29 +1077,4 @@ public function getValue(ResultRow $values, $field = NULL) { } } - /** - * {@inheritdoc} - */ - public function onDependencyRemoval(array $dependencies) { - // See if this handler is responsible for any of the dependencies being - // removed. If this is the case, indicate that this handler needs to be - // removed from the View. - $remove = FALSE; - // Get all the current dependencies for this handler. - $current_dependencies = $this->calculateDependencies(); - foreach ($current_dependencies as $group => $dependency_list) { - // Check if any of the handler dependencies match the dependencies being - // removed. - foreach ($dependency_list as $config_key) { - if (isset($dependencies[$group]) && array_key_exists($config_key, $dependencies[$group])) { - // This handlers dependency matches a dependency being removed, - // indicate that this handler needs to be removed. - $remove = TRUE; - break 2; - } - } - } - return $remove; - } - } only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/filter/StringFilter.php +++ b/core/modules/views/src/Plugin/views/filter/StringFilter.php @@ -2,7 +2,6 @@ namespace Drupal\views\Plugin\views\filter; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; /** @@ -266,7 +265,7 @@ protected function opContains($field) { } protected function opContainsWord($field) { - $where = $this->operator == 'word' ? new Condition('OR') : new Condition('AND'); + $where = $this->operator == 'word' ? db_or() : db_and(); // Don't filter on empty strings. if (empty($this->value)) { only in patch2: unchanged: --- a/core/modules/views/src/Plugin/views/query/Sql.php +++ b/core/modules/views/src/Plugin/views/query/Sql.php @@ -5,7 +5,6 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\Cache; use Drupal\Core\Database\Database; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\display\DisplayPluginBase; @@ -831,7 +830,7 @@ public function clearFields() { * @code * $this->query->addWhere( * $this->options['group'], - * (new Condition('OR')) + * db_or() * ->condition($field, $value, 'NOT IN') * ->condition($field, $value, 'IS NULL') * ); @@ -1057,13 +1056,13 @@ protected function buildCondition($where = 'where') { $has_arguments = FALSE; $has_filter = FALSE; - $main_group = new Condition('AND'); - $filter_group = $this->groupOperator == 'OR' ? new Condition('OR') : new Condition('AND'); + $main_group = db_and(); + $filter_group = $this->groupOperator == 'OR' ? db_or() : db_and(); foreach ($this->$where as $group => $info) { if (!empty($info['conditions'])) { - $sub_group = $info['type'] == 'OR' ? new Condition('OR') : new Condition('AND'); + $sub_group = $info['type'] == 'OR' ? db_or() : db_and(); foreach ($info['conditions'] as $clause) { if ($clause['operator'] == 'formula') { $has_condition = TRUE; only in patch2: unchanged: --- a/core/modules/views/tests/src/Kernel/TestViewsTest.php +++ b/core/modules/views/tests/src/Kernel/TestViewsTest.php @@ -34,8 +34,7 @@ public function testDefaultConfig() { \Drupal::service('config.storage'), new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY), \Drupal::service('cache.discovery'), - \Drupal::service('module_handler'), - \Drupal::service('class_resolver') + \Drupal::service('module_handler') ); // Create a configuration storage with access to default configuration in only in patch2: unchanged: --- a/core/modules/views/tests/src/Kernel/ViewsConfigDependenciesIntegrationTest.php +++ b/core/modules/views/tests/src/Kernel/ViewsConfigDependenciesIntegrationTest.php @@ -5,7 +5,6 @@ use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\image\Entity\ImageStyle; -use Drupal\user\Entity\Role; use Drupal\views\Entity\View; /** @@ -18,7 +17,7 @@ class ViewsConfigDependenciesIntegrationTest extends ViewsKernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['field', 'file', 'image', 'entity_test', 'user', 'text']; + public static $modules = ['field', 'file', 'image', 'entity_test']; /** * {@inheritdoc} @@ -26,16 +25,6 @@ class ViewsConfigDependenciesIntegrationTest extends ViewsKernelTestBase { public static $testViews = ['entity_test_fields']; /** - * {@inheritdoc} - */ - protected function setUp($import_test_views = TRUE) { - parent::setUp($import_test_views); - - $this->installEntitySchema('user'); - $this->installSchema('user', ['users_data']); - } - - /** * Tests integration with image module. */ public function testImage() { @@ -80,81 +69,7 @@ public function testImage() { // Delete the 'foo' image style. $style->delete(); - $view = View::load('entity_test_fields'); - - // Checks that the view has not been deleted too. - $this->assertNotNull(View::load('entity_test_fields')); - - // Checks that the image field was removed from the View. - $display = $view->getDisplay('default'); - $this->assertFalse(isset($display['display_options']['fields']['bar'])); - - // Checks that the view has been disabled. - $this->assertFalse($view->status()); - - $dependencies = $view->getDependencies() + ['config' => []]; - // Checks that the dependency on style 'foo' has been removed. - $this->assertFalse(in_array('image.style.foo', $dependencies['config'])); - } - - /** - * Tests removing a config dependency that deletes the View. - */ - public function testConfigRemovalRole() { - // Create a role we can add to the View and delete. - $role = Role::create([ - 'id' => 'dummy', - 'label' => 'dummy', - ]); - - $role->save(); - - /** @var \Drupal\views\ViewEntityInterface $view */ - $view = View::load('entity_test_fields'); - $display = &$view->getDisplay('default'); - - // Set the access to be restricted by the dummy role. - $display['display_options']['access'] = [ - 'type' => 'role', - 'options' => [ - 'role' => [ - $role->id() => $role->id(), - ], - ], - ]; - $view->save(); - - // Check that the View now has a dependency on the Role. - $dependencies = $view->getDependencies() + ['config' => []]; - $this->assertTrue(in_array('user.role.dummy', $dependencies['config'])); - - // Delete the role. - $role->delete(); - - $view = View::load('entity_test_fields'); - // Checks that the view has been deleted too. - $this->assertNull($view); - } - - /** - * Tests uninstalling a module that provides a base table for a View. - */ - public function testConfigRemovalBaseTable() { - // Find all the entity types provided by the entity_test module and install - // the schema for them so we can uninstall them. - $entities = \Drupal::entityTypeManager()->getDefinitions(); - foreach ($entities as $entity_type_id => $definition) { - if ($definition->getProvider() == 'entity_test') { - $this->installEntitySchema($entity_type_id); - }; - } - - // Check that removing the module that provides the base table for a View, - // deletes the View. - $this->assertNotNull(View::load('entity_test_fields')); - $this->container->get('module_installer')->uninstall(['entity_test']); - // Check that the View has been deleted. $this->assertNull(View::load('entity_test_fields')); } only in patch2: unchanged: --- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php +++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Config\Entity\ConfigEntityType; use Drupal\Core\Entity\ContentEntityType; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Sql\DefaultTableMapping; use Drupal\Core\Field\BaseFieldDefinition; @@ -1086,7 +1087,7 @@ public function setEntityType(EntityTypeInterface $entity_type) { } -class TestEntityType extends ContentEntityType { +class TestEntityType extends EntityType { /** * Sets a specific entity key. only in patch2: unchanged: --- a/core/modules/views/views.post_update.php +++ b/core/modules/views/views.post_update.php @@ -201,15 +201,3 @@ function views_post_update_boolean_filter_values() { function views_post_update_grouped_filters() { // Empty update to cause a cache rebuild so that the schema changes are read. } - -/** - * Fix table names for revision metadata fields. - */ -function views_post_update_revision_metadata_fields() { - // The table names are fixed automatically in - // \Drupal\views\Entity\View::preSave(), so we just need to re-save all views. - $views = View::loadMultiple(); - array_walk($views, function(View $view) { - $view->save(); - }); -} only in patch2: unchanged: --- a/core/modules/workflows/src/Form/WorkflowEditForm.php +++ b/core/modules/workflows/src/Form/WorkflowEditForm.php @@ -191,6 +191,7 @@ public function save(array $form, FormStateInterface $form_state) { $workflow = $this->entity; $workflow->save(); drupal_set_message($this->t('Saved the %label Workflow.', ['%label' => $workflow->label()])); + $form_state->setRedirectUrl($workflow->toUrl('collection')); } /** only in patch2: unchanged: --- a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php +++ b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php @@ -176,8 +176,9 @@ public function testWorkflowCreation() { $workflow = $workflow_storage->loadUnchanged('test'); $this->assertEquals('draft', $workflow->getInitialState()->id()); - // Verify that we are still on the workflow edit page. - $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test'); + // This will take us to the list of workflows, so we need to edit the + // workflow again. + $this->clickLink('Edit'); // Ensure that weight changes the transition ordering. $this->assertEquals(['publish', 'create_new_draft'], array_keys($workflow->getTransitions())); @@ -186,8 +187,9 @@ public function testWorkflowCreation() { $workflow = $workflow_storage->loadUnchanged('test'); $this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTransitions())); - // Verify that we are still on the workflow edit page. - $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test'); + // This will take us to the list of workflows, so we need to edit the + // workflow again. + $this->clickLink('Edit'); // Ensure that a delete link for the published state exists before deleting // the draft state. only in patch2: unchanged: --- a/core/modules/workflows/tests/src/Unit/StateTest.php +++ b/core/modules/workflows/tests/src/Unit/StateTest.php @@ -27,9 +27,6 @@ protected function setUp() { // mocked. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_type->deleteState(Argument::any())->willReturn(NULL); only in patch2: unchanged: --- a/core/modules/workflows/tests/src/Unit/TransitionTest.php +++ b/core/modules/workflows/tests/src/Unit/TransitionTest.php @@ -27,9 +27,6 @@ protected function setUp() { // mocked. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_manager = $this->prophesize(WorkflowTypeManager::class); only in patch2: unchanged: --- a/core/modules/workflows/tests/src/Unit/WorkflowTest.php +++ b/core/modules/workflows/tests/src/Unit/WorkflowTest.php @@ -27,9 +27,6 @@ protected function setUp() { // mocked. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_manager = $this->prophesize(WorkflowTypeManager::class); @@ -218,9 +215,6 @@ public function testDeleteState() { // correctly. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_type->deleteState('draft')->shouldBeCalled(); @@ -642,9 +636,6 @@ public function testDeleteTransition() { // correctly. $container = new ContainerBuilder(); $workflow_type = $this->prophesize(WorkflowTypeInterface::class); - $workflow_type->setConfiguration(Argument::any())->will(function ($arguments) { - $this->getConfiguration()->willReturn($arguments[0]); - }); $workflow_type->decorateState(Argument::any())->willReturnArgument(0); $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); $workflow_type->deleteTransition('publish')->shouldBeCalled(); only in patch2: unchanged: --- a/core/scripts/run-tests.sh +++ b/core/scripts/run-tests.sh @@ -17,7 +17,6 @@ use Drupal\simpletest\Form\SimpletestResultsForm; use Drupal\simpletest\TestBase; use Drupal\simpletest\TestDiscovery; -use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; $autoloader = require_once __DIR__ . '/../../autoload.php'; @@ -37,7 +36,7 @@ const SIMPLETEST_SCRIPT_EXIT_FAILURE = 1; const SIMPLETEST_SCRIPT_EXIT_EXCEPTION = 2; -if (!class_exists(TestCase::class)) { +if (!class_exists('\PHPUnit_Framework_TestCase')) { echo "\nrun-tests.sh requires the PHPUnit testing framework. Please use 'composer install --dev' to ensure that it is present.\n\n"; exit(SIMPLETEST_SCRIPT_EXIT_FAILURE); } @@ -784,7 +783,7 @@ function simpletest_script_run_one_test($test_id, $test_class) { $methods = array(); } $test = new $class_name($test_id); - if (is_subclass_of($test_class, TestCase::class)) { + if (is_subclass_of($test_class, '\PHPUnit_Framework_TestCase')) { $status = simpletest_script_run_phpunit($test_id, $test_class); } else { @@ -866,7 +865,7 @@ function simpletest_script_command($test_id, $test_class) { * @see simpletest_script_run_one_test() */ function simpletest_script_cleanup($test_id, $test_class, $exitcode) { - if (is_subclass_of($test_class, TestCase::class)) { + if (is_subclass_of($test_class, '\PHPUnit_Framework_TestCase')) { // PHPUnit test, move on. return; } @@ -1021,7 +1020,7 @@ function simpletest_script_get_test_list() { else { foreach ($matches[1] as $class_name) { $namespace_class = $namespace . '\\' . $class_name; - if (is_subclass_of($namespace_class, '\Drupal\simpletest\TestBase') || is_subclass_of($namespace_class, TestCase::class)) { + if (is_subclass_of($namespace_class, '\Drupal\simpletest\TestBase') || is_subclass_of($namespace_class, '\PHPUnit_Framework_TestCase')) { $test_list[] = $namespace_class; } } @@ -1075,7 +1074,7 @@ function simpletest_script_get_test_list() { else { foreach ($matches[1] as $class_name) { $namespace_class = $namespace . '\\' . $class_name; - if (is_subclass_of($namespace_class, '\Drupal\simpletest\TestBase') || is_subclass_of($namespace_class, TestCase::class)) { + if (is_subclass_of($namespace_class, '\Drupal\simpletest\TestBase') || is_subclass_of($namespace_class, '\PHPUnit_Framework_TestCase')) { $test_list[] = $namespace_class; } } only in patch2: unchanged: --- a/core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php +++ b/core/tests/Drupal/FunctionalTests/HttpKernel/CorsIntegrationTest.php @@ -2,7 +2,6 @@ namespace Drupal\FunctionalTests\HttpKernel; -use Drupal\Core\Url; use Drupal\Tests\BrowserTestBase; /** @@ -73,19 +72,6 @@ public function testCrossSiteRequest() { $this->drupalGet('/test-page', [], ['Origin' => 'http://example.com']); $this->assertSession()->statusCodeEquals(200); $this->assertSession()->responseHeaderEquals('Access-Control-Allow-Origin', 'http://example.com'); - - // Verify POST still functions with 'Origin' header set to site's domain. - $origin = \Drupal::request()->getSchemeAndHttpHost(); - - /** @var \GuzzleHttp\ClientInterface $httpClient */ - $httpClient = $this->getSession()->getDriver()->getClient()->getClient(); - $url = Url::fromUri('base:/test-page'); - $response = $httpClient->request('POST', $url->setAbsolute()->toString(), [ - 'headers' => [ - 'Origin' => $origin, - ] - ]); - $this->assertEquals(200, $response->getStatusCode()); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/AssertLegacyTrait.php +++ b/core/tests/Drupal/KernelTests/AssertLegacyTrait.php @@ -6,7 +6,7 @@ * Translates Simpletest assertion methods to PHPUnit. * * Protected methods are custom. Public static methods override methods of - * \PHPUnit\Framework\Assert. + * \PHPUnit_Framework_Assert. * * @deprecated Scheduled for removal in Drupal 9.0.0. Use PHPUnit's native * assert methods instead. only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Config/TypedConfigTest.php +++ /dev/null @@ -1,146 +0,0 @@ -installConfig('config_test'); - } - - /** - * Verifies that the Typed Data API is implemented correctly. - */ - public function testTypedDataAPI() { - /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */ - $typed_config_manager = \Drupal::service('config.typed'); - /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */ - $typed_config = $typed_config_manager->get('config_test.validation'); - - // Test a primitive. - $string_data = $typed_config->get('llama'); - $this->assertInstanceOf(StringInterface::class, $string_data); - $this->assertEquals('llama', $string_data->getValue()); - - // Test complex data. - $mapping = $typed_config->get('cat'); - /** @var \Drupal\Core\TypedData\ComplexDataInterface $mapping */ - $this->assertInstanceOf(ComplexDataInterface::class, $mapping); - $this->assertInstanceOf(StringInterface::class, $mapping->get('type')); - $this->assertEquals('kitten', $mapping->get('type')->getValue()); - $this->assertInstanceOf(IntegerInterface::class, $mapping->get('count')); - $this->assertEquals(2, $mapping->get('count')->getValue()); - // Verify the item metadata is available. - $this->assertInstanceOf(ComplexDataDefinitionInterface::class, $mapping->getDataDefinition()); - $this->assertArrayHasKey('type', $mapping->getProperties()); - $this->assertArrayHasKey('count', $mapping->getProperties()); - - // Test accessing sequences. - $sequence = $typed_config->get('giraffe'); - /** @var \Drupal\Core\TypedData\ListInterface $sequence */ - $this->assertInstanceOf(ComplexDataInterface::class, $sequence); - $this->assertInstanceOf(StringInterface::class, $sequence->get('hum1')); - $this->assertEquals('hum1', $sequence->get('hum1')->getValue()); - $this->assertEquals('hum2', $sequence->get('hum2')->getValue()); - $this->assertEquals(2, count($sequence->getIterator())); - // Verify the item metadata is available. - $this->assertInstanceOf(SequenceDataDefinition::class, $sequence->getDataDefinition()); - } - - /** - * Tests config validation via the Typed Data API. - */ - public function testSimpleConfigValidation() { - $config = \Drupal::configFactory()->getEditable('config_test.validation'); - /** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager */ - $typed_config_manager = \Drupal::service('config.typed'); - /** @var \Drupal\Core\Config\Schema\TypedConfigInterface $typed_config */ - $typed_config = $typed_config_manager->get('config_test.validation'); - - $result = $typed_config->validate(); - $this->assertInstanceOf(ConstraintViolationListInterface::class, $result); - $this->assertEmpty($result); - - // Test constraints on primitive types. - $config->set('llama', 'elephant'); - $config->save(); - - $typed_config = $typed_config_manager->get('config_test.validation'); - $result = $typed_config->validate(); - // Its not a valid llama anymore. - $this->assertCount(1, $result); - $this->assertEquals('no valid llama', $result->get(0)->getMessage()); - - // Test constraints on mapping. - $config->set('llama', 'llama'); - $config->set('cat.type', 'nyans'); - $config->save(); - - $typed_config = $typed_config_manager->get('config_test.validation'); - $result = $typed_config->validate(); - $this->assertEmpty($result); - - // Test constrains on nested mapping. - $config->set('cat.type', 'miaus'); - $config->save(); - - $typed_config = $typed_config_manager->get('config_test.validation'); - $result = $typed_config->validate(); - $this->assertCount(1, $result); - $this->assertEquals('no valid cat', $result->get(0)->getMessage()); - - // Test constrains on sequences elements. - $config->set('cat.type', 'nyans'); - $config->set('giraffe', ['muh', 'hum2']); - $config->save(); - $typed_config = $typed_config_manager->get('config_test.validation'); - $result = $typed_config->validate(); - $this->assertCount(1, $result); - $this->assertEquals('Giraffes just hum', $result->get(0)->getMessage()); - - // Test constrains on the sequence itself. - $config->set('giraffe', ['hum', 'hum2', 'invalid-key' => 'hum']); - $config->save(); - - $typed_config = $typed_config_manager->get('config_test.validation'); - $result = $typed_config->validate(); - $this->assertCount(1, $result); - $this->assertEquals('giraffe', $result->get(0)->getPropertyPath()); - $this->assertEquals('Invalid giraffe key.', $result->get(0)->getMessage()); - - // Validates mapping. - $typed_config = $typed_config_manager->get('config_test.validation'); - $value = $typed_config->getValue(); - unset($value['giraffe']); - $value['elephant'] = 'foo'; - $typed_config->setValue($value); - $result = $typed_config->validate(); - $this->assertCount(1, $result); - $this->assertEquals('', $result->get(0)->getPropertyPath()); - $this->assertEquals('Missing giraffe.', $result->get(0)->getMessage()); - } - -} only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php @@ -47,7 +47,6 @@ public function testSchemaMapping() { $expected['class'] = Undefined::class; $expected['type'] = 'undefined'; $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for nonexistent configuration.'); // Configuration file without schema will return Undefined as well. @@ -68,7 +67,6 @@ public function testSchemaMapping() { $expected['mapping']['testlist'] = ['label' => 'Test list']; $expected['type'] = 'config_schema_test.someschema'; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for configuration with only some schema.'); // Check type detection on elements with undefined types. @@ -79,7 +77,6 @@ public function testSchemaMapping() { $expected['class'] = Undefined::class; $expected['type'] = 'undefined'; $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Automatic type detected for a scalar is undefined.'); $definition = $config->get('testlist')->getDataDefinition()->toArray(); $expected = []; @@ -87,7 +84,6 @@ public function testSchemaMapping() { $expected['class'] = Undefined::class; $expected['type'] = 'undefined'; $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Automatic type detected for a list is undefined.'); $definition = $config->get('testnoschema')->getDataDefinition()->toArray(); $expected = []; @@ -95,7 +91,6 @@ public function testSchemaMapping() { $expected['class'] = Undefined::class; $expected['type'] = 'undefined'; $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Automatic type detected for an undefined integer is undefined.'); // Simple case, straight metadata. @@ -114,7 +109,6 @@ public function testSchemaMapping() { $expected['mapping']['_core']['type'] = '_core_config_info'; $expected['type'] = 'system.maintenance'; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for system.maintenance'); // Mixed schema with ignore elements. @@ -145,7 +139,6 @@ public function testSchemaMapping() { 'type' => 'integer', ]; $expected['type'] = 'config_schema_test.ignore'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected); @@ -156,7 +149,6 @@ public function testSchemaMapping() { $expected['label'] = 'Irrelevant'; $expected['class'] = Ignore::class; $expected['definition_class'] = '\Drupal\Core\TypedData\DataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected); $definition = \Drupal::service('config.typed')->get('config_schema_test.ignore')->get('indescribable')->getDataDefinition()->toArray(); $expected['label'] = 'Indescribable'; @@ -168,7 +160,6 @@ public function testSchemaMapping() { $expected['label'] = 'Image style'; $expected['class'] = Mapping::class; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $expected['mapping']['name']['type'] = 'string'; $expected['mapping']['uuid']['type'] = 'string'; $expected['mapping']['uuid']['label'] = 'UUID'; @@ -202,7 +193,6 @@ public function testSchemaMapping() { $expected['label'] = 'Image scale'; $expected['class'] = Mapping::class; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $expected['mapping']['width']['type'] = 'integer'; $expected['mapping']['width']['label'] = 'Width'; $expected['mapping']['height']['type'] = 'integer'; @@ -230,7 +220,6 @@ public function testSchemaMapping() { $expected['label'] = 'Mapping'; $expected['class'] = Mapping::class; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $expected['mapping'] = [ 'integer' => ['type' => 'integer'], 'string' => ['type' => 'string'], @@ -252,7 +241,6 @@ public function testSchemaMapping() { $expected['mapping']['testdescription']['label'] = 'Description'; $expected['type'] = 'config_schema_test.someschema.somemodule.*.*'; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $this->assertEqual($definition, $expected, 'Retrieved the right metadata for config_schema_test.someschema.somemodule.section_one.subsection'); @@ -275,7 +263,6 @@ public function testSchemaMappingWithParents() { 'label' => 'Test item nested one level', 'class' => StringData::class, 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', - 'unwrap_for_canonical_representation' => TRUE, ]; $this->assertEqual($definition, $expected); @@ -287,7 +274,6 @@ public function testSchemaMappingWithParents() { 'label' => 'Test item nested two levels', 'class' => StringData::class, 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', - 'unwrap_for_canonical_representation' => TRUE, ]; $this->assertEqual($definition, $expected); @@ -299,7 +285,6 @@ public function testSchemaMappingWithParents() { 'label' => 'Test item nested three levels', 'class' => StringData::class, 'definition_class' => '\Drupal\Core\TypedData\DataDefinition', - 'unwrap_for_canonical_representation' => TRUE, ]; $this->assertEqual($definition, $expected); } @@ -411,76 +396,6 @@ public function testConfigSaveWithSchema() { } /** - * Tests configuration sequence sorting using schemas. - */ - public function testConfigSaveWithSequenceSorting() { - $data = [ - 'keyed_sort' => [ - 'b' => '1', - 'a' => '2', - ], - 'no_sort' => [ - 'b' => '2', - 'a' => '1', - ], - ]; - // Save config which has a schema that enforces sorting. - $this->config('config_schema_test.schema_sequence_sort') - ->setData($data) - ->save(); - $this->assertSame(['a' => '2', 'b' => '1'], $this->config('config_schema_test.schema_sequence_sort')->get('keyed_sort')); - $this->assertSame(['b' => '2', 'a' => '1'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort')); - - $data = [ - 'value_sort' => ['b', 'a'], - 'no_sort' => ['b', 'a'], - ]; - // Save config which has a schema that enforces sorting. - $this->config('config_schema_test.schema_sequence_sort') - ->setData($data) - ->save(); - - $this->assertSame(['a', 'b'], $this->config('config_schema_test.schema_sequence_sort')->get('value_sort')); - $this->assertSame(['b', 'a'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort')); - - // Value sort does not preserve keys - this is intentional. - $data = [ - 'value_sort' => [1 => 'b', 2 => 'a'], - 'no_sort' => [1 => 'b', 2 => 'a'], - ]; - // Save config which has a schema that enforces sorting. - $this->config('config_schema_test.schema_sequence_sort') - ->setData($data) - ->save(); - - $this->assertSame(['a', 'b'], $this->config('config_schema_test.schema_sequence_sort')->get('value_sort')); - $this->assertSame([1 => 'b', 2 => 'a'], $this->config('config_schema_test.schema_sequence_sort')->get('no_sort')); - - // Test sorts do not destroy complex values. - $data = [ - 'complex_sort_value' => [['foo' => 'b', 'bar' => 'b'] , ['foo' => 'a', 'bar' => 'a']], - 'complex_sort_key' => ['b' => ['foo' => '1', 'bar' => '1'] , 'a' => ['foo' => '2', 'bar' => '2']], - ]; - $this->config('config_schema_test.schema_sequence_sort') - ->setData($data) - ->save(); - $this->assertSame([['foo' => 'a', 'bar' => 'a'], ['foo' => 'b', 'bar' => 'b']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_value')); - $this->assertSame(['a' => ['foo' => '2', 'bar' => '2'], 'b' => ['foo' => '1', 'bar' => '1']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_key')); - - // Swap the previous test scenario around. - $data = [ - 'complex_sort_value' => ['b' => ['foo' => '1', 'bar' => '1'] , 'a' => ['foo' => '2', 'bar' => '2']], - 'complex_sort_key' => [['foo' => 'b', 'bar' => 'b'] , ['foo' => 'a', 'bar' => 'a']], - ]; - $this->config('config_schema_test.schema_sequence_sort') - ->setData($data) - ->save(); - $this->assertSame([['foo' => '1', 'bar' => '1'], ['foo' => '2', 'bar' => '2']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_value')); - $this->assertSame([['foo' => 'b', 'bar' => 'b'], ['foo' => 'a', 'bar' => 'a']], $this->config('config_schema_test.schema_sequence_sort')->get('complex_sort_key')); - - } - - /** * Tests fallback to a greedy wildcard. */ public function testSchemaFallback() { @@ -490,7 +405,6 @@ public function testSchemaFallback() { $expected['label'] = 'Schema wildcard fallback test'; $expected['class'] = Mapping::class; $expected['definition_class'] = '\Drupal\Core\TypedData\MapDataDefinition'; - $expected['unwrap_for_canonical_representation'] = TRUE; $expected['mapping']['langcode']['type'] = 'string'; $expected['mapping']['langcode']['label'] = 'Language code'; $expected['mapping']['_core']['type'] = '_core_config_info'; only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php @@ -3,7 +3,6 @@ namespace Drupal\KernelTests\Core\Database; use Drupal\Core\Database\Database; -use Drupal\Core\Database\Query\Condition; use Drupal\Core\Database\RowCountException; use Drupal\user\Entity\User; @@ -313,7 +312,7 @@ public function testNestedConditions() { $query = db_select('test'); $query->addField('test', 'job'); $query->condition('name', 'Paul'); - $query->condition((new Condition('OR'))->condition('age', 26)->condition('age', 27)); + $query->condition(db_or()->condition('age', 26)->condition('age', 27)); $job = $query->execute()->fetchField(); $this->assertEqual($job, 'Songwriter', 'Correct data retrieved.'); @@ -396,7 +395,7 @@ public function testSelectWithRowCount() { public function testJoinConditionObject() { // Same test as testDefaultJoin, but with a Condition object. $query = db_select('test_task', 't'); - $join_cond = (new Condition('AND'))->where('t.pid = p.id'); + $join_cond = db_and()->where('t.pid = p.id'); $people_alias = $query->join('test', 'p', $join_cond); $name_field = $query->addField($people_alias, 'name', 'name'); $query->addField('t', 'task', 'task'); @@ -419,7 +418,7 @@ public function testJoinConditionObject() { // Test a condition object that creates placeholders. $t1_name = 'John'; $t2_name = 'George'; - $join_cond = (new Condition('AND')) + $join_cond = db_and() ->condition('t1.name', $t1_name) ->condition('t2.name', $t2_name); $query = db_select('test', 't1'); only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Database/UpdateComplexTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/UpdateComplexTest.php @@ -2,8 +2,6 @@ namespace Drupal\KernelTests\Core\Database; -use Drupal\Core\Database\Query\Condition; - /** * Tests the Update query builder, complex queries. * @@ -17,7 +15,7 @@ class UpdateComplexTest extends DatabaseTestBase { public function testOrConditionUpdate() { $update = db_update('test') ->fields(['job' => 'Musician']) - ->condition((new Condition('OR')) + ->condition(db_or() ->condition('name', 'John') ->condition('name', 'Paul') ); only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php +++ b/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php @@ -184,11 +184,6 @@ public function testPreventChangeOfSitePath() { $pass = TRUE; } $this->assertTrue($pass, 'Throws LogicException if DrupalKernel::setSitePath() is called after boot'); - - // Ensure no LogicException if DrupalKernel::setSitePath() is called with - // identical path after boot. - $path = $kernel->getSitePath(); - $kernel->setSitePath($path); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityTypedDataDefinitionTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityTypedDataDefinitionTest.php @@ -101,8 +101,8 @@ public function testEntities() { // Test that the definition factory creates the right definitions for all // entity data types variants. - $this->assertEqual(serialize($this->typedDataManager->createDataDefinition('entity')), serialize(EntityDataDefinition::create())); - $this->assertEqual(serialize($this->typedDataManager->createDataDefinition('entity:node')), serialize(EntityDataDefinition::create('node'))); + $this->assertEqual($this->typedDataManager->createDataDefinition('entity'), EntityDataDefinition::create()); + $this->assertEqual($this->typedDataManager->createDataDefinition('entity:node'), EntityDataDefinition::create('node')); // Config entities don't support typed data. $entity_definition = EntityDataDefinition::create('node_type'); @@ -123,7 +123,7 @@ public function testEntityReferences() { // Test that the definition factory creates the right definition object. $reference_definition2 = $this->typedDataManager->createDataDefinition('entity_reference'); $this->assertTrue($reference_definition2 instanceof DataReferenceDefinitionInterface); - $this->assertEqual(serialize($reference_definition2), serialize($reference_definition)); + $this->assertEqual($reference_definition2, $reference_definition); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/RevisionableContentEntityBaseTest.php @@ -2,12 +2,9 @@ namespace Drupal\KernelTests\Core\Entity; -use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\entity_test_revlog\Entity\EntityTestMulWithRevisionLog; +use Drupal\entity_test\Entity\EntityTestWithRevisionLog; use Drupal\KernelTests\KernelTestBase; use Drupal\user\Entity\User; -use Drupal\user\UserInterface; /** * @coversDefaultClass \Drupal\Core\Entity\RevisionableContentEntityBase @@ -18,7 +15,7 @@ class RevisionableContentEntityBaseTest extends KernelTestBase { /** * {@inheritdoc} */ - public static $modules = ['entity_test_revlog', 'system', 'user']; + public static $modules = ['entity_test', 'system', 'user']; /** * {@inheritdoc} @@ -26,102 +23,34 @@ class RevisionableContentEntityBaseTest extends KernelTestBase { protected function setUp() { parent::setUp(); - $this->installEntitySchema('entity_test_mul_revlog'); + $this->installEntitySchema('entity_test_revlog'); $this->installEntitySchema('user'); $this->installSchema('system', 'sequences'); } - /** - * Tests the correct functionality CRUD operations of entity revisions. - */ public function testRevisionableContentEntity() { - $entity_type = 'entity_test_mul_revlog'; - $definition = \Drupal::entityManager()->getDefinition($entity_type); $user = User::create(['name' => 'test name']); $user->save(); - /** @var \Drupal\entity_test_mul_revlog\Entity\EntityTestMulWithRevisionLog $entity */ - $entity = EntityTestMulWithRevisionLog::create([ - 'type' => $entity_type, + /** @var \Drupal\entity_test\Entity\EntityTestWithRevisionLog $entity */ + $entity = EntityTestWithRevisionLog::create([ + 'type' => 'entity_test_revlog', ]); - - // Save the entity, this creates the first revision. $entity->save(); - $revision_ids[] = $entity->getRevisionId(); - $this->assertItemsTableCount(1, $definition); - // Create the second revision. $entity->setNewRevision(TRUE); $random_timestamp = rand(1e8, 2e8); - $this->createRevision($entity, $user, $random_timestamp, 'This is my log message'); + $entity->setRevisionCreationTime($random_timestamp); + $entity->setRevisionUserId($user->id()); + $entity->setRevisionLogMessage('This is my log message'); + $entity->save(); $revision_id = $entity->getRevisionId(); - $revision_ids[] = $revision_id; - $storage = \Drupal::entityTypeManager()->getStorage('entity_test_mul_revlog'); - $entity = $storage->loadRevision($revision_id); + $entity = \Drupal::entityTypeManager()->getStorage('entity_test_revlog')->loadRevision($revision_id); $this->assertEquals($random_timestamp, $entity->getRevisionCreationTime()); $this->assertEquals($user->id(), $entity->getRevisionUserId()); $this->assertEquals($user->id(), $entity->getRevisionUser()->id()); $this->assertEquals('This is my log message', $entity->getRevisionLogMessage()); - - // Create the third revision. - $random_timestamp = rand(1e8, 2e8); - $this->createRevision($entity, $user, $random_timestamp, 'This is my log message'); - $this->assertItemsTableCount(3, $definition); - $revision_ids[] = $entity->getRevisionId(); - - // Create another 3 revisions. - foreach (range(1, 3) as $count) { - $timestamp = rand(1e8, 2e8); - $this->createRevision($entity, $user, $timestamp, 'This is my log message number: ' . $count); - $revision_ids[] = $entity->getRevisionId(); - } - $this->assertItemsTableCount(6, $definition); - - $this->assertEqual(6, count($revision_ids)); - - // Delete the first 3 revisions. - foreach (range(0, 2) as $key) { - $storage->deleteRevision($revision_ids[$key]); - } - - // We should have only data for three revisions. - $this->assertItemsTableCount(3, $definition); - } - - /** - * Asserts the ammount of items on entity related tables. - * - * @param int $count - * The number of items expected to be in revisions related tables. - * @param \Drupal\Core\Entity\EntityTypeInterface $definition - * The definition and metada of the entity being tested. - */ - protected function assertItemsTableCount($count, EntityTypeInterface $definition) { - $this->assertEqual(1, db_query('SELECT COUNT(*) FROM {' . $definition->getBaseTable() . '}')->fetchField()); - $this->assertEqual(1, db_query('SELECT COUNT(*) FROM {' . $definition->getDataTable() . '}')->fetchField()); - $this->assertEqual($count, db_query('SELECT COUNT(*) FROM {' . $definition->getRevisionTable() . '}')->fetchField()); - $this->assertEqual($count, db_query('SELECT COUNT(*) FROM {' . $definition->getRevisionDataTable() . '}')->fetchField()); - } - - /** - * Creates a new revision in the entity of this test class. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity where revision will be created. - * @param \Drupal\user\UserInterface $user - * The author of the new revision. - * @param int $timestamp - * The timestamp of the new revision. - * @param string $log_message - * The log message of the new revision. - */ - protected function createRevision(EntityInterface $entity, UserInterface $user, $timestamp, $log_message) { - $entity->setNewRevision(TRUE); - $entity->setRevisionCreationTime($timestamp); - $entity->setRevisionUserId($user->id()); - $entity->setRevisionLogMessage($log_message); - $entity->save(); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Form/FormValidationMessageOrderTest.php +++ /dev/null @@ -1,92 +0,0 @@ - 'textfield', - '#title' => 'One', - '#required' => TRUE, - '#weight' => 40, - ]; - $form['two'] = [ - '#type' => 'textfield', - '#title' => 'Two', - '#required' => TRUE, - '#weight' => 30, - ]; - $form['three'] = [ - '#type' => 'textfield', - '#title' => 'Three', - '#required' => TRUE, - '#weight' => 10, - ]; - $form['four'] = [ - '#type' => 'textfield', - '#title' => 'Four', - '#required' => TRUE, - '#weight' => 20, - ]; - $form['actions'] = [ - '#type' => 'actions', - 'submit' => [ - '#type' => 'submit', - '#value' => 'Submit', - ], - ]; - return $form; - } - - /** - * {@inheritdoc} - */ - public function validateForm(array &$form, FormStateInterface $form_state) { - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - } - - /** - * Tests that fields validation messages are sorted in the fields order. - */ - public function testLimitValidationErrors() { - $form_state = new FormState(); - $form_builder = $this->container->get('form_builder'); - $form_builder->submitForm($this, $form_state); - - $messages = drupal_get_messages(); - $this->assertTrue(isset($messages['error'])); - $error_messages = $messages['error']; - $this->assertEqual($error_messages[0], 'Three field is required.'); - $this->assertEqual($error_messages[1], 'Four field is required.'); - $this->assertEqual($error_messages[2], 'Two field is required.'); - $this->assertEqual($error_messages[3], 'One field is required.'); - } - -} only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Routing/ExceptionHandlingTest.php +++ b/core/tests/Drupal/KernelTests/Core/Routing/ExceptionHandlingTest.php @@ -155,7 +155,7 @@ public function testBacktraceEscaping() { $kernel = \Drupal::getContainer()->get('http_kernel'); $response = $kernel->handle($request)->prepare($request); $this->assertEqual($response->getStatusCode(), Response::HTTP_INTERNAL_SERVER_ERROR); - $this->assertEqual($response->headers->get('Content-type'), 'text/plain; charset=UTF-8'); + $this->assertEqual($response->headers->get('Content-type'), 'text/html; charset=UTF-8'); // Test both that the backtrace is properly escaped, and that the unescaped // string is not output at all. @@ -178,7 +178,7 @@ public function testExceptionEscaping() { $kernel = \Drupal::getContainer()->get('http_kernel'); $response = $kernel->handle($request)->prepare($request); $this->assertEqual($response->getStatusCode(), Response::HTTP_INTERNAL_SERVER_ERROR); - $this->assertEqual($response->headers->get('Content-type'), 'text/plain; charset=UTF-8'); + $this->assertEqual($response->headers->get('Content-type'), 'text/html; charset=UTF-8'); // Test message is properly escaped, and that the unescaped string is not // output at all. @@ -192,11 +192,10 @@ public function testExceptionEscaping() { $kernel = \Drupal::getContainer()->get('http_kernel'); $response = $kernel->handle($request)->prepare($request); // As the Content-type is text/plain the fact that the raw string is - // contained in the output would not matter, but because it is output by the - // final exception subscriber, it is printed as partial HTML, and hence - // escaped. + // contained in the output does not matter. $this->assertEqual($response->headers->get('Content-type'), 'text/plain; charset=UTF-8'); - $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.

Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException: Not acceptable format: json<script>alert(123);</script> in ', $response->getContent()); + $this->setRawContent($response->getContent()); + $this->assertRaw($string); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php +++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigWhiteListTest.php @@ -42,7 +42,6 @@ class TwigWhiteListTest extends KernelTestBase { */ protected function setUp() { parent::setUp(); - \Drupal::service('theme_handler')->install(['test_theme']); $this->installSchema('system', ['sequences']); $this->installEntitySchema('node'); $this->installEntitySchema('user'); only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/Core/TypedData/TypedDataDefinitionTest.php +++ b/core/tests/Drupal/KernelTests/Core/TypedData/TypedDataDefinitionTest.php @@ -77,7 +77,7 @@ public function testMaps() { $map_definition2->setPropertyDefinition('one', DataDefinition::create('string')) ->setPropertyDefinition('two', DataDefinition::create('string')) ->setPropertyDefinition('three', DataDefinition::create('string')); - $this->assertEqual(serialize($map_definition), serialize($map_definition2)); + $this->assertEqual($map_definition, $map_definition2); } /** @@ -93,7 +93,7 @@ public function testDataReferences() { // Test using the definition factory. $language_reference_definition2 = $this->typedDataManager->createDataDefinition('language_reference'); $this->assertTrue($language_reference_definition2 instanceof DataReferenceDefinitionInterface); - $this->assertEqual(serialize($language_reference_definition), serialize($language_reference_definition2)); + $this->assertEqual($language_reference_definition, $language_reference_definition2); } } only in patch2: unchanged: --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -22,7 +22,6 @@ use Drupal\Tests\ConfigTestTrait; use Drupal\Tests\RandomGeneratorTrait; use Drupal\simpletest\TestServiceProvider; -use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpFoundation\Request; use org\bovigo\vfs\vfsStream; @@ -50,7 +49,7 @@ * @todo Extend ::setRequirementsFromAnnotation() and ::checkRequirements() to * account for '@requires module'. */ -abstract class KernelTestBase extends TestCase implements ServiceProviderInterface { +abstract class KernelTestBase extends \PHPUnit_Framework_TestCase implements ServiceProviderInterface { use AssertLegacyTrait; use AssertContentTrait; only in patch2: unchanged: --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -27,7 +27,6 @@ use Drupal\simpletest\BlockCreationTrait; use Drupal\simpletest\NodeCreationTrait; use Drupal\simpletest\UserCreationTrait; -use PHPUnit\Framework\TestCase; use Symfony\Component\CssSelector\CssSelectorConverter; use Symfony\Component\HttpFoundation\Request; use Psr\Http\Message\RequestInterface; @@ -42,7 +41,7 @@ * * @ingroup testing */ -abstract class BrowserTestBase extends TestCase { +abstract class BrowserTestBase extends \PHPUnit_Framework_TestCase { use FunctionalTestSetupTrait; use TestSetupTrait; only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php +++ b/core/tests/Drupal/Tests/Component/Assertion/InspectorTest.php @@ -7,14 +7,14 @@ namespace Drupal\Tests\Component\Assertion; -use PHPUnit\Framework\TestCase; +use PHPUnit_Framework_TestCase; use Drupal\Component\Assertion\Inspector; /** * @coversDefaultClass \Drupal\Component\Assertion\Inspector * @group Assertion */ -class InspectorTest extends TestCase { +class InspectorTest extends PHPUnit_Framework_TestCase { /** * Tests asserting argument is an array or traversable object. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php @@ -8,7 +8,6 @@ namespace Drupal\Tests\Component\DependencyInjection; use Drupal\Component\Utility\Crypt; -use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; @@ -22,7 +21,7 @@ * @coversDefaultClass \Drupal\Component\DependencyInjection\Container * @group DependencyInjection */ -class ContainerTest extends TestCase { +class ContainerTest extends \PHPUnit_Framework_TestCase { /** * The tested container. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php @@ -8,7 +8,6 @@ namespace Drupal\Tests\Component\DependencyInjection\Dumper { use Drupal\Component\Utility\Crypt; - use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; @@ -22,7 +21,7 @@ * @coversDefaultClass \Drupal\Component\DependencyInjection\Dumper\OptimizedPhpArrayDumper * @group DependencyInjection */ - class OptimizedPhpArrayDumperTest extends TestCase { + class OptimizedPhpArrayDumperTest extends \PHPUnit_Framework_TestCase { /** * The container builder instance. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Diff/DiffFormatterTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/DiffFormatterTest.php @@ -4,7 +4,6 @@ use Drupal\Component\Diff\Diff; use Drupal\Component\Diff\DiffFormatter; -use PHPUnit\Framework\TestCase; /** * Test DiffFormatter classes. @@ -13,7 +12,7 @@ * * @group Diff */ -class DiffFormatterTest extends TestCase { +class DiffFormatterTest extends \PHPUnit_Framework_TestCase { /** * @return array only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffEngineTest.php @@ -7,7 +7,6 @@ use Drupal\Component\Diff\Engine\DiffOpCopy; use Drupal\Component\Diff\Engine\DiffOpChange; use Drupal\Component\Diff\Engine\DiffOpDelete; -use PHPUnit\Framework\TestCase; /** * Test DiffEngine class. @@ -16,7 +15,7 @@ * * @group Diff */ -class DiffEngineTest extends TestCase { +class DiffEngineTest extends \PHPUnit_Framework_TestCase { /** * @return array only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/Engine/DiffOpTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\Component\Diff\Engine; use Drupal\Component\Diff\Engine\DiffOp; -use PHPUnit\Framework\TestCase; /** * Test DiffOp base class. @@ -16,7 +15,7 @@ * * @group Diff */ -class DiffOpTest extends TestCase { +class DiffOpTest extends \PHPUnit_Framework_TestCase { /** * DiffOp::reverse() always throws an error. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Diff/Engine/HWLDFWordAccumulatorTest.php +++ b/core/tests/Drupal/Tests/Component/Diff/Engine/HWLDFWordAccumulatorTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\Component\Diff\Engine; use Drupal\Component\Diff\Engine\HWLDFWordAccumulator; -use PHPUnit\Framework\TestCase; /** * Test HWLDFWordAccumulator. @@ -12,7 +11,7 @@ * * @group Diff */ -class HWLDFWordAccumulatorTest extends TestCase { +class HWLDFWordAccumulatorTest extends \PHPUnit_Framework_TestCase { /** * Verify that we only get back a NBSP from an empty accumulator. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Component/Serialization/YamlTestBase.php +++ b/core/tests/Drupal/Tests/Component/Serialization/YamlTestBase.php @@ -2,12 +2,10 @@ namespace Drupal\Tests\Component\Serialization; -use PHPUnit\Framework\TestCase; - /** * Provides standard data to validate different YAML implementations. */ -abstract class YamlTestBase extends TestCase { +abstract class YamlTestBase extends \PHPUnit_Framework_TestCase { /** * Some data that should be able to be serialized. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Cache/Context/SessionCacheContextTest.php +++ b/core/tests/Drupal/Tests/Core/Cache/Context/SessionCacheContextTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\Core\Cache\Context; use Drupal\Core\Cache\Context\SessionCacheContext; -use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -11,7 +10,7 @@ * @coversDefaultClass \Drupal\Core\Cache\Context\SessionCacheContext * @group Cache */ -class SessionCacheContextTest extends UnitTestCase { +class SessionCacheContextTest extends \PHPUnit_Framework_TestCase { /** * The request stack. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Config/ConfigFactoryOverrideBaseTest.php +++ b/core/tests/Drupal/Tests/Core/Config/ConfigFactoryOverrideBaseTest.php @@ -6,13 +6,12 @@ use Drupal\Core\Config\ConfigCrudEvent; use Drupal\Core\Config\ConfigFactoryOverrideBase; use Drupal\Core\Config\ConfigRenameEvent; -use Drupal\Tests\UnitTestCase; /** * @coversDefaultClass \Drupal\Core\Config\ConfigFactoryOverrideBase * @group config */ -class ConfigFactoryOverrideBaseTest extends UnitTestCase { +class ConfigFactoryOverrideBaseTest extends \PHPUnit_Framework_TestCase { /** * @dataProvider providerTestFilterNestedArray only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/AuthenticationProviderPassTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/AuthenticationProviderPassTest.php @@ -4,7 +4,6 @@ use Drupal\Core\DependencyInjection\Compiler\AuthenticationProviderPass; use Drupal\Core\DependencyInjection\ContainerBuilder; -use Drupal\Tests\UnitTestCase; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\Serializer\Serializer; @@ -12,7 +11,7 @@ * @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\AuthenticationProviderPass * @group DependencyInjection */ -class AuthenticationProviderPassTest extends UnitTestCase { +class AuthenticationProviderPassTest extends \PHPUnit_Framework_TestCase { /** * @covers ::process only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/YamlFileLoaderTest.php @@ -5,14 +5,13 @@ use Drupal\Component\FileCache\FileCacheFactory; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\YamlFileLoader; -use Drupal\Tests\UnitTestCase; use org\bovigo\vfs\vfsStream; /** * @coversDefaultClass \Drupal\Core\DependencyInjection\YamlFileLoader * @group DependencyInjection */ -class YamlFileLoaderTest extends UnitTestCase { +class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase { /** * {@inheritdoc} only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php @@ -534,9 +534,6 @@ public function testGetTableMappingRevisionable(array $entity_keys) { ['bundle', $entity_keys['bundle']], ['revision', $entity_keys['revision']], ])); - $this->entityType->expects($this->any()) - ->method('getRevisionMetadataKeys') - ->will($this->returnValue([])); $this->setUpEntityStorage(); @@ -577,13 +574,13 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) { // PHPUnit does not allow for multiple data providers. $test_cases = [ [], - ['revision_created' => 'revision_timestamp'], - ['revision_user' => 'revision_uid'], - ['revision_log_message' => 'revision_log'], - ['revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid'], - ['revision_created' => 'revision_timestamp', 'revision_log_message' => 'revision_log'], - ['revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'], - ['revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'], + ['revision_timestamp'], + ['revision_uid'], + ['revision_log'], + ['revision_timestamp', 'revision_uid'], + ['revision_timestamp', 'revision_log'], + ['revision_uid', 'revision_log'], + ['revision_timestamp', 'revision_uid', 'revision_log'], ]; foreach ($test_cases as $revision_metadata_field_names) { $this->setUp(); @@ -594,7 +591,7 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) { $revisionable_field_names = ['description', 'owner']; $field_names = array_merge($field_names, $revisionable_field_names); - $this->fieldDefinitions += $this->mockFieldDefinitions(array_merge($revisionable_field_names, array_values($revision_metadata_field_names)), ['isRevisionable' => TRUE]); + $this->fieldDefinitions += $this->mockFieldDefinitions(array_merge($revisionable_field_names, $revision_metadata_field_names), ['isRevisionable' => TRUE]); $this->entityType->expects($this->exactly(2)) ->method('isRevisionable') @@ -608,10 +605,6 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) { ['revision', $entity_keys['revision']], ])); - $this->entityType->expects($this->any()) - ->method('getRevisionMetadataKeys') - ->will($this->returnValue($revision_metadata_field_names)); - $this->setUpEntityStorage(); $mapping = $this->entityStorage->getTableMapping(); @@ -623,7 +616,7 @@ public function testGetTableMappingRevisionableWithFields(array $entity_keys) { $expected = array_merge( [$entity_keys['id'], $entity_keys['revision']], $revisionable_field_names, - array_values($revision_metadata_field_names) + $revision_metadata_field_names ); $this->assertEquals($expected, $mapping->getFieldNames('entity_test_revision')); @@ -768,11 +761,6 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys) 'uuid' => $entity_keys['uuid'], 'langcode' => 'langcode', ]; - $revision_metadata_keys = [ - 'revision_created' => 'revision_timestamp', - 'revision_user' => 'revision_uid', - 'revision_log_message' => 'revision_log' - ]; $this->entityType->expects($this->atLeastOnce()) ->method('isRevisionable') @@ -792,9 +780,6 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys) ['revision', $entity_keys['revision']], ['langcode', $entity_keys['langcode']], ])); - $this->entityType->expects($this->any()) - ->method('getRevisionMetadataKeys') - ->will($this->returnValue($revision_metadata_keys)); $this->setUpEntityStorage(); @@ -825,7 +810,6 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys) $entity_keys['revision'], $entity_keys['langcode'], ])); - $expected = array_merge($expected, array_values($revision_metadata_keys)); $actual = $mapping->getFieldNames('entity_test_revision'); $this->assertEquals($expected, $actual); // The UUID is not stored on the data table. @@ -881,13 +865,13 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent // PHPUnit does not allow for multiple data providers. $test_cases = [ [], - ['revision_created' => 'revision_timestamp'], - ['revision_user' => 'revision_uid'], - ['revision_log_message' => 'revision_log'], - ['revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid'], - ['revision_created' => 'revision_timestamp', 'revision_log_message' => 'revision_log'], - ['revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'], - ['revision_created' => 'revision_timestamp', 'revision_user' => 'revision_uid', 'revision_log_message' => 'revision_log'], + ['revision_timestamp'], + ['revision_uid'], + ['revision_log'], + ['revision_timestamp', 'revision_uid'], + ['revision_timestamp', 'revision_log'], + ['revision_uid', 'revision_log'], + ['revision_timestamp', 'revision_uid', 'revision_log'], ]; foreach ($test_cases as $revision_metadata_field_names) { $this->setUp(); @@ -897,7 +881,7 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent $this->fieldDefinitions = $this->mockFieldDefinitions($field_names); $revisionable_field_names = ['description', 'owner']; - $this->fieldDefinitions += $this->mockFieldDefinitions(array_merge($revisionable_field_names, array_values($revision_metadata_field_names)), ['isRevisionable' => TRUE]); + $this->fieldDefinitions += $this->mockFieldDefinitions(array_merge($revisionable_field_names, $revision_metadata_field_names), ['isRevisionable' => TRUE]); $this->entityType->expects($this->atLeastOnce()) ->method('isRevisionable') @@ -917,9 +901,6 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent ['revision', $entity_keys['revision']], ['langcode', $entity_keys['langcode']], ])); - $this->entityType->expects($this->any()) - ->method('getRevisionMetadataKeys') - ->will($this->returnValue($revision_metadata_field_names)); $this->setUpEntityStorage(); @@ -957,7 +938,7 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent $entity_keys['id'], $entity_keys['revision'], $entity_keys['langcode'], - ]), array_values($revision_metadata_field_names)); + ]), $revision_metadata_field_names); $actual = $mapping->getFieldNames('entity_test_revision'); $this->assertEquals($expected, $actual); // The UUID is not stored on the data table. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/EventSubscriber/FinalExceptionSubscriberTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/DefaultExceptionSubscriberTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\Core\EventSubscriber; -use Drupal\Core\EventSubscriber\FinalExceptionSubscriber; +use Drupal\Core\EventSubscriber\DefaultExceptionSubscriber; use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -11,13 +11,14 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * @coversDefaultClass \Drupal\Core\EventSubscriber\FinalExceptionSubscriber + * @coversDefaultClass \Drupal\Core\EventSubscriber\DefaultExceptionSubscriber * @group EventSubscriber */ -class FinalExceptionSubscriberTest extends UnitTestCase { +class DefaultExceptionSubscriberTest extends UnitTestCase { /** * @covers ::onException + * @covers ::onFormatUnknown */ public function testOnExceptionWithUnknownFormat() { $config_factory = $this->getConfigFactoryStub(); @@ -26,13 +27,12 @@ public function testOnExceptionWithUnknownFormat() { $request = Request::create('/test?_format=bananas'); $e = new MethodNotAllowedHttpException(['POST', 'PUT'], 'test message'); $event = new GetResponseForExceptionEvent($kernel->reveal(), $request, 'GET', $e); - $subscriber = new TestDefaultExceptionSubscriber($config_factory); - $subscriber->setStringTranslation($this->getStringTranslationStub()); + $subscriber = new DefaultExceptionSubscriber($config_factory); $subscriber->onException($event); $response = $event->getResponse(); $this->assertInstanceOf(Response::class, $response); - $this->stringStartsWith('The website encountered an unexpected error. Please try again later.

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: test message in ', $response->getContent()); + $this->assertEquals('test message', $response->getContent()); $this->assertEquals(405, $response->getStatusCode()); $this->assertEquals('POST, PUT', $response->headers->get('Allow')); // Also check that that text/plain content type was added. @@ -40,19 +40,3 @@ public function testOnExceptionWithUnknownFormat() { } } - -class TestDefaultExceptionSubscriber extends FinalExceptionSubscriber { - - protected function isErrorDisplayable($error) { - return TRUE; - } - - protected function simplifyFileInError($error) { - return $error; - } - - protected function isErrorLevelVerbose() { - return TRUE; - } - -} only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/EventSubscriber/OptionsRequestSubscriberTest.php +++ b/core/tests/Drupal/Tests/Core/EventSubscriber/OptionsRequestSubscriberTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\Core\EventSubscriber; use Drupal\Core\EventSubscriber\OptionsRequestSubscriber; -use Drupal\Tests\UnitTestCase; use Symfony\Cmf\Component\Routing\RouteProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -15,7 +14,7 @@ * @coversDefaultClass \Drupal\Core\EventSubscriber\OptionsRequestSubscriber * @group EventSubscriber */ -class OptionsRequestSubscriberTest extends UnitTestCase { +class OptionsRequestSubscriberTest extends \PHPUnit_Framework_TestCase { /** * @covers ::onRequest only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php @@ -413,7 +413,7 @@ public function testGetTasksBuildWithCacheabilityMetadata() { ->method('getDefinitions') ->will($this->returnValue($definitions)); - // Set up some cacheability metadata and ensure its merged together. + // Set up some cacheablity metadata and ensure its merged together. $definitions['menu_local_task_test_tasks_settings']['cache_tags'] = ['tag.example1']; $definitions['menu_local_task_test_tasks_settings']['cache_contexts'] = ['context.example1']; $definitions['menu_local_task_test_tasks_edit']['cache_tags'] = ['tag.example2']; only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php +++ b/core/tests/Drupal/Tests/Core/Plugin/DefaultSingleLazyPluginCollectionTest.php @@ -58,17 +58,6 @@ public function testAddInstanceId() { $this->assertEquals(['id' => 'banana', 'key' => 'other_value'], $this->defaultPluginCollection->get('banana')->getConfiguration()); } - /** - * @covers ::getInstanceIds - */ - public function testGetInstanceIds() { - $this->setupPluginCollection($this->any()); - $this->assertEquals(['apple' => 'apple'], $this->defaultPluginCollection->getInstanceIds()); - - $this->defaultPluginCollection->addInstanceId('banana', ['id' => 'banana', 'key' => 'other_value']); - $this->assertEquals(['banana' => 'banana'], $this->defaultPluginCollection->getInstanceIds()); - } - } class ConfigurablePlugin extends PluginBase implements ConfigurablePluginInterface { only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php +++ b/core/tests/Drupal/Tests/Core/Render/BubbleableMetadataTest.php @@ -671,7 +671,7 @@ public function testAddCacheableDependency(BubbleableMetadata $a, $b, Bubbleable * * @return array */ - public function providerTestAddCacheableDependency() { + public function providerTestAddCachableDependency() { return [ // Merge in a cacheable metadata. 'merge-cacheable-metadata' => [ only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Render/RendererTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererTest.php @@ -511,7 +511,7 @@ public function testRenderWithAccessControllerResolved($access) { * @covers ::render * @covers ::doRender */ - public function testRenderAccessCacheabilityDependencyInheritance() { + public function testRenderAccessCacheablityDependencyInheritance() { $build = [ '#access' => AccessResult::allowed()->addCacheContexts(['user']), ]; only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Core/Routing/MethodFilterTest.php +++ b/core/tests/Drupal/Tests/Core/Routing/MethodFilterTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\Core\Routing; use Drupal\Core\Routing\MethodFilter; -use Drupal\Tests\UnitTestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Route; @@ -13,7 +12,7 @@ * @coversDefaultClass \Drupal\Core\Routing\MethodFilter * @group Routing */ -class MethodFilterTest extends UnitTestCase { +class MethodFilterTest extends \PHPUnit_Framework_TestCase { /** * @covers ::applies only in patch2: unchanged: --- a/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php +++ b/core/tests/Drupal/Tests/Listeners/DrupalStandardsListener.php @@ -2,26 +2,23 @@ namespace Drupal\Tests\Listeners; -use PHPUnit\Framework\BaseTestListener; -use PHPUnit\Framework\TestCase; - /** * Listens for PHPUnit tests and fails those with invalid coverage annotations. * * Enforces various coding standards within test runs. */ -class DrupalStandardsListener extends BaseTestListener { +class DrupalStandardsListener extends \PHPUnit_Framework_BaseTestListener { /** * Signals a coding standards failure to the user. * - * @param \PHPUnit\Framework\TestCase $test + * @param \PHPUnit_Framework_TestCase $test * The test where we should insert our test failure. * @param string $message * The message to add to the failure notice. The test class name and test * name will be appended to this message automatically. */ - protected function fail(TestCase $test, $message) { + protected function fail(\PHPUnit_Framework_TestCase $test, $message) { // Add the report to the test's results. $message .= ': ' . get_class($test) . '::' . $test->getName(); $fail = new \PHPUnit_Framework_AssertionFailedError($message); @@ -47,10 +44,10 @@ protected function classExists($class) { * * This method is called from $this::endTest(). * - * @param \PHPUnit\Framework\TestCase $test + * @param \PHPUnit_Framework_TestCase $test * The test to examine. */ - public function checkValidCoversForTest(TestCase $test) { + public function checkValidCoversForTest(\PHPUnit_Framework_TestCase $test) { // If we're generating a coverage report already, don't do anything here. if ($test->getTestResultObject() && $test->getTestResultObject()->getCollectCodeCoverageInformation()) { return; @@ -147,7 +144,7 @@ public function endTest(\PHPUnit_Framework_Test $test, $time) { // \PHPUnit_Framework_Test does not have any useful methods of its own for // our purpose, so we have to distinguish between the different known // subclasses. - if ($test instanceof TestCase) { + if ($test instanceof \PHPUnit_Framework_TestCase) { $this->checkValidCoversForTest($test); } elseif ($test instanceof \PHPUnit_Framework_TestSuite) { only in patch2: unchanged: --- a/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php +++ b/core/tests/Drupal/Tests/TestSuites/TestSuiteBaseTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\TestSuites; use org\bovigo\vfs\vfsStream; -use PHPUnit\Framework\TestCase; // The test suite class is not part of the autoloader, we need to include it // manually. @@ -14,7 +13,7 @@ * * @group TestSuite */ -class TestSuiteBaseTest extends TestCase { +class TestSuiteBaseTest extends \PHPUnit_Framework_TestCase { /** * Helper method to set up the file system. only in patch2: unchanged: --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -8,7 +8,6 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\StringTranslation\PluralTranslatableMarkup; -use PHPUnit\Framework\TestCase; /** @@ -16,7 +15,7 @@ * * @ingroup testing */ -abstract class UnitTestCase extends TestCase { +abstract class UnitTestCase extends \PHPUnit_Framework_TestCase { /** * The random generator. only in patch2: unchanged: --- a/core/themes/seven/css/components/jquery.ui/theme.css +++ b/core/themes/seven/css/components/jquery.ui/theme.css @@ -33,6 +33,8 @@ .ui-state-active, .ui-widget-content .ui-state-active { color: #840; + background: #fe6; + border: solid 1px #ed5; } .ui-state-error, .ui-widget-content .ui-state-error { only in patch2: unchanged: --- a/example.gitignore +++ b/example.gitignore @@ -37,3 +37,7 @@ sites/simpletest # Ignore SimpleTest multi-site environment. # simpletest + +# Ignore core phpcs.xml and phpunit.xml. +core/phpcs.xml +core/phpunit.xml only in patch2: unchanged: --- a/sites/default/default.settings.php +++ b/sites/default/default.settings.php @@ -86,7 +86,7 @@ * ); * @endcode */ -$databases = array(); + $databases = array(); /** * Customizing database settings. @@ -750,16 +750,6 @@ ]; /** - * The default number of entities to update in a batch process. - * - * This is used by update and post-update functions that need to go through and - * change all the entities on a site, so it is useful to increase this number - * if your hosting configuration (i.e. RAM allocation, CPU speed) allows for a - * larger number of entities to be processed in a single batch run. - */ -$settings['entity_update_batch_size'] = 50; - -/** * Load local development override configuration, if available. * * Use settings.local.php to override variables on secondary (staging,