CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.4 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.4
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 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

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • BakeTask
  • ControllerTask
  • DbConfigTask
  • ExtractTask
  • FixtureTask
  • ModelTask
  • PluginTask
  • ProjectTask
  • TemplateTask
  • TestTask
  • ViewTask
  1: <?php
  2: /**
  3:  * The FixtureTask handles creating and updating fixture files.
  4:  *
  5:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7:  *
  8:  * Licensed under The MIT License
  9:  * For full copyright and license information, please see the LICENSE.txt
 10:  * Redistributions of files must retain the above copyright notice.
 11:  *
 12:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 13:  * @link          http://cakephp.org CakePHP(tm) Project
 14:  * @since         CakePHP(tm) v 1.3
 15:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 16:  */
 17: 
 18: App::uses('AppShell', 'Console/Command');
 19: App::uses('BakeTask', 'Console/Command/Task');
 20: App::uses('Model', 'Model');
 21: 
 22: /**
 23:  * Task class for creating and updating fixtures files.
 24:  *
 25:  * @package       Cake.Console.Command.Task
 26:  */
 27: class FixtureTask extends BakeTask {
 28: 
 29: /**
 30:  * Tasks to be loaded by this Task
 31:  *
 32:  * @var array
 33:  */
 34:     public $tasks = array('DbConfig', 'Model', 'Template');
 35: 
 36: /**
 37:  * path to fixtures directory
 38:  *
 39:  * @var string
 40:  */
 41:     public $path = null;
 42: 
 43: /**
 44:  * Schema instance
 45:  *
 46:  * @var CakeSchema
 47:  */
 48:     protected $_Schema = null;
 49: 
 50: /**
 51:  * Override initialize
 52:  *
 53:  * @param ConsoleOutput $stdout A ConsoleOutput object for stdout.
 54:  * @param ConsoleOutput $stderr A ConsoleOutput object for stderr.
 55:  * @param ConsoleInput $stdin A ConsoleInput object for stdin.
 56:  */
 57:     public function __construct($stdout = null, $stderr = null, $stdin = null) {
 58:         parent::__construct($stdout, $stderr, $stdin);
 59:         $this->path = APP . 'Test' . DS . 'Fixture' . DS;
 60:     }
 61: 
 62: /**
 63:  * get the option parser.
 64:  *
 65:  * @return void
 66:  */
 67:     public function getOptionParser() {
 68:         $parser = parent::getOptionParser();
 69:         return $parser->description(
 70:             __d('cake_console', 'Generate fixtures for use with the test suite. You can use `bake fixture all` to bake all fixtures.')
 71:         )->addArgument('name', array(
 72:             'help' => __d('cake_console', 'Name of the fixture to bake. Can use Plugin.name to bake plugin fixtures.')
 73:         ))->addOption('count', array(
 74:             'help' => __d('cake_console', 'When using generated data, the number of records to include in the fixture(s).'),
 75:             'short' => 'n',
 76:             'default' => 10
 77:         ))->addOption('connection', array(
 78:             'help' => __d('cake_console', 'Which database configuration to use for baking.'),
 79:             'short' => 'c',
 80:             'default' => 'default'
 81:         ))->addOption('plugin', array(
 82:             'help' => __d('cake_console', 'CamelCased name of the plugin to bake fixtures for.'),
 83:             'short' => 'p',
 84:         ))->addOption('schema', array(
 85:             'help' => __d('cake_console', 'Importing schema for fixtures rather than hardcoding it.'),
 86:             'short' => 's',
 87:             'boolean' => true
 88:         ))->addOption('theme', array(
 89:             'short' => 't',
 90:             'help' => __d('cake_console', 'Theme to use when baking code.')
 91:         ))->addOption('force', array(
 92:             'short' => 'f',
 93:             'help' => __d('cake_console', 'Force overwriting existing files without prompting.')
 94:         ))->addOption('records', array(
 95:             'help' => __d('cake_console', 'Used with --count and <name>/all commands to pull [n] records from the live tables, where [n] is either --count or the default of 10.'),
 96:             'short' => 'r',
 97:             'boolean' => true
 98:         ))->epilog(__d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.'));
 99:     }
100: 
101: /**
102:  * Execution method always used for tasks
103:  * Handles dispatching to interactive, named, or all processes.
104:  *
105:  * @return void
106:  */
107:     public function execute() {
108:         parent::execute();
109:         if (empty($this->args)) {
110:             $this->_interactive();
111:         }
112: 
113:         if (isset($this->args[0])) {
114:             $this->interactive = false;
115:             if (!isset($this->connection)) {
116:                 $this->connection = 'default';
117:             }
118:             if (strtolower($this->args[0]) === 'all') {
119:                 return $this->all();
120:             }
121:             $model = $this->_modelName($this->args[0]);
122:             $this->bake($model);
123:         }
124:     }
125: 
126: /**
127:  * Bake All the Fixtures at once. Will only bake fixtures for models that exist.
128:  *
129:  * @return void
130:  */
131:     public function all() {
132:         $this->interactive = false;
133:         $this->Model->interactive = false;
134:         $tables = $this->Model->listAll($this->connection, false);
135: 
136:         foreach ($tables as $table) {
137:             $model = $this->_modelName($table);
138:             $importOptions = array();
139:             if (!empty($this->params['schema'])) {
140:                 $importOptions['schema'] = $model;
141:             }
142:             $this->bake($model, false, $importOptions);
143:         }
144:     }
145: 
146: /**
147:  * Interactive baking function
148:  *
149:  * @return void
150:  */
151:     protected function _interactive() {
152:         $this->DbConfig->interactive = $this->Model->interactive = $this->interactive = true;
153:         $this->hr();
154:         $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->getPath()));
155:         $this->hr();
156: 
157:         if (!isset($this->connection)) {
158:             $this->connection = $this->DbConfig->getConfig();
159:         }
160:         $modelName = $this->Model->getName($this->connection);
161:         $useTable = $this->Model->getTable($modelName, $this->connection);
162:         $importOptions = $this->importOptions($modelName);
163:         $this->bake($modelName, $useTable, $importOptions);
164:     }
165: 
166: /**
167:  * Interacts with the User to setup an array of import options. For a fixture.
168:  *
169:  * @param string $modelName Name of model you are dealing with.
170:  * @return array Array of import options.
171:  */
172:     public function importOptions($modelName) {
173:         $options = array();
174: 
175:         if (!empty($this->params['schema'])) {
176:             $options['schema'] = $modelName;
177:         } else {
178:             $doSchema = $this->in(__d('cake_console', 'Would you like to import schema for this fixture?'), array('y', 'n'), 'n');
179:             if ($doSchema === 'y') {
180:                 $options['schema'] = $modelName;
181:             }
182:         }
183:         if (!empty($this->params['records'])) {
184:             $doRecords = 'y';
185:         } else {
186:             $doRecords = $this->in(__d('cake_console', 'Would you like to use record importing for this fixture?'), array('y', 'n'), 'n');
187:         }
188:         if ($doRecords === 'y') {
189:             $options['records'] = true;
190:         }
191:         if ($doRecords === 'n') {
192:             $prompt = __d('cake_console', "Would you like to build this fixture with data from %s's table?", $modelName);
193:             $fromTable = $this->in($prompt, array('y', 'n'), 'n');
194:             if (strtolower($fromTable) === 'y') {
195:                 $options['fromTable'] = true;
196:             }
197:         }
198:         return $options;
199:     }
200: 
201: /**
202:  * Assembles and writes a Fixture file
203:  *
204:  * @param string $model Name of model to bake.
205:  * @param string $useTable Name of table to use.
206:  * @param array $importOptions Options for public $import
207:  * @return string Baked fixture content
208:  */
209:     public function bake($model, $useTable = false, $importOptions = array()) {
210:         App::uses('CakeSchema', 'Model');
211:         $table = $schema = $records = $import = $modelImport = null;
212:         $importBits = array();
213: 
214:         if (!$useTable) {
215:             $useTable = Inflector::tableize($model);
216:         } elseif ($useTable != Inflector::tableize($model)) {
217:             $table = $useTable;
218:         }
219: 
220:         if (!empty($importOptions)) {
221:             if (isset($importOptions['schema'])) {
222:                 $modelImport = true;
223:                 $importBits[] = "'model' => '{$importOptions['schema']}'";
224:             }
225:             if (isset($importOptions['records'])) {
226:                 $importBits[] = "'records' => true";
227:             }
228:             if ($this->connection !== 'default') {
229:                 $importBits[] .= "'connection' => '{$this->connection}'";
230:             }
231:             if (!empty($importBits)) {
232:                 $import = sprintf("array(%s)", implode(', ', $importBits));
233:             }
234:         }
235: 
236:         $this->_Schema = new CakeSchema();
237:         $data = $this->_Schema->read(array('models' => false, 'connection' => $this->connection));
238:         if (!isset($data['tables'][$useTable])) {
239:             $this->error('Could not find your selected table ' . $useTable);
240:             return false;
241:         }
242: 
243:         $tableInfo = $data['tables'][$useTable];
244:         if ($modelImport === null) {
245:             $schema = $this->_generateSchema($tableInfo);
246:         }
247: 
248:         if (empty($importOptions['records']) && !isset($importOptions['fromTable'])) {
249:             $recordCount = 1;
250:             if (isset($this->params['count'])) {
251:                 $recordCount = $this->params['count'];
252:             }
253:             $records = $this->_makeRecordString($this->_generateRecords($tableInfo, $recordCount));
254:         }
255:         if (!empty($this->params['records']) || isset($importOptions['fromTable'])) {
256:             $records = $this->_makeRecordString($this->_getRecordsFromTable($model, $useTable));
257:         }
258:         $out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import'));
259:         return $out;
260:     }
261: 
262: /**
263:  * Generate the fixture file, and write to disk
264:  *
265:  * @param string $model name of the model being generated
266:  * @param string $otherVars Contents of the fixture file.
267:  * @return string Content saved into fixture file.
268:  */
269:     public function generateFixtureFile($model, $otherVars) {
270:         $defaults = array('table' => null, 'schema' => null, 'records' => null, 'import' => null, 'fields' => null);
271:         $vars = array_merge($defaults, $otherVars);
272: 
273:         $path = $this->getPath();
274:         $filename = Inflector::camelize($model) . 'Fixture.php';
275: 
276:         $this->Template->set('model', $model);
277:         $this->Template->set($vars);
278:         $content = $this->Template->generate('classes', 'fixture');
279: 
280:         $this->out("\n" . __d('cake_console', 'Baking test fixture for %s...', $model), 1, Shell::QUIET);
281:         $this->createFile($path . $filename, $content);
282:         return $content;
283:     }
284: 
285: /**
286:  * Get the path to the fixtures.
287:  *
288:  * @return string Path for the fixtures
289:  */
290:     public function getPath() {
291:         $path = $this->path;
292:         if (isset($this->plugin)) {
293:             $path = $this->_pluginPath($this->plugin) . 'Test' . DS . 'Fixture' . DS;
294:         }
295:         return $path;
296:     }
297: 
298: /**
299:  * Generates a string representation of a schema.
300:  *
301:  * @param array $tableInfo Table schema array
302:  * @return string fields definitions
303:  */
304:     protected function _generateSchema($tableInfo) {
305:         $schema = trim($this->_Schema->generateTable('f', $tableInfo), "\n");
306:         return substr($schema, 13, -1);
307:     }
308: 
309: /**
310:  * Generate String representation of Records
311:  *
312:  * @param array $tableInfo Table schema array
313:  * @param integer $recordCount
314:  * @return array Array of records to use in the fixture.
315:  */
316:     protected function _generateRecords($tableInfo, $recordCount = 1) {
317:         $records = array();
318:         for ($i = 0; $i < $recordCount; $i++) {
319:             $record = array();
320:             foreach ($tableInfo as $field => $fieldInfo) {
321:                 if (empty($fieldInfo['type'])) {
322:                     continue;
323:                 }
324:                 $insert = '';
325:                 switch ($fieldInfo['type']) {
326:                     case 'integer':
327:                     case 'float':
328:                         $insert = $i + 1;
329:                         break;
330:                     case 'string':
331:                     case 'binary':
332:                         $isPrimaryUuid = (
333:                             isset($fieldInfo['key']) && strtolower($fieldInfo['key']) === 'primary' &&
334:                             isset($fieldInfo['length']) && $fieldInfo['length'] == 36
335:                         );
336:                         if ($isPrimaryUuid) {
337:                             $insert = String::uuid();
338:                         } else {
339:                             $insert = "Lorem ipsum dolor sit amet";
340:                             if (!empty($fieldInfo['length'])) {
341:                                 $insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
342:                             }
343:                         }
344:                         break;
345:                     case 'timestamp':
346:                         $insert = time();
347:                         break;
348:                     case 'datetime':
349:                         $insert = date('Y-m-d H:i:s');
350:                         break;
351:                     case 'date':
352:                         $insert = date('Y-m-d');
353:                         break;
354:                     case 'time':
355:                         $insert = date('H:i:s');
356:                         break;
357:                     case 'boolean':
358:                         $insert = 1;
359:                         break;
360:                     case 'text':
361:                         $insert = "Lorem ipsum dolor sit amet, aliquet feugiat.";
362:                         $insert .= " Convallis morbi fringilla gravida,";
363:                         $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin";
364:                         $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla";
365:                         $insert .= " vestibulum massa neque ut et, id hendrerit sit,";
366:                         $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus";
367:                         $insert .= " duis vestibulum nunc mattis convallis.";
368:                         break;
369:                 }
370:                 $record[$field] = $insert;
371:             }
372:             $records[] = $record;
373:         }
374:         return $records;
375:     }
376: 
377: /**
378:  * Convert a $records array into a a string.
379:  *
380:  * @param array $records Array of records to be converted to string
381:  * @return string A string value of the $records array.
382:  */
383:     protected function _makeRecordString($records) {
384:         $out = "array(\n";
385:         foreach ($records as $record) {
386:             $values = array();
387:             foreach ($record as $field => $value) {
388:                 $val = var_export($value, true);
389:                 if ($val === 'NULL') {
390:                     $val = 'null';
391:                 }
392:                 $values[] = "\t\t\t'$field' => $val";
393:             }
394:             $out .= "\t\tarray(\n";
395:             $out .= implode(",\n", $values);
396:             $out .= "\n\t\t),\n";
397:         }
398:         $out .= "\t)";
399:         return $out;
400:     }
401: 
402: /**
403:  * Interact with the user to get a custom SQL condition and use that to extract data
404:  * to build a fixture.
405:  *
406:  * @param string $modelName name of the model to take records from.
407:  * @param string $useTable Name of table to use.
408:  * @return array Array of records.
409:  */
410:     protected function _getRecordsFromTable($modelName, $useTable = null) {
411:         if ($this->interactive) {
412:             $condition = null;
413:             $prompt = __d('cake_console', "Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1");
414:             while (!$condition) {
415:                 $condition = $this->in($prompt, null, 'WHERE 1=1');
416:             }
417:             $prompt = __d('cake_console', "How many records do you want to import?");
418:             $recordCount = $this->in($prompt, null, 10);
419:         } else {
420:             $condition = 'WHERE 1=1';
421:             $recordCount = (isset($this->params['count']) ? $this->params['count'] : 10);
422:         }
423:         $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection));
424:         $records = $modelObject->find('all', array(
425:             'conditions' => $condition,
426:             'recursive' => -1,
427:             'limit' => $recordCount
428:         ));
429: 
430:         $schema = $modelObject->schema(true);
431:         $out = array();
432:         foreach ($records as $record) {
433:             $row = array();
434:             foreach ($record[$modelObject->alias] as $field => $value) {
435:                 if ($schema[$field]['type'] === 'boolean') {
436:                     $value = (int)(bool)$value;
437:                 }
438:                 $row[$field] = $value;
439:             }
440:             $out[] = $row;
441:         }
442:         return $out;
443:     }
444: 
445: }
446: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs