diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php index 8dfac43eaf19639d32ffe831941b9c29bec20b6e..3508611279a5e5637713a9e05f87bd539e3b499c 100644 --- a/core/lib/Drupal/Core/Config/ConfigBase.php +++ b/core/lib/Drupal/Core/Config/ConfigBase.php @@ -9,7 +9,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; -use \Drupal\Core\DependencyInjection\DependencySerialization; +use \Drupal\Core\DependencyInjection\DependencySerializationTrait; /** * Provides a base class for configuration objects with get/set support. @@ -26,7 +26,8 @@ * @see \Drupal\Core\Config\Config * @see \Drupal\Core\Theme\ThemeSettings */ -abstract class ConfigBase extends DependencySerialization { +abstract class ConfigBase { + use DependencySerializationTrait; /** * The name of the configuration object. diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php index 6691b0e32992bf87a98f25ce643609fee2afe3c1..dbf340f12b06e14695a0687ce6f7e49b08ab80cd 100644 --- a/core/lib/Drupal/Core/Config/ConfigImporter.php +++ b/core/lib/Drupal/Core/Config/ConfigImporter.php @@ -11,7 +11,7 @@ use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\Component\Utility\String; use Drupal\Core\Config\Entity\ImportableEntityStorageInterface; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; @@ -37,8 +37,9 @@ * * @see \Drupal\Core\Config\ConfigImporterEvent */ -class ConfigImporter extends DependencySerialization { +class ConfigImporter { use StringTranslationTrait; + use DependencySerializationTrait; /** * The name used to identify the lock. diff --git a/core/lib/Drupal/Core/Config/StorageComparer.php b/core/lib/Drupal/Core/Config/StorageComparer.php index d19f67a48e1d66cc26616173dd4fb2e92beaecdc..307238167584f26d2cd09f169b5ea6d294b06497 100644 --- a/core/lib/Drupal/Core/Config/StorageComparer.php +++ b/core/lib/Drupal/Core/Config/StorageComparer.php @@ -9,12 +9,13 @@ use Drupal\Component\Utility\String; use Drupal\Core\Config\Entity\ConfigDependencyManager; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; /** * Defines a config storage comparer. */ -class StorageComparer extends DependencySerialization implements StorageComparerInterface { +class StorageComparer implements StorageComparerInterface { + use DependencySerializationTrait; /** * The source storage used to discover configuration changes. diff --git a/core/lib/Drupal/Core/Controller/FormController.php b/core/lib/Drupal/Core/Controller/FormController.php index 5fec415cbbeece9cfaa57d4777965bb3dc3c42d6..6ba7ba37fb426c757d1d4b39fb389f53041088d4 100644 --- a/core/lib/Drupal/Core/Controller/FormController.php +++ b/core/lib/Drupal/Core/Controller/FormController.php @@ -7,8 +7,7 @@ namespace Drupal\Core\Controller; -use Drupal\Core\DependencyInjection\DependencySerialization; -use Drupal\Core\Controller\ControllerResolverInterface; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Form\FormBuilderInterface; use Symfony\Component\HttpFoundation\Request; @@ -17,8 +16,8 @@ * * @todo Make this a trait in PHP 5.4. */ -abstract class FormController extends DependencySerialization { - +abstract class FormController { + use DependencySerializationTrait; /** * The form definition. The format may vary depending on the child class. * diff --git a/core/lib/Drupal/Core/DependencyInjection/DependencySerialization.php b/core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php similarity index 89% rename from core/lib/Drupal/Core/DependencyInjection/DependencySerialization.php rename to core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php index 256ce745d4a16c5d36ac7c7386324051a89b4fbf..cb6a27d04c4a541cd8df04a075e93601742ef8f1 100644 --- a/core/lib/Drupal/Core/DependencyInjection/DependencySerialization.php +++ b/core/lib/Drupal/Core/DependencyInjection/DependencySerializationTrait.php @@ -2,16 +2,17 @@ /** * @file - * Contains \Drupal\Core\DependencyInjection\DependencySerialization. + * Contains \Drupal\Core\DependencyInjection\DependencySerializationTrait. */ namespace Drupal\Core\DependencyInjection; + use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Provides a dependency injection friendly methods for serialization. + * Provides dependency injection friendly methods for serialization. */ -abstract class DependencySerialization { +trait DependencySerializationTrait { /** * An array of service IDs keyed by property name used for serialization. @@ -52,7 +53,7 @@ public function __wakeup() { foreach ($this->_serviceIds as $key => $service_id) { $this->$key = $container->get($service_id); } - unset($this->_serviceIds); + $this->_serviceIds = array(); } } diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index a93c505496ba05fb83da752a33523c851762a13c..e223fe9fefaa7b92c3779484733ca6a565b7443f 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -8,7 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Core\Cache\Cache; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\String; use Drupal\Component\Utility\Unicode; @@ -24,7 +24,8 @@ /** * Defines a base entity class. */ -abstract class Entity extends DependencySerialization implements EntityInterface { +abstract class Entity implements EntityInterface { + use DependencySerializationTrait; /** * The entity type. diff --git a/core/lib/Drupal/Core/Entity/EntityControllerBase.php b/core/lib/Drupal/Core/Entity/EntityControllerBase.php index cbaf6709d90cd82799c0fb3eec5af3fb9418a8b4..9b13ed8eade841895b49a1b1b7c6fb6b822e8965 100644 --- a/core/lib/Drupal/Core/Entity/EntityControllerBase.php +++ b/core/lib/Drupal/Core/Entity/EntityControllerBase.php @@ -7,7 +7,7 @@ namespace Drupal\Core\Entity; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; @@ -17,8 +17,9 @@ * * @todo Convert this to a trait. */ -abstract class EntityControllerBase extends DependencySerialization { +abstract class EntityControllerBase { use StringTranslationTrait; + use DependencySerializationTrait; /** * The module handler to invoke hooks on. diff --git a/core/lib/Drupal/Core/Form/FormBase.php b/core/lib/Drupal/Core/Form/FormBase.php index 5dedf6c3f61318b2d68cc9ef7cc3473362beb644..b94a3ed2cd37dfd191627df93cee12dfdbe7817d 100644 --- a/core/lib/Drupal/Core/Form/FormBase.php +++ b/core/lib/Drupal/Core/Form/FormBase.php @@ -9,7 +9,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -18,8 +18,9 @@ /** * Provides a base class for forms. */ -abstract class FormBase extends DependencySerialization implements FormInterface, ContainerInjectionInterface { +abstract class FormBase implements FormInterface, ContainerInjectionInterface { use StringTranslationTrait; + use DependencySerializationTrait; /** * The current request. @@ -38,14 +39,14 @@ abstract class FormBase extends DependencySerialization implements FormInterface /** * The config factory. * - * This is marked private in order to force subclasses to use the - * self::config() method, which may be overridden to address specific needs - * when loading config. See \Drupal\Core\Form\ConfigFormBase::config() for an - * example of this. + * Subclasses should use the self::config() method, which may be overridden to + * address specific needs when loading config, rather than this property + * directly. See \Drupal\Core\Form\ConfigFormBase::config() for an example of + * this. * * @var \Drupal\Core\Config\ConfigFactoryInterface */ - private $configFactory; + protected $configFactory; /** * The form error handler. diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index d596853e3d55cc21896c81ca6847482fbf99b00d..c77345ec601c4d3df9202302fc90646a65a9f000 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -8,13 +8,14 @@ namespace Drupal\Core\Language; use Drupal\Component\Utility\String; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\StringTranslation\TranslationInterface; /** * Class responsible for providing language support on language-unaware sites. */ -class LanguageManager extends DependencySerialization implements LanguageManagerInterface { +class LanguageManager implements LanguageManagerInterface { + use DependencySerializationTrait; /** * The string translation service. diff --git a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php index 43d3a66f28cdb774abaa81da67eb5705077ffc00..1f5fc7e8d944f427ed67a22d6ee94bf308ce9d1e 100644 --- a/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php +++ b/core/lib/Drupal/Core/Plugin/ContextAwarePluginBase.php @@ -8,10 +8,10 @@ namespace Drupal\Core\Plugin; use Drupal\Component\Plugin\ContextAwarePluginBase as ComponentContextAwarePluginBase; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Plugin\Context\Context; use Drupal\Component\Plugin\Discovery\DiscoveryInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Drupal specific class for plugins that use context. @@ -22,16 +22,7 @@ */ abstract class ContextAwarePluginBase extends ComponentContextAwarePluginBase { use StringTranslationTrait; - - /** - * An array of service IDs keyed by property name used for serialization. - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait in https://drupal.org/node/2208115. - * - * @var array - */ - protected $_serviceIds = array(); + use DependencySerializationTrait; /** * Override of \Drupal\Component\Plugin\ContextAwarePluginBase::__construct(). @@ -61,45 +52,4 @@ public function setContextValue($name, $value) { return $this; } - /** - * {@inheritdoc} - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait in https://drupal.org/node/2208115. - */ - public function __sleep() { - $this->_serviceIds = array(); - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value) && isset($value->_serviceId)) { - // If a class member was instantiated by the dependency injection - // container, only store its ID so it can be used to get a fresh object - // on unserialization. - $this->_serviceIds[$key] = $value->_serviceId; - unset($vars[$key]); - } - // Special case the container, which might not have a service ID. - elseif ($value instanceof ContainerInterface) { - $this->_serviceIds[$key] = 'service_container'; - unset($vars[$key]); - } - } - - return array_keys($vars); - } - - /** - * {@inheritdoc} - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait in https://drupal.org/node/2208115. - */ - public function __wakeup() { - $container = \Drupal::getContainer(); - foreach ($this->_serviceIds as $key => $service_id) { - $this->$key = $container->get($service_id); - } - unset($this->_serviceIds); - } - } diff --git a/core/lib/Drupal/Core/Plugin/PluginBase.php b/core/lib/Drupal/Core/Plugin/PluginBase.php index 931062d089aeba6ef6c099ef20a81354f3b6bdb9..daaf99acc64c5941ea0556be5d95042d5fc01990 100644 --- a/core/lib/Drupal/Core/Plugin/PluginBase.php +++ b/core/lib/Drupal/Core/Plugin/PluginBase.php @@ -9,63 +9,13 @@ use Drupal\Component\Plugin\PluginBase as ComponentPluginBase; use Drupal\Core\StringTranslation\StringTranslationTrait; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; /** * Base class for plugins supporting metadata inspection and translation. */ abstract class PluginBase extends ComponentPluginBase { use StringTranslationTrait; - - /** - * An array of service IDs keyed by property name used for serialization. - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait. - * - * @var array - */ - protected $_serviceIds = array(); - - /** - * {@inheritdoc} - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait. - */ - public function __sleep() { - $this->_serviceIds = array(); - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value) && isset($value->_serviceId)) { - // If a class member was instantiated by the dependency injection - // container, only store its ID so it can be used to get a fresh object - // on unserialization. - $this->_serviceIds[$key] = $value->_serviceId; - unset($vars[$key]); - } - // Special case the container, which might not have a service ID. - elseif ($value instanceof ContainerInterface) { - $this->_serviceIds[$key] = 'service_container'; - unset($vars[$key]); - } - } - - return array_keys($vars); - } - - /** - * {@inheritdoc} - * - * @todo Remove when Drupal\Core\DependencyInjection\DependencySerialization - * is converted to a trait. - */ - public function __wakeup() { - $container = \Drupal::getContainer(); - foreach ($this->_serviceIds as $key => $service_id) { - $this->$key = $container->get($service_id); - } - unset($this->_serviceIds); - } + use DependencySerializationTrait; } diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php index f7f2b1a7fc71470e03354a6140ad0da9b2149454..874335ed910d51e7c959c15bae424a883a22e1fd 100644 --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -8,7 +8,7 @@ namespace Drupal\Core; use Drupal\Component\Utility\UrlHelper; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Routing\MatchingRouteNotFoundException; use Drupal\Core\Routing\UrlGeneratorInterface; use Symfony\Cmf\Component\Routing\RouteObjectInterface; @@ -18,7 +18,8 @@ /** * Defines an object that holds information about a URL. */ -class Url extends DependencySerialization { +class Url { + use DependencySerializationTrait; /** * The URL generator. diff --git a/core/modules/forum/src/ForumManager.php b/core/modules/forum/src/ForumManager.php index 1609899f745b9c43903a7379dccaff18ff0f3dcb..add0760846dbf59b7de515ad58dd1377e08f1fee 100644 --- a/core/modules/forum/src/ForumManager.php +++ b/core/modules/forum/src/ForumManager.php @@ -9,7 +9,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Database\Connection; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\TranslationInterface; @@ -19,8 +19,12 @@ /** * Provides forum manager service. */ -class ForumManager extends DependencySerialization implements ForumManagerInterface { +class ForumManager implements ForumManagerInterface { use StringTranslationTrait; + use DependencySerializationTrait { + __wakeup as defaultWakeup; + __sleep as defaultSleep; + } /** * Forum sort order, newest first. @@ -499,7 +503,7 @@ public function unreadTopics($term, $uid) { * {@inheritdoc} */ public function __sleep() { - $vars = parent::__sleep(); + $vars = $this->defaultSleep(); // Do not serialize static cache. unset($vars['history'], $vars['index'], $vars['lastPostData'], $vars['forumChildren'], $vars['forumStatistics']); return $vars; @@ -509,7 +513,7 @@ public function __sleep() { * {@inheritdoc} */ public function __wakeup() { - parent::__wakeup(); + $this->defaultWakeup(); // Initialize static cache. $this->history = array(); $this->lastPostData = array(); diff --git a/core/modules/views/src/Form/ViewsForm.php b/core/modules/views/src/Form/ViewsForm.php index 45f1730e3cb8c530897ca39c6283c842f419c8b0..72ae384519204bc8e1c4d3b4ef4c599262eec78f 100644 --- a/core/modules/views/src/Form/ViewsForm.php +++ b/core/modules/views/src/Form/ViewsForm.php @@ -11,7 +11,7 @@ use Drupal\Core\Controller\ControllerResolverInterface; use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Form\FormInterface; use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\views\ViewExecutable; @@ -26,7 +26,8 @@ * default is \Drupal\views\Form\ViewsFormMainForm). That way it is actually * possible for modules to have a multistep form if they need to. */ -class ViewsForm extends DependencySerialization implements FormInterface, ContainerInjectionInterface { +class ViewsForm implements FormInterface, ContainerInjectionInterface { + use DependencySerializationTrait; /** * The class resolver to get the subform form objects. diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php index d6b477575295daf33ebe2cbed158bfa81a835e1f..72da90cdf7c27cdd912c3de1b35226256414e644 100644 --- a/core/modules/views/src/ViewExecutable.php +++ b/core/modules/views/src/ViewExecutable.php @@ -7,7 +7,7 @@ namespace Drupal\views; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Core\Session\AccountInterface; use Drupal\views\Plugin\views\query\QueryPluginBase; use Drupal\views\ViewStorageInterface; @@ -26,7 +26,8 @@ * An object to contain all of the data to generate a view, plus the member * functions to build the view query, execute the query and render the output. */ -class ViewExecutable extends DependencySerialization { +class ViewExecutable { + use DependencySerializationTrait; /** * The config entity in which the view is stored. diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/DependencySerializationTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/DependencySerializationTest.php index 1cf99cc081ceb2117fb4c080c7544c7b58d6ac59..2c852565fae8ab7dd819b656a94e6d9a77e88707 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/DependencySerializationTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/DependencySerializationTest.php @@ -8,15 +8,15 @@ namespace Drupal\Tests\Core\DependencyInjection; use Drupal\Core\DependencyInjection\Container; -use Drupal\Core\DependencyInjection\DependencySerialization; +use Drupal\Core\DependencyInjection\DependencySerializationTrait; use Drupal\Tests\UnitTestCase; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Tests the dependency serialization base class. + * Tests the dependency serialization trait. * - * @see \Drupal\Core\DependencyInjection\DependencySerialization + * @coversDefaultClass \Drupal\Core\DependencyInjection\DependencySerializationTrait */ class DependencySerializationTest extends UnitTestCase { @@ -25,14 +25,15 @@ class DependencySerializationTest extends UnitTestCase { */ public static function getInfo() { return array( - 'name' => 'Service dependency serialization', - 'description' => 'Tests the dependency serialization base class.', + 'name' => '\Drupal\Core\DependencyInjection\DependencySerializationTrait unit test', + 'description' => '', 'group' => 'System' ); } /** - * Tests serialization and unserialization. + * @covers ::__sleep + * @covers ::__wakeup */ public function testSerialization() { // Create a pseudo service and dependency injected object. @@ -43,26 +44,19 @@ public function testSerialization() { $container->set('service_container', $container); \Drupal::setContainer($container); - $dependencySerialization = new TestClass($service); + $dependencySerialization = new DependencySerializationTestDummy($service); $dependencySerialization->setContainer($container); $string = serialize($dependencySerialization); $object = unserialize($string); - // The original object got _serviceIds added so removing it to check - // equality. - unset($dependencySerialization->_serviceIds); - - // Ensure dependency injected object remains the same after serialization. - $this->assertEquals($dependencySerialization, $object); - - // Ensure that _serviceIds does not exist on the object anymore. - $this->assertFalse(isset($object->_serviceIds)); + $string = serialize($dependencySerialization); + /** @var \Drupal\Tests\Core\DependencyInjection\DependencySerializationTestDummy $object */ + $dependencySerialization = unserialize($string); - // Ensure that both the service and the variable are in the unserialized - // object. - $this->assertSame($service, $object->service); - $this->assertSame($container, $object->container); + $this->assertSame($service, $dependencySerialization->service); + $this->assertSame($container, $dependencySerialization->container); + $this->assertEmpty($dependencySerialization->getServiceIds()); } } @@ -70,7 +64,9 @@ public function testSerialization() { /** * Defines a test class which has a single service as dependency. */ -class TestClass extends DependencySerialization implements ContainerAwareInterface { +class DependencySerializationTestDummy implements ContainerAwareInterface { + + use DependencySerializationTrait; /** * A test service. @@ -86,13 +82,6 @@ class TestClass extends DependencySerialization implements ContainerAwareInterfa */ public $container; - /** - * {@inheritdoc} - * - * Make the property accessible for the test. - */ - public $_serviceIds; - /** * Constructs a new TestClass object. * @@ -109,4 +98,11 @@ public function __construct(\stdClass $service) { public function setContainer(ContainerInterface $container = NULL) { $this->container = $container; } + + /** + * Gets the stored service IDs. + */ + public function getServiceIds() { + return $this->_serviceIds; + } }