123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /**
- * Implementation of the @magentoDataFixture DocBlock annotation
- */
- namespace Magento\TestFramework\Annotation;
- use PHPUnit\Framework\Exception;
- class DataFixture
- {
- /**
- * @var string
- */
- protected $_fixtureBaseDir;
- /**
- * Fixtures that have been applied
- *
- * @var array
- */
- private $_appliedFixtures = [];
- /**
- * Constructor
- *
- * @param string $fixtureBaseDir
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function __construct($fixtureBaseDir)
- {
- if (!is_dir($fixtureBaseDir)) {
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase("Fixture base directory '%1' does not exist.", [$fixtureBaseDir])
- );
- }
- $this->_fixtureBaseDir = realpath($fixtureBaseDir);
- }
- /**
- * Handler for 'startTestTransactionRequest' event
- *
- * @param \PHPUnit\Framework\TestCase $test
- * @param \Magento\TestFramework\Event\Param\Transaction $param
- */
- public function startTestTransactionRequest(
- \PHPUnit\Framework\TestCase $test,
- \Magento\TestFramework\Event\Param\Transaction $param
- ) {
- /* Start transaction before applying first fixture to be able to revert them all further */
- if ($this->_getFixtures($test)) {
- if ($this->getDbIsolationState($test) !== ['disabled']) {
- $param->requestTransactionStart();
- } else {
- $this->_applyFixtures($this->_getFixtures($test));
- }
- }
- }
- /**
- * Handler for 'endTestNeedTransactionRollback' event
- *
- * @param \PHPUnit\Framework\TestCase $test
- * @param \Magento\TestFramework\Event\Param\Transaction $param
- */
- public function endTestTransactionRequest(
- \PHPUnit\Framework\TestCase $test,
- \Magento\TestFramework\Event\Param\Transaction $param
- ) {
- /* Isolate other tests from test-specific fixtures */
- if ($this->_appliedFixtures && $this->_getFixtures($test)) {
- if ($this->getDbIsolationState($test) !== ['disabled']) {
- $param->requestTransactionRollback();
- } else {
- $this->_revertFixtures();
- }
- }
- }
- /**
- * Handler for 'startTransaction' event
- *
- * @param \PHPUnit\Framework\TestCase $test
- */
- public function startTransaction(\PHPUnit\Framework\TestCase $test)
- {
- $this->_applyFixtures($this->_getFixtures($test));
- }
- /**
- * Handler for 'rollbackTransaction' event
- */
- public function rollbackTransaction()
- {
- $this->_revertFixtures();
- }
- /**
- * Retrieve fixtures from annotation
- *
- * @param \PHPUnit\Framework\TestCase $test
- * @param string $scope
- * @return array
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function _getFixtures(\PHPUnit\Framework\TestCase $test, $scope = null)
- {
- if ($scope === null) {
- $annotations = $this->getAnnotations($test);
- } else {
- $annotations = $test->getAnnotations()[$scope];
- }
- $result = [];
- if (!empty($annotations['magentoDataFixture'])) {
- foreach ($annotations['magentoDataFixture'] as $fixture) {
- if (strpos($fixture, '\\') !== false) {
- // usage of a single directory separator symbol streamlines search across the source code
- throw new \Magento\Framework\Exception\LocalizedException(
- new \Magento\Framework\Phrase('Directory separator "\\" is prohibited in fixture declaration.')
- );
- }
- $fixtureMethod = [get_class($test), $fixture];
- if (is_callable($fixtureMethod)) {
- $result[] = $fixtureMethod;
- } else {
- $result[] = $this->_fixtureBaseDir . '/' . $fixture;
- }
- }
- }
- return $result;
- }
- /**
- * @param \PHPUnit\Framework\TestCase $test
- * @return array
- */
- private function getAnnotations(\PHPUnit\Framework\TestCase $test)
- {
- $annotations = $test->getAnnotations();
- return array_replace($annotations['class'], $annotations['method']);
- }
- /**
- * Return is explicit set isolation state
- *
- * @param \PHPUnit\Framework\TestCase $test
- * @return bool|null
- */
- protected function getDbIsolationState(\PHPUnit\Framework\TestCase $test)
- {
- $annotations = $this->getAnnotations($test);
- return isset($annotations[DbIsolation::MAGENTO_DB_ISOLATION])
- ? $annotations[DbIsolation::MAGENTO_DB_ISOLATION]
- : null;
- }
- /**
- * Execute single fixture script
- *
- * @param string|array $fixture
- * @throws \Exception
- */
- protected function _applyOneFixture($fixture)
- {
- try {
- if (is_callable($fixture)) {
- call_user_func($fixture);
- } else {
- require $fixture;
- }
- } catch (\Exception $e) {
- throw new Exception(
- sprintf(
- "Error in fixture: %s.\n %s\n %s",
- json_encode($fixture),
- $e->getMessage(),
- $e->getTraceAsString()
- ),
- 500,
- $e
- );
- }
- }
- /**
- * Execute fixture scripts if any
- *
- * @param array $fixtures
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function _applyFixtures(array $fixtures)
- {
- /* Execute fixture scripts */
- foreach ($fixtures as $oneFixture) {
- /* Skip already applied fixtures */
- if (in_array($oneFixture, $this->_appliedFixtures, true)) {
- continue;
- }
- $this->_applyOneFixture($oneFixture);
- $this->_appliedFixtures[] = $oneFixture;
- }
- }
- /**
- * Revert changes done by fixtures
- */
- protected function _revertFixtures()
- {
- $appliedFixtures = array_reverse($this->_appliedFixtures);
- foreach ($appliedFixtures as $fixture) {
- if (is_callable($fixture)) {
- $fixture[1] .= 'Rollback';
- if (is_callable($fixture)) {
- $this->_applyOneFixture($fixture);
- }
- } else {
- $fileInfo = pathinfo($fixture);
- $extension = '';
- if (isset($fileInfo['extension'])) {
- $extension = '.' . $fileInfo['extension'];
- }
- $rollbackScript = $fileInfo['dirname'] . '/' . $fileInfo['filename'] . '_rollback' . $extension;
- if (file_exists($rollbackScript)) {
- $this->_applyOneFixture($rollbackScript);
- }
- }
- }
- $this->_appliedFixtures = [];
- }
- }
|