Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/bake/src/Shell/Task/FixtureTask.php
<?php
/**
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @since         0.1.0
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */
namespace Bake\Shell\Task;

use
Cake\Console\Shell;
use
Cake\Core\Configure;
use
Cake\Database\Exception;
use
Cake\Database\Schema\TableSchema;
use
Cake\Datasource\ConnectionManager;
use
Cake\ORM\TableRegistry;
use
Cake\Utility\Inflector;
use
Cake\Utility\Text;
use
DateTimeInterface;

/**
 * Task class for creating and updating fixtures files.
 *
 * @property \Bake\Shell\Task\BakeTemplateTask $BakeTemplate
 * @property \Bake\Shell\Task\ModelTask $Model
 */
class FixtureTask extends BakeTask
{
   
/**
     * Tasks to be loaded by this Task
     *
     * @var array
     */
   
public $tasks = [
       
'Bake.Model',
       
'Bake.BakeTemplate',
    ];

   
/**
     * Get the file path.
     *
     * @return string
     */
   
public function getPath()
    {
       
$dir = 'Fixture/';
       
$path = defined('TESTS') ? TESTS . $dir : ROOT . DS . 'tests' . DS . $dir;
        if (isset(
$this->plugin)) {
           
$path = $this->_pluginPath($this->plugin) . 'tests/' . $dir;
        }

        return
str_replace('/', DS, $path);
    }

   
/**
     * Gets the option parser instance and configures it.
     *
     * @return \Cake\Console\ConsoleOptionParser
     */
   
public function getOptionParser()
    {
       
$parser = parent::getOptionParser();

       
$parser = $parser->setDescription(
           
'Generate fixtures for use with the test suite. You can use `bake fixture all` to bake all fixtures.'
       
)->addArgument('name', [
           
'help' => 'Name of the fixture to bake (without the `Fixture` suffix). ' .
               
'You can use Plugin.name to bake plugin fixtures.',
        ])->
addOption('table', [
           
'help' => 'The table name if it does not follow conventions.',
        ])->
addOption('count', [
           
'help' => 'When using generated data, the number of records to include in the fixture(s).',
           
'short' => 'n',
           
'default' => 1,
        ])->
addOption('schema', [
           
'help' => 'Create a fixture that imports schema, instead of dumping a schema snapshot into the fixture.',
           
'short' => 's',
           
'boolean' => true,
        ])->
addOption('records', [
           
'help' => 'Generate a fixture with records from the non-test database.' .
           
' Used with --count and --conditions to limit which records are added to the fixture.',
           
'short' => 'r',
           
'boolean' => true,
        ])->
addOption('conditions', [
           
'help' => 'The SQL snippet to use when importing records.',
           
'default' => '1=1',
        ])->
addSubcommand('all', [
           
'help' => 'Bake all fixture files for tables in the chosen connection.',
        ]);

        return
$parser;
    }

   
/**
     * Execution method always used for tasks
     * Handles dispatching to interactive, named, or all processes.
     *
     * @param string|null $name The name of the fixture to bake.
     * @return null|bool
     */
   
public function main($name = null)
    {
       
parent::main();
       
$name = $this->_getName($name);

        if (empty(
$name)) {
           
$this->out('Choose a fixture to bake from the following:');
            foreach (
$this->Model->listUnskipped() as $table) {
               
$this->out('- ' . $this->_camelize($table));
            }

            return
true;
        }

       
$table = null;
        if (isset(
$this->params['table'])) {
           
$table = $this->params['table'];
        }
       
$model = $this->_camelize($name);
       
$this->bake($model, $table);
    }

   
/**
     * Bake All the Fixtures at once. Will only bake fixtures for models that exist.
     *
     * @return void
     */
   
public function all()
    {
       
$tables = $this->Model->listUnskipped();

        foreach (
$tables as $table) {
           
$this->main($table);
        }
    }

   
/**
     * Assembles and writes a Fixture file
     *
     * @param string $model Name of model to bake.
     * @param string|null $useTable Name of table to use.
     * @return string Baked fixture content
     * @throws \RuntimeException
     */
   
public function bake($model, $useTable = null)
    {
       
$table = $schema = $records = $import = $modelImport = null;

        if (!
$useTable) {
           
$useTable = Inflector::tableize($model);
        } elseif (
$useTable !== Inflector::tableize($model)) {
           
$table = $useTable;
        }

       
$importBits = [];
        if (!empty(
$this->params['schema'])) {
           
$modelImport = true;
           
$importBits[] = "'table' => '{$useTable}'";
        }
        if (!empty(
$importBits) && $this->connection !== 'default') {
           
$importBits[] = "'connection' => '{$this->connection}'";
        }
        if (!empty(
$importBits)) {
           
$import = sprintf("[%s]", implode(', ', $importBits));
        }

        try {
           
$data = $this->readSchema($model, $useTable);
        } catch (
Exception $e) {
           
TableRegistry::getTableLocator()->remove($model);
           
$useTable = Inflector::underscore($model);
           
$table = $useTable;
           
$data = $this->readSchema($model, $useTable);
        }

        if (
$modelImport === null) {
           
$schema = $this->_generateSchema($data);
        }

        if (empty(
$this->params['records'])) {
           
$recordCount = 1;
            if (isset(
$this->params['count'])) {
               
$recordCount = $this->params['count'];
            }
           
$records = $this->_makeRecordString($this->_generateRecords($data, $recordCount));
        }
        if (!empty(
$this->params['records'])) {
           
$records = $this->_makeRecordString($this->_getRecordsFromTable($model, $useTable));
        }

        return
$this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import'));
    }

   
/**
     * Get schema metadata for the current table mapping.
     *
     * @param string $name The model alias to use
     * @param string $table The table name to get schema metadata for.
     * @return \Cake\Database\Schema\TableSchema
     */
   
public function readSchema($name, $table)
    {
       
$connection = ConnectionManager::get($this->connection);

        if (
TableRegistry::getTableLocator()->exists($name)) {
           
$model = TableRegistry::getTableLocator()->get($name);
        } else {
           
$model = TableRegistry::getTableLocator()->get($name, [
               
'table' => $table,
               
'connection' => $connection,
            ]);
        }

        return
$model->getSchema();
    }

   
/**
     * Generate the fixture file, and write to disk
     *
     * @param string $model name of the model being generated
     * @param array $otherVars Contents of the fixture file.
     * @return string Content saved into fixture file.
     */
   
public function generateFixtureFile($model, array $otherVars)
    {
       
$defaults = [
           
'name' => $model,
           
'table' => null,
           
'schema' => null,
           
'records' => null,
           
'import' => null,
           
'fields' => null,
           
'namespace' => Configure::read('App.namespace'),
        ];
        if (
$this->plugin) {
           
$defaults['namespace'] = $this->_pluginNamespace($this->plugin);
        }
       
$vars = $otherVars + $defaults;

       
$path = $this->getPath();
       
$filename = $vars['name'] . 'Fixture.php';

       
$this->BakeTemplate->set('model', $model);
       
$this->BakeTemplate->set($vars);
       
$content = $this->BakeTemplate->generate('tests/fixture');

       
$this->out("\n" . sprintf('Baking test fixture for %s...', $model), 1, Shell::QUIET);
       
$this->createFile($path . $filename, $content);
       
$emptyFile = $path . 'empty';
       
$this->_deleteEmptyFile($emptyFile);

        return
$content;
    }

   
/**
     * Generates a string representation of a schema.
     *
     * @param \Cake\Database\Schema\TableSchema $table Table schema
     * @return string fields definitions
     */
   
protected function _generateSchema(TableSchema $table)
    {
       
$cols = $indexes = $constraints = [];
        foreach (
$table->columns() as $field) {
           
$fieldData = $table->getColumn($field);
           
$properties = implode(', ', $this->_values($fieldData));
           
$cols[] = "        '$field' => [$properties],";
        }
        foreach (
$table->indexes() as $index) {
           
$fieldData = $table->getIndex($index);
           
$properties = implode(', ', $this->_values($fieldData));
           
$indexes[] = "            '$index' => [$properties],";
        }
        foreach (
$table->constraints() as $index) {
           
$fieldData = $table->getConstraint($index);
           
$properties = implode(', ', $this->_values($fieldData));
           
$constraints[] = "            '$index' => [$properties],";
        }
       
$options = $this->_values($table->getOptions());

       
$content = implode("\n", $cols) . "\n";
        if (!empty(
$indexes)) {
           
$content .= "        '_indexes' => [\n" . implode("\n", $indexes) . "\n        ],\n";
        }
        if (!empty(
$constraints)) {
           
$content .= "        '_constraints' => [\n" . implode("\n", $constraints) . "\n        ],\n";
        }
        if (!empty(
$options)) {
            foreach (
$options as &$option) {
               
$option = '            ' . $option;
            }
           
$content .= "        '_options' => [\n" . implode(",\n", $options) . "\n        ],\n";
        }

        return
"[\n$content    ]";
    }

   
/**
     * Formats Schema columns from Model Object
     *
     * @param array $values options keys(type, null, default, key, length, extra)
     * @return array Formatted values
     */
   
protected function _values($values)
    {
       
$vals = [];
        if (!
is_array($values)) {
            return
$vals;
        }
        foreach (
$values as $key => $val) {
            if (
is_array($val)) {
               
$vals[] = "'{$key}' => [" . implode(", ", $this->_values($val)) . "]";
            } else {
               
$val = var_export($val, true);
                if (
$val === 'NULL') {
                   
$val = 'null';
                }
                if (!
is_numeric($key)) {
                   
$vals[] = "'{$key}' => {$val}";
                } else {
                   
$vals[] = "{$val}";
                }
            }
        }

        return
$vals;
    }

   
/**
     * Generate String representation of Records
     *
     * @param \Cake\Database\Schema\TableSchema $table Table schema array
     * @param int $recordCount The number of records to generate.
     * @return array Array of records to use in the fixture.
     */
   
protected function _generateRecords(TableSchema $table, $recordCount = 1)
    {
       
$records = [];
        for (
$i = 0; $i < $recordCount; $i++) {
           
$record = [];
            foreach (
$table->columns() as $field) {
               
$fieldInfo = $table->getColumn($field);
               
$insert = '';
                switch (
$fieldInfo['type']) {
                    case
'decimal':
                       
$insert = $i + 1.5;
                        break;
                    case
'biginteger':
                    case
'integer':
                    case
'float':
                    case
'smallinteger':
                    case
'tinyinteger':
                       
$insert = $i + 1;
                        break;
                    case
'string':
                    case
'binary':
                       
$isPrimary = in_array($field, $table->primaryKey());
                        if (
$isPrimary) {
                           
$insert = Text::uuid();
                        } else {
                           
$insert = "Lorem ipsum dolor sit amet";
                            if (!empty(
$fieldInfo['length'])) {
                               
$insert = substr($insert, 0, (int)$fieldInfo['length'] > 2 ? (int)$fieldInfo['length'] - 2 : (int)$fieldInfo['length']);
                            }
                        }
                        break;
                    case
'timestamp':
                       
$insert = time();
                        break;
                    case
'datetime':
                       
$insert = date('Y-m-d H:i:s');
                        break;
                    case
'date':
                       
$insert = date('Y-m-d');
                        break;
                    case
'time':
                       
$insert = date('H:i:s');
                        break;
                    case
'boolean':
                       
$insert = 1;
                        break;
                    case
'text':
                       
$insert = "Lorem ipsum dolor sit amet, aliquet feugiat.";
                       
$insert .= " Convallis morbi fringilla gravida,";
                       
$insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin";
                       
$insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla";
                       
$insert .= " vestibulum massa neque ut et, id hendrerit sit,";
                       
$insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus";
                       
$insert .= " duis vestibulum nunc mattis convallis.";
                        break;
                    case
'uuid':
                       
$insert = Text::uuid();
                        break;
                }
               
$record[$field] = $insert;
            }
           
$records[] = $record;
        }

        return
$records;
    }

   
/**
     * Convert a $records array into a string.
     *
     * @param array $records Array of records to be converted to string
     * @return string A string value of the $records array.
     */
   
protected function _makeRecordString($records)
    {
       
$out = "[\n";
        foreach (
$records as $record) {
           
$values = [];
            foreach (
$record as $field => $value) {
                if (
$value instanceof DateTimeInterface) {
                   
$value = $value->format('Y-m-d H:i:s');
                }
               
$val = var_export($value, true);
                if (
$val === 'NULL') {
                   
$val = 'null';
                }
               
$values[] = "                '$field' => $val";
            }
           
$out .= "            [\n";
           
$out .= implode(",\n", $values);
           
$out .= ",\n            ],\n";
        }
       
$out .= "        ]";

        return
$out;
    }

   
/**
     * Interact with the user to get a custom SQL condition and use that to extract data
     * to build a fixture.
     *
     * @param string $modelName name of the model to take records from.
     * @param string|null $useTable Name of table to use.
     * @return array Array of records.
     */
   
protected function _getRecordsFromTable($modelName, $useTable = null)
    {
       
$recordCount = (isset($this->params['count']) ? $this->params['count'] : 10);
       
$conditions = (isset($this->params['conditions']) ? $this->params['conditions'] : '1=1');
        if (
TableRegistry::getTableLocator()->exists($modelName)) {
           
$model = TableRegistry::getTableLocator()->get($modelName);
        } else {
           
$model = TableRegistry::getTableLocator()->get($modelName, [
               
'table' => $useTable,
               
'connection' => ConnectionManager::get($this->connection),
            ]);
        }
       
$records = $model->find('all')
            ->
where($conditions)
            ->
limit($recordCount)
            ->
enableHydration(false);

        return
$records->toArray();
    }
}