CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.7 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.7
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • FixtureInjector
  • FixtureManager
  • TestFixture
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * For full copyright and license information, please see the LICENSE.txt
  8:  * Redistributions of files must retain the above copyright notice
  9:  *
 10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
 11:  * @since         1.2.0
 12:  * @license       https://opensource.org/licenses/mit-license.php MIT License
 13:  */
 14: namespace Cake\TestSuite\Fixture;
 15: 
 16: use Cake\Core\Exception\Exception as CakeException;
 17: use Cake\Database\Schema\TableSchema;
 18: use Cake\Database\Schema\TableSchemaAwareInterface;
 19: use Cake\Database\Schema\TableSchemaInterface as DatabaseTableSchemaInterface;
 20: use Cake\Datasource\ConnectionInterface;
 21: use Cake\Datasource\ConnectionManager;
 22: use Cake\Datasource\FixtureInterface;
 23: use Cake\Datasource\TableSchemaInterface;
 24: use Cake\Log\Log;
 25: use Cake\ORM\Locator\LocatorAwareTrait;
 26: use Cake\Utility\Inflector;
 27: use Exception;
 28: 
 29: /**
 30:  * Cake TestFixture is responsible for building and destroying tables to be used
 31:  * during testing.
 32:  */
 33: class TestFixture implements FixtureInterface, TableSchemaInterface, TableSchemaAwareInterface
 34: {
 35: 
 36:     use LocatorAwareTrait;
 37: 
 38:     /**
 39:      * Fixture Datasource
 40:      *
 41:      * @var string
 42:      */
 43:     public $connection = 'test';
 44: 
 45:     /**
 46:      * Full Table Name
 47:      *
 48:      * @var string
 49:      */
 50:     public $table;
 51: 
 52:     /**
 53:      * Fields / Schema for the fixture.
 54:      *
 55:      * This array should be compatible with Cake\Database\Schema\Schema.
 56:      * The `_constraints`, `_options` and `_indexes` keys are reserved for defining
 57:      * constraints, options and indexes respectively.
 58:      *
 59:      * @var array
 60:      */
 61:     public $fields = [];
 62: 
 63:     /**
 64:      * Configuration for importing fixture schema
 65:      *
 66:      * Accepts a `connection` and `model` or `table` key, to define
 67:      * which table and which connection contain the schema to be
 68:      * imported.
 69:      *
 70:      * @var array|null
 71:      */
 72:     public $import;
 73: 
 74:     /**
 75:      * Fixture records to be inserted.
 76:      *
 77:      * @var array
 78:      */
 79:     public $records = [];
 80: 
 81:     /**
 82:      * The schema for this fixture.
 83:      *
 84:      * @var \Cake\Database\Schema\TableSchema
 85:      */
 86:     protected $_schema;
 87: 
 88:     /**
 89:      * Fixture constraints to be created.
 90:      *
 91:      * @var array
 92:      */
 93:     protected $_constraints = [];
 94: 
 95:     /**
 96:      * Instantiate the fixture.
 97:      *
 98:      * @throws \Cake\Core\Exception\Exception on invalid datasource usage.
 99:      */
100:     public function __construct()
101:     {
102:         if (!empty($this->connection)) {
103:             $connection = $this->connection;
104:             if (strpos($connection, 'test') !== 0) {
105:                 $message = sprintf(
106:                     'Invalid datasource name "%s" for "%s" fixture. Fixture datasource names must begin with "test".',
107:                     $connection,
108:                     $this->table
109:                 );
110:                 throw new CakeException($message);
111:             }
112:         }
113:         $this->init();
114:     }
115: 
116:     /**
117:      * {@inheritDoc}
118:      */
119:     public function connection()
120:     {
121:         return $this->connection;
122:     }
123: 
124:     /**
125:      * {@inheritDoc}
126:      */
127:     public function sourceName()
128:     {
129:         return $this->table;
130:     }
131: 
132:     /**
133:      * Initialize the fixture.
134:      *
135:      * @return void
136:      * @throws \Cake\ORM\Exception\MissingTableClassException When importing from a table that does not exist.
137:      */
138:     public function init()
139:     {
140:         if ($this->table === null) {
141:             $this->table = $this->_tableFromClass();
142:         }
143: 
144:         if (empty($this->import) && !empty($this->fields)) {
145:             $this->_schemaFromFields();
146:         }
147: 
148:         if (!empty($this->import)) {
149:             $this->_schemaFromImport();
150:         }
151: 
152:         if (empty($this->import) && empty($this->fields)) {
153:             $this->_schemaFromReflection();
154:         }
155:     }
156: 
157:     /**
158:      * Returns the table name using the fixture class
159:      *
160:      * @return string
161:      */
162:     protected function _tableFromClass()
163:     {
164:         list(, $class) = namespaceSplit(get_class($this));
165:         preg_match('/^(.*)Fixture$/', $class, $matches);
166:         $table = $class;
167: 
168:         if (isset($matches[1])) {
169:             $table = $matches[1];
170:         }
171: 
172:         return Inflector::tableize($table);
173:     }
174: 
175:     /**
176:      * Build the fixtures table schema from the fields property.
177:      *
178:      * @return void
179:      */
180:     protected function _schemaFromFields()
181:     {
182:         $connection = ConnectionManager::get($this->connection());
183:         $this->_schema = new TableSchema($this->table);
184:         foreach ($this->fields as $field => $data) {
185:             if ($field === '_constraints' || $field === '_indexes' || $field === '_options') {
186:                 continue;
187:             }
188:             $this->_schema->addColumn($field, $data);
189:         }
190:         if (!empty($this->fields['_constraints'])) {
191:             foreach ($this->fields['_constraints'] as $name => $data) {
192:                 if (!$connection->supportsDynamicConstraints() || $data['type'] !== TableSchema::CONSTRAINT_FOREIGN) {
193:                     $this->_schema->addConstraint($name, $data);
194:                 } else {
195:                     $this->_constraints[$name] = $data;
196:                 }
197:             }
198:         }
199:         if (!empty($this->fields['_indexes'])) {
200:             foreach ($this->fields['_indexes'] as $name => $data) {
201:                 $this->_schema->addIndex($name, $data);
202:             }
203:         }
204:         if (!empty($this->fields['_options'])) {
205:             $this->_schema->setOptions($this->fields['_options']);
206:         }
207:     }
208: 
209:     /**
210:      * Build fixture schema from a table in another datasource.
211:      *
212:      * @return void
213:      * @throws \Cake\Core\Exception\Exception when trying to import from an empty table.
214:      */
215:     protected function _schemaFromImport()
216:     {
217:         if (!is_array($this->import)) {
218:             return;
219:         }
220:         $import = $this->import + ['connection' => 'default', 'table' => null, 'model' => null];
221: 
222:         if (!empty($import['model'])) {
223:             if (!empty($import['table'])) {
224:                 throw new CakeException('You cannot define both table and model.');
225:             }
226:             $import['table'] = $this->getTableLocator()->get($import['model'])->getTable();
227:         }
228: 
229:         if (empty($import['table'])) {
230:             throw new CakeException('Cannot import from undefined table.');
231:         }
232: 
233:         $this->table = $import['table'];
234: 
235:         $db = ConnectionManager::get($import['connection'], false);
236:         $schemaCollection = $db->getSchemaCollection();
237:         $table = $schemaCollection->describe($import['table']);
238:         $this->_schema = $table;
239:     }
240: 
241:     /**
242:      * Build fixture schema directly from the datasource
243:      *
244:      * @return void
245:      * @throws \Cake\Core\Exception\Exception when trying to reflect a table that does not exist
246:      */
247:     protected function _schemaFromReflection()
248:     {
249:         $db = ConnectionManager::get($this->connection());
250:         $schemaCollection = $db->getSchemaCollection();
251:         $tables = $schemaCollection->listTables();
252: 
253:         if (!in_array($this->table, $tables)) {
254:             throw new CakeException(
255:                 sprintf(
256:                     'Cannot describe schema for table `%s` for fixture `%s` : the table does not exist.',
257:                     $this->table,
258:                     get_class($this)
259:                 )
260:             );
261:         }
262: 
263:         $this->_schema = $schemaCollection->describe($this->table);
264:     }
265: 
266:     /**
267:      * Gets/Sets the TableSchema instance used by this fixture.
268:      *
269:      * @param \Cake\Database\Schema\TableSchema|null $schema The table to set.
270:      * @return \Cake\Database\Schema\TableSchema|null
271:      * @deprecated 3.5.0 Use getTableSchema/setTableSchema instead.
272:      */
273:     public function schema(TableSchema $schema = null)
274:     {
275:         deprecationWarning(
276:             'TestFixture::schema() is deprecated. ' .
277:             'Use TestFixture::setTableSchema()/getTableSchema() instead.'
278:         );
279:         if ($schema) {
280:             $this->setTableSchema($schema);
281:         }
282: 
283:         return $this->getTableSchema();
284:     }
285: 
286:     /**
287:      * {@inheritDoc}
288:      */
289:     public function create(ConnectionInterface $db)
290:     {
291:         if (empty($this->_schema)) {
292:             return false;
293:         }
294: 
295:         if (empty($this->import) && empty($this->fields)) {
296:             return true;
297:         }
298: 
299:         try {
300:             $queries = $this->_schema->createSql($db);
301:             foreach ($queries as $query) {
302:                 $stmt = $db->prepare($query);
303:                 $stmt->execute();
304:                 $stmt->closeCursor();
305:             }
306:         } catch (Exception $e) {
307:             $msg = sprintf(
308:                 'Fixture creation for "%s" failed "%s"',
309:                 $this->table,
310:                 $e->getMessage()
311:             );
312:             Log::error($msg);
313:             trigger_error($msg, E_USER_WARNING);
314: 
315:             return false;
316:         }
317: 
318:         return true;
319:     }
320: 
321:     /**
322:      * {@inheritDoc}
323:      */
324:     public function drop(ConnectionInterface $db)
325:     {
326:         if (empty($this->_schema)) {
327:             return false;
328:         }
329: 
330:         if (empty($this->import) && empty($this->fields)) {
331:             return true;
332:         }
333: 
334:         try {
335:             $sql = $this->_schema->dropSql($db);
336:             foreach ($sql as $stmt) {
337:                 $db->execute($stmt)->closeCursor();
338:             }
339:         } catch (Exception $e) {
340:             return false;
341:         }
342: 
343:         return true;
344:     }
345: 
346:     /**
347:      * {@inheritDoc}
348:      */
349:     public function insert(ConnectionInterface $db)
350:     {
351:         if (isset($this->records) && !empty($this->records)) {
352:             list($fields, $values, $types) = $this->_getRecords();
353:             $query = $db->newQuery()
354:                 ->insert($fields, $types)
355:                 ->into($this->table);
356: 
357:             foreach ($values as $row) {
358:                 $query->values($row);
359:             }
360:             $statement = $query->execute();
361:             $statement->closeCursor();
362: 
363:             return $statement;
364:         }
365: 
366:         return true;
367:     }
368: 
369:     /**
370:      * {@inheritDoc}
371:      */
372:     public function createConstraints(ConnectionInterface $db)
373:     {
374:         if (empty($this->_constraints)) {
375:             return true;
376:         }
377: 
378:         foreach ($this->_constraints as $name => $data) {
379:             $this->_schema->addConstraint($name, $data);
380:         }
381: 
382:         $sql = $this->_schema->addConstraintSql($db);
383: 
384:         if (empty($sql)) {
385:             return true;
386:         }
387: 
388:         foreach ($sql as $stmt) {
389:             $db->execute($stmt)->closeCursor();
390:         }
391: 
392:         return true;
393:     }
394: 
395:     /**
396:      * {@inheritDoc}
397:      */
398:     public function dropConstraints(ConnectionInterface $db)
399:     {
400:         if (empty($this->_constraints)) {
401:             return true;
402:         }
403: 
404:         $sql = $this->_schema->dropConstraintSql($db);
405: 
406:         if (empty($sql)) {
407:             return true;
408:         }
409: 
410:         foreach ($sql as $stmt) {
411:             $db->execute($stmt)->closeCursor();
412:         }
413: 
414:         foreach ($this->_constraints as $name => $data) {
415:             $this->_schema->dropConstraint($name);
416:         }
417: 
418:         return true;
419:     }
420: 
421:     /**
422:      * Converts the internal records into data used to generate a query.
423:      *
424:      * @return array
425:      */
426:     protected function _getRecords()
427:     {
428:         $fields = $values = $types = [];
429:         $columns = $this->_schema->columns();
430:         foreach ($this->records as $record) {
431:             $fields = array_merge($fields, array_intersect(array_keys($record), $columns));
432:         }
433:         $fields = array_values(array_unique($fields));
434:         foreach ($fields as $field) {
435:             $types[$field] = $this->_schema->getColumn($field)['type'];
436:         }
437:         $default = array_fill_keys($fields, null);
438:         foreach ($this->records as $record) {
439:             $values[] = array_merge($default, $record);
440:         }
441: 
442:         return [$fields, $values, $types];
443:     }
444: 
445:     /**
446:      * {@inheritDoc}
447:      */
448:     public function truncate(ConnectionInterface $db)
449:     {
450:         $sql = $this->_schema->truncateSql($db);
451:         foreach ($sql as $stmt) {
452:             $db->execute($stmt)->closeCursor();
453:         }
454: 
455:         return true;
456:     }
457: 
458:     /**
459:      * {@inheritDoc}
460:      */
461:     public function getTableSchema()
462:     {
463:         return $this->_schema;
464:     }
465: 
466:     /**
467:      * {@inheritDoc}
468:      */
469:     public function setTableSchema(DatabaseTableSchemaInterface $schema)
470:     {
471:         $this->_schema = $schema;
472: 
473:         return $this;
474:     }
475: }
476: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs