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.8 Red Velvet API

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