<commit_before><?php defined('SYSPATH') OR die('No direct access allowed.');

/**
 * Jammaker api and maker class
 *
 * @package    Jamaker
 * @author     <NAME>
 * @license    http://www.opensource.org/licenses/isc-license.txt
 */
abstract class Kohana_Jamaker {

	/**
	 * All the defined jamaker factories
	 * @var array
	 */
	static protected $factories = array();

	/**
	 * Holds all the makers that have saved objects to the database. This is used to later clean them up.
	 * @var array
	 */
	static protected $created = array();

	static protected $autoloaded = FALSE;

	/**
	 * Define a Jamaker object
	 * @param  string $name       The name of the maker, must be unique
	 * @param  array  $params     If no attributes are defined - use this for attributes
	 * @param  array $attributes  
	 * @return Jamaker             
	 */
	static public function factory($name, array $params, $attributes = NULL)
	{
		Jamaker::autoload();

		if (isset(Jamaker::$factories[$name]))
			throw new Kohana_Exception('Jamaker jamaker_user already defined');

		return Jamaker::$factories[$name] = new Jamaker($name, $params, $attributes);
	}

	/**
	 * Automatically include files tests/test_data/jamaker.php and tests/test_data/jamaker/*.php
	 * @return NULL
	 */
	static public function autoload()
	{
		if ( ! Jamaker::$autoloaded)
		{
			$jamakers = Kohana::list_files('tests/test_data/jamaker');
			$jamakers = $jamakers + Kohana::find_file('tests/test_data', 'jamaker', NULL, TRUE);
			foreach ($jamakers as $jamaker_file) 
			{
				require_once $jamaker_file;
			}
			Jamaker::$autoloaded = TRUE;
		}
	}

	/**
	 * * Clear all definitions. Useful for testing
	 * @param  array $factories Specifically what factories to remove
	 * @return NULL
	 */
	static public function clear_factories(array $factories = NULL)
	{
		if ($factories !== NULL)
		{
			foreach ($factories as $factory) 
			{
				unset(Jamaker::$factories[$factory]);
			}
		}
		else
		{
			Jamaker::$factories = array();
		}
	}

	/**
	 * Clear all created objects in the database so far.
	 * @return NULL 
	 */
	static public function clear_created()
	{
		$models = array();
		foreach (Jamaker::$created as $maker) 
		{
			$models[] = Jelly::model_name(Jamaker::factories($maker)->item_class());
		}

		foreach (array_unique(array_filter($models)) as $model) 
		{
			Jelly::query($model)->delete();
		}

		Jamaker::$created = array();
	}

	/**
	 * Get the maker for a given name. Will raise an exception if maker not defined. If you pass a Jamaker object will return it.
	 * @param  mixed $name the name of the maker
	 * @throws Kohana_Exception If a maker with that name is not defined
	 * @return Jamaker       
	 */
	static public function factories($name = NULL)
	{
		Jamaker::autoload();

		if ($name !== NULL)
		{
			if (is_object($name))
			{
				if ( ! ($name instanceof Jamaker))
					throw new Kohana_Exception("Must be an instance of Jamaker but was :class", array(':class' => get_class($name)));

				return $name;
			}

			if ( ! isset(Jamaker::$factories[$name]))
				throw new Kohana_Exception('A Jelly Maker with the name ":name" is not defined', array(':name' => $name));
				
			return Jamaker::$factories[$name];
		}

		return Jamaker::$factories;
	}

	/**
	 * Get the attributes for a given definition, used to build / create an item. Useful for passing to controllers.
	 * @param  string $name      The name of the definition to use
	 * @param  array $overrides  Use this to apply last-minute attributes to the generated item. Will overwrite any previous attributes with the same names
	 * @return array             An array of attributes for the item.
	 */
	static public function attributes_for($name, array $overrides = NULL, $strategy = 'build')
	{
		return Jamaker::factories($name)->attributes($overrides, $strategy);
	}

	/**
	 * Generate an object for a jamaker definition. 
	 * Triggers events, if strategy is 'create' - saves the object to the database
	 * 
	 * @param  string $strategy  'build' or 'create'
	 * @param  string $name      The name of the definition to use
	 * @param  array $overrides  Use this to apply last-minute attributes to the generated item. Will overwrite any previos attributes with the same names
	 * @return mixed             The resulting object, Jell_Model
	 */
	static public function generate($strategy, $name, array $overrides = NULL)
	{
		$maker = Jamaker::factories($name);
		$class = $maker->item_class();
		$item = new $class();

		foreach ($maker->attributes($overrides, $strategy) as $attribute_name => $value) 
		{
			$item->$attribute_name = $value;
		}
		
		$maker->events()->trigger('build.after', $item, array($maker));
		if ($strategy == 'create')
		{
			Jamaker::$created[] = $name;

			$maker->events()->trigger('create.before', $item, array($maker));

			$item->save();

			$maker->events()->trigger('create.after', $item, array($maker));
		}
		return $item;
	}

	/**
	 * Generate a list of items, based on a template.
	 * 
	 * @param  string $strategy  'build' or 'create'
	 * @param  string $name      The name of the definition to use
	 * @param  integer $count    How many objects to generate based on this definition
	 * @param  array  $overrides use this to apply last-minute attributes to the generated item. Will overwrite any previous attributes with the same names
	 * @return array             an array of item objects
	 */
	static public function generate_list($strategy, $name, $count, array $overrides = NULL)
	{
		$list = array();
		foreach (range(1, $count) as $i) 
		{
			$list[] = Jamaker::generate($strategy, $name, $overrides);
		}
		return $list;
	}

	/**
	 * Shorthand for Jamaker::generate('build', $name, $overrides);
	 * @param  string $name
	 * @param  array  $overrides 
	 * @return mixed<commit_msg>add builder strategy<commit_after><?php defined('SYSPATH') OR die('No direct access allowed.');

/**
 * Jammaker api and maker class
 *
 * @package    Jamaker
 * @author     <NAME>
 * @license    http://www.opensource.org/licenses/isc-license.txt
 */
abstract class Kohana_Jamaker {

	/**
	 * All the defined jamaker factories
	 * @var array
	 */
	static protected $factories = array();

	/**
	 * Holds all the makers that have saved objects to the database. This is used to later clean them up.
	 * @var array
	 */
	static protected $created = array();

	static protected $autoloaded = FALSE;

	/**
	 * Define a Jamaker object
	 * @param  string $name       The name of the maker, must be unique
	 * @param  array  $params     If no attributes are defined - use this for attributes
	 * @param  array $attributes  
	 * @return Jamaker             
	 */
	static public function factory($name, array $params, $attributes = NULL)
	{
		Jamaker::autoload();

		if (isset(Jamaker::$factories[$name]))
			throw new Kohana_Exception('Jamaker jamaker_user already defined');

		return Jamaker::$factories[$name] = new Jamaker($name, $params, $attributes);
	}

	/**
	 * Automatically include files tests/test_data/jamaker.php and tests/test_data/jamaker/*.php
	 * @return NULL
	 */
	static public function autoload()
	{
		if ( ! Jamaker::$autoloaded)
		{
			$jamakers = Kohana::list_files('tests/test_data/jamaker');
			$jamakers = $jamakers + Kohana::find_file('tests/test_data', 'jamaker', NULL, TRUE);
			foreach ($jamakers as $jamaker_file) 
			{
				require_once $jamaker_file;
			}
			Jamaker::$autoloaded = TRUE;
		}
	}

	/**
	 * * Clear all definitions. Useful for testing
	 * @param  array $factories Specifically what factories to remove
	 * @return NULL
	 */
	static public function clear_factories(array $factories = NULL)
	{
		if ($factories !== NULL)
		{
			foreach ($factories as $factory) 
			{
				unset(Jamaker::$factories[$factory]);
			}
		}
		else
		{
			Jamaker::$factories = array();
		}
	}

	/**
	 * Clear all created objects in the database so far.
	 * @return NULL 
	 */
	static public function clear_created()
	{
		$models = array();
		foreach (Jamaker::$created as $maker) 
		{
			$models[] = Jelly::model_name(Jamaker::factories($maker)->item_class());
		}

		foreach (array_unique(array_filter($models)) as $model) 
		{
			Jelly::query($model)->delete();
		}

		Jamaker::$created = array();
	}

	/**
	 * Get the maker for a given name. Will raise an exception if maker not defined. If you pass a Jamaker object will return it.
	 * @param  mixed $name the name of the maker
	 * @throws Kohana_Exception If a maker with that name is not defined
	 * @return Jamaker       
	 */
	static public function factories($name = NULL)
	{
		Jamaker::autoload();

		if ($name !== NULL)
		{
			if (is_object($name))
			{
				if ( ! ($name instanceof Jamaker))
					throw new Kohana_Exception("Must be an instance of Jamaker but was :class", array(':class' => get_class($name)));

				return $name;
			}

			if ( ! isset(Jamaker::$factories[$name]))
				throw new Kohana_Exception('A Jelly Maker with the name ":name" is not defined', array(':name' => $name));
				
			return Jamaker::$factories[$name];
		}

		return Jamaker::$factories;
	}

	/**
	 * Get the attributes for a given definition, used to build / create an item. Useful for passing to controllers.
	 * @param  string $name      The name of the definition to use
	 * @param  array $overrides  Use this to apply last-minute attributes to the generated item. Will overwrite any previous attributes with the same names
	 * @return array             An array of attributes for the item.
	 */
	static public function attributes_for($name, array $overrides = NULL, $strategy = 'build')
	{
		return Jamaker::factories($name)->attributes($overrides, $strategy);
	}

	/**
	 * Generate an object for a jamaker definition. 
	 * Triggers events, if strategy is 'create' - saves the object to the database
	 * 
	 * @param  string $strategy  'build' or 'create'
	 * @param  string $name      The name of the definition to use
	 * @param  array $overrides  Use this to apply last-minute attributes to the generated item. Will overwrite any previos attributes with the same names
	 * @return mixed             The resulting object, Jell_Model
	 */
	static public function generate($strategy, $name, array $overrides = NULL)
	{
		$maker = Jamaker::factories($name);
		$class = $maker->item_class();
		$item = new $class();

		foreach ($maker->attributes($overrides, $strategy) as $attribute_name => $value) 
		{
			$item->$attribute_name = $value;
		}
		
		$maker->events()->trigger('build.after', $item, array($maker, $strategy));
		if ($strategy == 'create')
		{
			Jamaker::$created[] = $name;

			$maker->events()->trigger('create.before', $item, array($maker, $strategy));

			$item->save();

			$maker->events()->trigger('create.after', $item, array($maker, $strategy));
		}
		return $item;
	}

	/**
	 * Generate a list of items, based on a template.
	 * 
	 * @param  string $strategy  'build' or 'create'
	 * @param  string $name      The name of the definition to use
	 * @param  integer $count    How many objects to generate based on this definition
	 * @param  array  $overrides use this to apply last-minute attributes to the generated item. Will overwrite any previous attributes with the same names
	 * @return array             an array of item objects
	 */
	static public function generate_list($strategy, $name, $count, array $overrides = NULL)
	{
		$list = array();
		foreach (range(1, $count) as $i) 
		{
			$list[] = Jamaker::generate($strategy, $name, $overrides);
		}
		return $list;
	}

	/**
	 * Shorthand for Jamaker::generate('build', $name, $overrides);
	 * @param  string $name
	 * @param  array  $overrides 
	 * @return mixed
{'fraction_non_alphanumeric': 0.1286529482967318, 'fraction_numerical': 0.00017292062943109114, 'mean_word_length': 3.431800766283525, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2853097', 'n_tokens_mistral': 3893, 'n_tokens_neox': 3464, 'n_words': 1162}