Skip to content

Commit

Permalink
Merge pull request #5 from sizuhiko/feature/define
Browse files Browse the repository at this point in the history
Feature 1.2
  • Loading branch information
sizuhiko committed Jun 6, 2014
2 parents d05bcdc + 61215b6 commit 1f36d00
Show file tree
Hide file tree
Showing 17 changed files with 928 additions and 159 deletions.
27 changes: 27 additions & 0 deletions Lib/Definition/FabricateDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* FabricateDefinition class
*/
class FabricateDefinition {
private $define = false;
public $parent = false;

/**
* @param mixed $define callback or attributes
*/
public function __construct($define) {
$this->define = $define;
}

public function run($data, $world) {
$result = [];
if(is_callable($this->define)) {
$callback = $this->define;
$result = $callback($data, $world);
} else if(is_array($this->define)) {
$result = $this->define;
}
return $result;
}
}
187 changes: 102 additions & 85 deletions Lib/Fabricate.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<?php
App::uses('FabricateConfig', 'Fabricate.Lib');
App::uses('FabricateContext', 'Fabricate.Lib');
App::uses('FabricateRegistry', 'Fabricate.Lib');
App::uses('FabricateFactory', 'Fabricate.Lib/Factory');
App::uses('FabricateDefinition', 'Fabricate.Lib/Definition');

/**
* Fabricator for CakePHP model.
Expand All @@ -9,13 +12,19 @@
class Fabricate {
private static $_instance = null;
private $config;
private $registry;
private $factory;
private $traits;

/**
* Return Fabricator instance
*/
private static function getInstance() {
if(self::$_instance == null) {
self::$_instance = new Fabricate();
self::$_instance->config = new FabricateConfig();
self::$_instance->registry = new FabricateRegistry('Fabricate');
self::$_instance->traits = [];
}
return self::$_instance;
}
Expand All @@ -24,8 +33,11 @@ private static function getInstance() {
* Override constructor.
*/
public function __construct() {
$this->config = new FabricateConfig();
}
}

public static function clear() {
self::$_instance = null;
}

/**
* To override these settings
Expand All @@ -43,11 +55,10 @@ public static function config($callback) {
*/
public static function create($modelName, $recordCount=1, $callback = null) {
$attributes = self::attributes_for($modelName, $recordCount, $callback);
$model = ClassRegistry::init($modelName);
foreach ($attributes as $data) {
$model->create($data);
$model->save(null, self::getInstance()->config->auto_validate);
}
$instance = self::getInstance();
$definition = $instance->definition($recordCount, $callback);
$recordCount = $instance->recordCount($recordCount);
return $instance->factory->create($attributes, $recordCount, $definition);
}
/**
* Only create a model instance.
Expand All @@ -57,97 +68,103 @@ public static function create($modelName, $recordCount=1, $callback = null) {
*/
public static function build($modelName, $callback = null) {
$data = self::attributes_for($modelName, 1, $callback);
$model = ClassRegistry::init($modelName);
$model->create($data[0]);
return $model;
$instance = self::getInstance();
$definition = $instance->definition(1, $callback);
return $instance->factory->build($data, $definition);
}
/**
* Only create model attributes array.
* @return array model attributes array.
*/
public static function attributes_for($modelName, $recordCount=1, $callback = null) {
if(is_callable($recordCount) || is_array($recordCount)) {
$callback = $recordCount;
$recordCount = 1;
}
$model = ClassRegistry::init($modelName);
$results = self::getInstance()->_generateRecords($model->schema(), $recordCount, $callback);
return $results;
$instance = self::getInstance();
$instance->factory = $instance->factory($modelName);
$definition = $instance->definition($recordCount, $callback);
$recordCount = $instance->recordCount($recordCount);
return $instance->factory->attributes_for($recordCount, $definition);
}

/**
* Generate String representation of Records
*
* @param array $tableInfo Table schema array
* @param integer $recordCount
* @return array Array of records.
* Only create model attributes array for association.
* @return array model attributes array.
*/
private function _generateRecords($tableInfo, $recordCount = 1, $callback) {
$world = new FabricateContext($this->config);
$records = array();
for ($i = 0; $i < $recordCount; $i++) {
$record = array();
foreach ($tableInfo as $field => $fieldInfo) {
if (empty($fieldInfo['type'])) {
continue;
}
$insert = '';
switch ($fieldInfo['type']) {
case 'integer':
case 'float':
$insert = $this->config->sequence_start + $i;
break;
case 'string':
case 'binary':
$isPrimaryUuid = (
isset($fieldInfo['key']) && strtolower($fieldInfo['key']) === 'primary' &&
isset($fieldInfo['length']) && $fieldInfo['length'] == 36
);
if ($isPrimaryUuid) {
$insert = String::uuid();
} else {
$insert = "Lorem ipsum dolor sit amet";
if (!empty($fieldInfo['length'])) {
$insert = substr($insert, 0, (int)$fieldInfo['length'] - 2);
}
}
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;
}
$record[$field] = $insert;
}
if(is_callable($callback)) {
$record = array_merge($record, $callback($record, $world));
} else if(is_array($callback)) {
$record = array_merge($record, $callback);
public static function association($modelName, $recordCount=1, $callback = null) {
$instance = self::getInstance();
$factory = $instance->factory($modelName);
$definition = $instance->definition($recordCount, $callback);
$recordCount = $instance->recordCount($recordCount);
return $factory->attributes_for($recordCount, $definition);
}

/**
* Return defined traits.
* @return array registed trait definition
*/
public static function traits() {
return self::getInstance()->traits;
}

/**
* @param mixed $name
* @param mixed $define
*/
public static function define($name, $define) {
$instance = self::getInstance();
$parent = false;
$base = false;
$trait = false;
if(is_array($name)) {
$parent = array_key_exists('parent', $name)?$name['parent']:false;
$base = array_key_exists('class', $name)?$name['class']:false;
if(array_key_exists('trait', $name)) {
$name = $name['trait'];
$parent = $base = false;
$trait = true;
} else {
$name = $name[0];
}
$records[] = $record;
}
return $records;
if(empty($name)) {
throw new InvalidArgumentException("name is empty");
}
if($parent && !$instance->registry->is_registered($parent)) {
throw new InvalidArgumentException("parent `{$parent}` is not registered");
}
if($base && in_array(ClassRegistry::init($base, true),[false, null])) {
throw new InvalidArgumentException("class `{$base}` is not found");
}
$definition = new FabricateDefinition($define);
if($trait) {
$instance->traits[$name] = $definition;
return;
}
if(!$parent && !$base) {
$base = $name;
}
$definition->parent = $parent?FabricateFactory::create($instance->registry->find($parent)):false;
$definition->parent = $base?FabricateFactory::create(ClassRegistry::init($base)):$definition->parent;
$definition->parent->setConfig(self::getInstance()->config);

$instance->registry->register($name, $definition);
}

private function factory($name) {
$factory = FabricateFactory::create(self::getInstance()->registry->find($name));
$factory->setConfig(self::getInstance()->config);
return $factory;
}

private function recordCount($recordCount) {
if(is_callable($recordCount) || is_array($recordCount)) {
$recordCount = 1;
}
return $recordCount;
}

private function definition($recordCount, $callback) {
if(is_callable($recordCount) || is_array($recordCount)) {
$callback = $recordCount;
}
return new FabricateDefinition($callback);
}
}
1 change: 1 addition & 0 deletions Lib/FabricateConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
class FabricateConfig {
public $sequence_start = 1;
public $auto_validate = false;
public $filter_key = false;
}
27 changes: 27 additions & 0 deletions Lib/FabricateContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class FabricateContext {
* Sequence Hash map
*/
private $sequences = [];
/**
* Trait use array
*/
private $traits = [];
/**
* Fabricate config
*/
Expand Down Expand Up @@ -50,4 +54,27 @@ public function sequence($name, $start=null, $callback=null) {
$this->sequences[$name]->next();
return $ret;
}

/**
* Add apply trait in the scope.
* @param string|array $name use trait name(s)
*/
public function traits($name) {
if(is_array($name)) {
$this->traits = array_merge($this->traits, $name);
} else {
$this->traits[] = $name;
}
}

/**
* Flush trait stack in the scope
* @return array flushed trait stack
*/
public function flashTraits() {
$traits = $this->traits;
$this->traits = [];
return $traits;
}

}
59 changes: 59 additions & 0 deletions Lib/FabricateRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/**
* Fabricator Registry Class
*/
class FabricateRegistry {
private $name;
private $items;

/**
* Construct with registry name
* @param string $name registry name
*/
public function __construct($name) {
$this->name = $name;
$this->items = [];
}

/**
* Clear registerd entries
*/
public function clear() {
$this->items = [];
}

/**
* Find from registred or model by name
* @param string $name
* @return mixed registerd object
*/
public function find($name) {
if($this->is_registered($name)) {
return $this->items[$name];
}
$model = ClassRegistry::init($name, true);
if($model) {
return $model;
}
throw new InvalidArgumentException("{$name} not registered");
}

/**
* Regist to registries
* @param string $name
* @param FabricateDefinition $item
*/
public function register($name, $item) {
$this->items[$name] = $item;
}

/**
* Is registered?
* @param string $name
* @return boolean
*/
public function is_registered($name) {
return array_key_exists($name, $this->items);
}
}
Loading

0 comments on commit 1f36d00

Please sign in to comment.