<?php
/**
 * @brief		Rules extension: {class}
 * @package		Rules for IPS Social Suite
 * @since		{date}
 * @version		SVN_VERSION_NUMBER
 */

namespace IPS\{app}\extensions\rules\Definitions;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
	header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
	exit;
}

/**
 * @brief	Rules definitions extension: {class}
 */
class _{class}
{

	/**
	 * @brief	The default option group title to list events, conditions, and actions from this class
	 */
	public $defaultGroup = '{class}';

	/**
	 * Triggerable Events
	 *
	 * Define the events that can be triggered by your application
	 *
	 * Trigger events in your application code like this:
	 * if ( \IPS\Application::appIsEnabled( 'rules' ) )
	 * {
	 * 	\IPS\rules\Event::load( '{app}', '{class}', 'event_key' )->trigger( $arg1, $arg2, etc... );
	 * }
	 *
	 * @return 	array		Array of event definitions
	 */
	public function events()
	{
		$events = array
		(
			/**
			 * Event Key
			 *
			 * Each of your events is triggered using an event key.
			 * Event keys only need to be unique to this class.
			 *
			 * The name of the event should be stored as a language string
			 * in your lang.php with a key in the following format:
			 *
			 * '{app}_{class}_event_{event_key}' => 'Event Name'
			 */
			'event_key' => array
			( 
				/**
				 * Option Group
				 *
				 * Customize the option group heading that this event is listed under in the ACP
				 *
				 * If this setting is omitted, then this option will be listed under the title of the 
				 * $defaultGroup property of this class definition.
				 */
				'group' => '{class}',
				
				/**
				 * Event Arguments
				 *
				 * Define the arguments that are sent to your event trigger
				 */
				'arguments' => array
				( 
					/**
					 * Argument/Variable Names
					 *
					 * Arguments need to be defined in the same order that they are provided
					 * by the event trigger.
					 *
					 * The names you define will be available as PHP variables
					 * when using PHP code in the rules configurations.
					 * eg: $variable1
					 *
					 * Note: since they are used as variable names, you may only
					 * use alphanumerics and underscores in the name.
					 *
					 * The description of the variable should be stored as a language string
					 * in your lang.php with a key in the following format:
					 *
					 * '{app}_{class}_event_{event_key}_{variable1}' => 'Description of the event variable'					 
					 */
					'variable1' => array
					(
						/**
						 * Argument Type
						 *
						 * Define the type of this argument as it will be passed to the event
						 * trigger. This allows actions to determine whether this argument
						 * is compatible with the action callback.
						 *
						 * string: this argument will always be a string ( or possibly null )
						 * int: this argument will always be an integer ( or possibly null )
						 * bool: this argument will always be boolean ( or possibly null )
						 * float: this argument will always be a floating point number ( or possibly null )
						 * array: this argument will always be an array ( or possibly null )
						 * object: this argument will always be an object ( or possibly null )
						 * mixed: this argument will contain mixed values ( or possibly null )
						 */
						'argtype' 	=> 'int',
						
						/**
						 * Class Association
						 *
						 * This is used to help rules determine whether this argument can be used 
						 * with conditions/actions that require objects. For example, if your argument
						 * is a member object, you should define it's class as \IPS\Member. This allows 
						 * rules to make it available as an event argument when the operation
						 * specifically needs a member object.
						 *
						 * If your argument will be an object, use the actual class of your object here.
						 * Otherwise, simply omit this setting or set it to NULL.
						 */
						'class'		=> '\IPS\Member',
												
						/**
						 * NULLABLE
						 *
						 * Set to TRUE if this argument may be NULL when the event is triggered.
						 * This gives the user the opportunity to set a default value for it when
						 * they create their rule.
						 *
						 * If the argument will always have a value that is not null, you 
						 * can omit this setting or leave it set it to FALSE
						 */
						'nullable'	=> FALSE,
					),
				),
			),
		);
		
		return array(); // $events;
	}
	
	/**
	 * Conditional Operations
	 *
	 * You can define your own conditional operations which can be
	 * added to rules as conditions.
	 *
	 * @return 	array		Array of conditions definitions
	 */
	public function conditions()
	{
		$conditions = array
		(
			/**
			 * Condition Key
			 *
			 * Any condition you provide is invoked using a condition key.
			 * Condition keys only need to be unique to this class.
			 *
			 * The name of the condition should be stored as a language string
			 * in your lang.php with a key in the following format:
			 *
			 * '{app}_{class}_conditions_{condition_key}' => 'Condition Name'
			 */
			'condition_key' => array
			(
				/**
				 * Option Group
				 *
				 * Customize the option group heading that this condition is listed under in the ACP
				 *
				 * If this setting is omitted, then this option will be listed under the title of the 
				 * $default_group property of this class definition.
				 */
				'group' => '{class}',
				
				/**
				 * Condition Callback
				 *
				 * The condition callback is the function that will be executed
				 * when your condition is invoked from rules.
				 */
				'callback' 	=> array( $this, 'operationCallback' ),
				
				/**
				 * Condition Configuration
				 * 
				 * You can create custom configuration options for your condition. This allows the user to
				 * change settings/options for how the condition will be evaluated.
				 */
				'configuration' => array
				(
					/**
					 * Form Builder
					 *
					 * Create custom form fields for your condition. The values will be saved
					 * automatically, and passed as an additional argument to your condition callback
					 * when it is invoked.
					 *
					 * @param	\IPS\Helpers\Form 	$form		The condition editing form 
					 * @param	array			$values		An array of any previously saved form values
					 * @param	\IPS\rules\Condition	$condition		The condition object
					 * @return	void
					 */
					'form' => function( $form, $values, $condition )
					{
						
					},
					
					/**
					 * Process Form Values
					 *
					 * Form values are saved automatically, however, you may need to modify them
					 * before they are saved (such as turning an array of member objects into an
					 * array of member id's).
					 *
					 * @param	array			$values		The values from the form
					 * @param	\IPS\rules\Condition	$condition	The condition object
					 * @return 	void
					 */
					'saveValues'	=> function( &$values, $condition ) 
					{
					
					},
				),
				
				/**
				 * Condition Arguments
				 *
				 * If your callback function for your condition has any arguments, 
				 * you need to define them so rules know how to invoke your callback.
				 */
				'arguments'	=> array
				(
					/**
					 * Argument Names
					 *
					 * Arguments need to be defined in the order that they will be
					 * passed to your callback function.
					 *
					 * The description of the argument should be stored as a language string
					 * in your lang.php with a key in the following format:
					 *
					 * '{app}_{class}_conditions_{condition_key}_{arg1}' => 'Description of argument'					 
					 */
					'arg1' => array
					(
						/**
						 * When rules are triggered by events, the event will usually have
						 * variables associated with it that may be usable by your condition.
						 *
						 * You can define which types of variables that are compatible with
						 * your argument, and also provide a converter function that will
						 * translate the passed variable into the correct state for your
						 * callback.
						 */
						'argtypes' => array
						(
							/**
							 * The following argtypes are valid:
							 *
							 * string: allows rules to pass you a string
							 * int: allows rules to pass you an integer
							 * bool: allows rules to pass you a boolean value
							 * float: allows rules to pass you a floating point value
							 * array: allows rules to pass you an array
							 * object: allows rules to pass you an object
							 * mixed: allows rules to pass you mixed variables
							 */
							'int' => array
							(
								/**
								 * Description
								 *
								 * Describe what you expect for this argtype. This description
								 * helps users who create rules using php code to know what
								 * to supply your converter/callback function.
								 */
								'description' => 'Member ID',
								
								/**
								 * Converter Function
								 *
								 * If you define a converter function, you can process an argument
								 * from the event before it gets sent to your condition callback.
								 *
								 * @param	mixed	$val	The value being sent as an argument to your condition callback
								 * @param	array	$values	The saved configuration values from the condition
								 */
								'converter' => function( $val, $values ) 
								{
									return \IPS\Member::load( $val );
								},
								
								/**
								 * When events are defined, the arguments they receive when triggered
								 * can be associated with specific classes.
								 *
								 * If you define classes here for an argtype, only variables that have
								 * been associated with these class(es) will be able to be
								 * passed to your converter or condition callback.
								 */
								'class' => array( '\IPS\Member' ),
																
							),						
						),
						
						/**
						 * Define whether this argument is required by your condition callback
						 */
						'required'	=> TRUE,
						
						/**
						 * Configuration
						 *
						 * You should create form elements on the condition editing form for users to 
						 * manually define the argument which is passed to your condition callback.
						 */
						'configuration' => array
						(
							/**
							 * Form Builder
							 *
							 * Rules will automatically hide your form elements if manual configuration is not selected
							 * by the user, but in order to do that, you must return an array of the HTML id's of the
							 * elements that you've added to the form ( the last argument in the form element construct )
							 *
							 * @param	\IPS\Helpers\Form 	$form		The condition editing form 
							 * @param	array			$values		An array of any previously saved form values
							 * @param	\IPS\rules\Condition	$condition	The condition object
							 * @return	array			An array of the form element id's that you created
							 */
							'form'		=> function( $form, $values, $condition ) 
							{
								$form->add( new \IPS\Helpers\Form\Text( 'custom_arg_value', $values[ 'custom_arg_value' ], FALSE, array(), NULL, NULL, NULL, 'custom_html_id' ) );
								return array( 'custom_html_id' );
							},
							
							/**
							 * Process Form Values
							 *
							 * Form values are saved automatically, however, you may need to modify them
							 * before they are saved (such as turning an array of member objects into an
							 * array of member id's).
							 *
							 * @param	array			$values		The values from the form
							 * @param	\IPS\rules\Condition	$condition	The condition object
							 * @return 	void
							 */
							'saveValues'	=> function( &$values, $condition ) 
							{
							
							},
							
							/**
							 * Get Callback Argument
							 *
							 * When your condition is invoked using a manually defined argument (via the form builder),
							 * the saved values are first passed to this function so that you can take any necessary
							 * steps to create the argument for your callback function.
							 * 
							 * @param	array			$values		The saved form values
							 * @param	\IPS\rules\Condition	$condition	The condition object
							 * @return	mixed			The value to be sent to your condition callback
							 */
							'getArg'	=> function( $values, $condition )
							{
								return $values[ 'custom_arg_value' ];
							},
						),
						
						/**
						 * Default Configuration Method
						 *
						 * The default configuration method for this argument will be to choose from event data. You
						 * can override that if the preferred default configuration method should be different.
						 *
						 * Possible values: 'manual', 'event', 'phpcode'
						 */
						'default' => 'manual',
					),	
				),				
			),
		);
		
		return array(); // $conditions;
	}

	/**
	 * Triggerable Actions
	 *
	 * @return 	array		Array of action definitions
	 */
	public function actions()
	{
		$actions = array
		(
			/**
			 * Action Key
			 *
			 * Each of your actions is invoked using an action key.
			 * Actions keys only need to be unique to this class.
			 *
			 * The name of the action should be stored as a language string
			 * in your lang.php with a key in the following format:
			 *
			 * '{app}_{class}_actions_{action_key}' => 'Action Name'
			 */
			'action_key' => array
			(
				/**
				 * Option Group
				 *
				 * Customize the option group heading that this action is listed under in the ACP
				 *
				 * If this setting is omitted, then this option will be listed under the title of the 
				 * $default_group property of this class definition.
				 */
				'group' => '{class}',
				
				/**
				 * Action Callback
				 *
				 * The action callback is the function that will be executed
				 * when your action is invoked from rules.
				 */
				'callback' 	=> array( $this, 'operationCallback' ),
				
				/**
				 * Action Configuration
				 * 
				 * You can create custom configuration options for your action.
				 */
				'configuration' => array
				(
					/**
					 * Form Builder
					 *
					 * Create custom form fields for your action. The values will be saved
					 * automatically, and passed as an additional argument to your action callback
					 * when it is invoked.
					 *
					 * @param	\IPS\Helpers\Form 	$form		The action editing form 
					 * @param	array			$values		An array of any previously saved form values
					 * @param	\IPS\rules\Action	$action		The action object
					 * @return	void
					 */
					'form' => function( $form, $values, $action )
					{
						
					},
					
					/**
					 * Process Form Values
					 *
					 * Form values are saved automatically, however, you may need to modify them
					 * before they are saved (such as turning an array of member objects into an
					 * array of member id's).
					 *
					 * @param	array			$values		The values from the form
					 * @param	\IPS\rules\Action	$action		The action object
					 * @return 	void
					 */
					'saveValues'	=> function( &$values, $action ) 
					{
					
					},
				),
				
				/**
				 * Action Arguments
				 *
				 * If your callback function for your action has any arguments, 
				 * you need to define them so rules know how to invoke your callback.
				 */
				'arguments'	=> array
				(
					/**
					 * Argument Names
					 *
					 * Arguments need to be defined in the order that they will be
					 * passed to your callback function.
					 *
					 * The description of the argument should be stored as a language string
					 * in your lang.php with a key in the following format:
					 *
					 * '{app}_{class}_actions_{action_key}_{arg1}' => 'Description of argument'					 
					 */
					'arg1' => array
					(
						/**
						 * When rules are triggered by events, the event will usually have
						 * variables associated with it that may be usable by your action.
						 *
						 * You can define which types of variables that are compatible with
						 * your argument, and also provide a converter function that will
						 * translate the passed variable into the correct state for your
						 * callback.
						 */
						'argtypes' => array
						(
							/**
							 * The following argtypes are valid:
							 *
							 * string: allows rules to pass you a string
							 * int: allows rules to pass you an integer
							 * bool: allows rules to pass you a boolean value
							 * float: allows rules to pass you a floating point value
							 * array: allows rules to pass you an array
							 * object: allows rules to pass you an object
							 * mixed: allows rules to pass you mixed variables
							 */
							'int' => array
							(
								/**
								 * Description
								 *
								 * Describe what you expect for this argtype. This description
								 * helps users who create rules using php code to know what
								 * to supply your converter/callback function.
								 */
								'description' => 'Member ID',
								
								/**
								 * Converter Function
								 *
								 * If you define a converter function, you can process an argument
								 * from the event before it gets sent to your action callback.
								 *
								 * @param	mixed	$val	The value being sent as an argument to your action callback
								 * @param	array	$values	The saved configuration values from the action
								 */
								'converter' => function( $val, $values ) 
								{
									return \IPS\Member::load( $val );
								},
								
								/**
								 * When events are defined, the arguments they receive when triggered
								 * can be associated with specific classes.
								 *
								 * If you define classes here for an argtype, only variables that have
								 * been associated with these class(es) will be able to be
								 * passed to your converter or action callback.
								 */
								'class' => array( '\IPS\Member' ),
																
							),						
						),
						
						/**
						 * Define whether this argument is required by your action callback
						 */
						'required'	=> TRUE,
						
						/**
						 * Configuration
						 *
						 * You should create form elements on the action editing form for users to 
						 * manually define the argument which is passed to your action callback.
						 */
						'configuration' => array
						(
							/**
							 * Form Builder
							 *
							 * Rules will automatically hide your form elements if manual configuration is not selected
							 * by the user, but in order to do that, you must return an array of the HTML id's of the
							 * elements that you've added to the form ( the last argument in the form element construct )
							 *
							 * @param	\IPS\Helpers\Form 	$form		The action editing form 
							 * @param	array			$values		An array of any previously saved form values
							 * @param	\IPS\rules\Action	$action		The action object
							 * @return	array			An array of the form element id's that you created
							 */
							'form'		=> function( $form, $values, $action ) 
							{
								$form->add( new \IPS\Helpers\Form\Text( 'custom_arg_value', $values[ 'custom_arg_value' ], FALSE, array(), NULL, NULL, NULL, 'custom_arg_value' ) );
								return array( 'custom_arg_value' );
							},
							
							/**
							 * Process Form Values
							 *
							 * Form values are saved automatically, however, you may need to modify them
							 * before they are saved (such as turning an array of member objects into an
							 * array of member id's).
							 *
							 * @param	array			$values		The values from the form
							 * @param	\IPS\rules\Action	$action		The action object
							 * @return 	void
							 */
							'saveValues'	=> function( &$values, $action ) 
							{
							
							},
							
							/**
							 * Get Callback Argument
							 *
							 * When your action is invoked using a manually defined argument (via the form builder),
							 * the saved values are first passed to this function so that you can take any necessary
							 * steps to create the argument for your callback function.
							 * 
							 * @param	array			$values		The saved form values
							 * @param	\IPS\rules\Action	$action		The action object
							 * @return	mixed			The value to be sent to your action callback
							 */
							'getArg'	=> function( $values, $action )
							{
								return $values[ 'custom_arg_value' ];
							},
						),
						
						/**
						 * Default Configuration Method
						 *
						 * The default configuration method for this argument will be to choose from event data. You
						 * can override that if the preferred default configuration method should be different.
						 *
						 * Possible values: 'manual', 'event', 'phpcode'
						 */
						'default' => 'manual',
					),
				),
			),
		);
		
		return array(); // $actions;
	}
	
	/**
	 * Example Operation Callback
	 *
	 * Your operation callback will recieve all of the arguments defined in your
	 * action/condition definition. If an argument is not required, and not provided 
	 * by the user, then it will be NULL.
	 *
	 * Your operation callback will also recieve three additional arguments at the end of
	 * your regularly defined arguments.
	 *
	 * @extraArg1	array				$values		An array of the existing saved values from the configuration form
	 * @extraArg2	array				$arg_map	A keyed array of the arguments from the event
	 * @extraArg3	object	\IPS\rules\Action	$operation	The operation object (Action or Condition) which is invoking the callback
	 *			\IPS\rules\Condition
	 *
	 * @return	mixed			If this is a condition callback, you should return either TRUE or FALSE depending on if the condition has passed.
	 * 					If it is an action callback, you should return a short message to describe the result of the action for debug purposes.
	 *
	 * Note: Any value that you return from an operation callback is logged to the debug console when the rule is in debug mode. This way
	 * it is possible to see what is happening with each operation as it is being evaluated.
	 */
	public function operationCallback( $arg1, $values, $arg_map, $operation )
	{
		return 'action taken';
	}
	
}