PageRenderTime 41ms CodeModel.GetById 15ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/inc/patForms/Element/Group.php

https://github.com/chregu/fluxcms
PHP | 657 lines | 362 code | 52 blank | 243 comment | 44 complexity | 847279f30c57a889c963047f9086dad3 MD5 | raw file
  1<?php
  2/**
  3 * Group element that can be used as a container for elements.
  4 * 
  5 * $Id$
  6 *
  7 * @package		patForms
  8 * @subpackage	patForms_Element
  9 */
 10 
 11/**
 12 * Group element that can be used as a container for elements.
 13 * 
 14 * $Id$
 15 *
 16 * @access		public
 17 * @package		patForms
 18 * @subpackage	patForms_Element
 19 * @author		Stephan Schmidt <schst@php-tools.net>
 20 * @version		1.0
 21 * @license		LGPL
 22 * @todo		finish element
 23 */
 24class patForms_Element_Group extends patForms_Element
 25{
 26   /**
 27	* Stores the name of the element - this is used mainly by the patForms
 28	* error management and should be set in every element class.
 29	* @access	public
 30	*/
 31	var $elementName	=	'Group';
 32
 33   /**
 34	* The radio element uses a renderer to serialize its content, so we set the flag
 35	* to true here
 36	*
 37	* @access	private
 38	* @var		array
 39	*/
 40	var $usesRenderer	=	true;
 41
 42   /**
 43	* set here which attributes you want to include in the element if you want to use
 44	* the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
 45	* convert the values from your element definition into element attributes.
 46	*
 47	* @access	protected
 48	* @see		patForms_Element::convertDefinition2Attribute()
 49	*/
 50	var	$attributeDefinition	=	array(	
 51			
 52		'id' => array(
 53			'required'		=>	false,
 54			'format'		=>	'string',
 55			'outputFormats'	=>	array( 'html' ),
 56		),
 57		'name' => array(
 58			'required'		=>	true,
 59			'format'		=>	'string',
 60			'outputFormats'	=>	array( 'html' ),
 61			'modifiers'		=>	array( 'insertSpecials' => array() ),
 62		),
 63		'title' => array(
 64			'required'		=>	false,
 65			'format'		=>	'string',
 66			'outputFormats'	=>	array( 'html' ),
 67			'modifiers'		=>	array( 'insertSpecials' => array() ),
 68		),
 69		'description' => array(
 70			'required'		=>	false,
 71			'format'		=>	'string',
 72			'outputFormats'	=>	array(),
 73			'modifiers'		=>	array( 'insertSpecials' => array() ),
 74		),
 75		'label' => array(
 76			'required'		=>	false,
 77			'format'		=>	'string',
 78			'outputFormats'	=>	array(),
 79		),
 80		'display' => array(
 81			'required'		=>	false,
 82			'format'		=>	'string',
 83			'default'		=>	'yes',
 84			'outputFormats'	=>	array(),
 85		),
 86		'edit' => array(
 87			'required'		=>	false,
 88			'format'		=>	'string',
 89			'default'		=>	'yes',
 90			'outputFormats'	=>	array(),
 91		),
 92		'style' => array(
 93			'required'		=>	false,
 94			'outputFormats'	=>	array( 'html' ),
 95			'format'		=>	'string',
 96		),
 97		'class' => array(
 98			'required'		=>	false,
 99			'outputFormats'	=>	array( 'html' ),
100			'format'		=>	'string',
101		),
102		'position' => array(
103			'required'		=>	false,
104			'format'		=>	'int',
105			'outputFormats'	=>	array(),
106		),
107		'disabled' => array(
108		 	'required'		=>	false,
109			'format'		=>	'string',
110			'default'		=>	'no',
111			'outputFormats'	=>	array( 'html' )
112		)
113	);
114
115   /**
116	* stores the element objects of this form.
117	* @access	protected
118	* @see		addElement()
119	*/
120	var $elements	=	array();
121	
122   /**
123	* stores a renderer
124	* @access	protected
125	* @see		setRenderer()
126	*/
127	var $renderer		=	null;
128
129    /**
130     *	define error codes an messages for each form element
131     *
132     *  @access private
133     *  @var	array	$validatorErrorCodes
134     */
135	var	$validatorErrorCodes  =   array(
136										"C"	=>	array(
137														),
138										"de" =>	array(
139													)
140										);
141		
142   /**
143	* stores the current element count for this form, used to generate the ids for each element
144	* @access	protected
145	* @see		getElementId()
146	*/
147	var $elementCounter	=	0;
148
149   /**
150	* sets the locale (language) to use for the validation error messages of the form.
151	*
152	* @access	public
153	* @param	string	$lang	
154	* @return	bool	$result	True on success
155	* @see		$locale
156	*/
157    function setLocale( $lang )
158    {
159		$this->locale = $lang;
160		$cnt = count($this->elements);
161    	for ($i = 0; $i < $cnt; $i++) {
162    		$this->elements[$i]->setLocale($lang);
163    	}
164        return  true;
165    }
166
167   /**
168	* sets the format of the element - this defines which method will be called in your
169	* element class, along with the {@link mode} property.
170	*
171	* @access	public
172	* @param	string	$format	The name of the format you have implemented in your element(s). Default is 'html'
173	* @see		setFormat()
174	* @see		format
175	* @see		serialize()
176	*/
177	function setFormat( $format )
178	{
179		$this->format = strtolower( $format );
180		$cnt = count($this->elements);
181    	for ($i = 0; $i < $cnt; $i++) {
182    		$this->elements[$i]->setFormat($format);
183    	}
184	}
185
186   /**
187	* sets the mode of the element that defines which methods will be called in your
188	* element class, along with the {@link format} property.
189	*
190	* @access	public
191	* @param	string	$mode	The mode to set the element to: default|readonly or any other mode you have implemented in your element class(es). Default is 'default'.
192	* @see		setFormat()
193	* @see		mode
194	* @see		serialize()
195	*/
196	function setMode( $mode )
197	{
198		$this->mode	= strtolower( $mode );
199		$cnt = count($this->elements);
200    	for ($i = 0; $i < $cnt; $i++) {
201    		$this->elements[$i]->setMode($mode);
202    	}
203	}
204
205   /**
206    * sets a renderer object that will be used to render
207	* the form.
208	*
209	* @access	public
210	* @param	object	renderer object
211	* @see		renderForm()
212	*/
213	function setRenderer( &$renderer )
214	{
215		if( !is_object( $renderer ) ) {
216			return patErrorManager::raiseError( 
217				PATFORMS_ERROR_INVALID_RENDERER, 
218				"No patForms_Renderer object supplied" 
219			);
220		}
221
222		$this->renderer	=	&$renderer;
223	}
224	
225   /**
226	* adds an observer to the element
227	*
228	* @access	public
229	* @param	object patForms_Observer	observer
230	* @return	boolean						currently always true
231	*/
232	function attachObserver( &$observer )
233	{
234		$this->observers[] = &$observer;
235		$cnt = count($this->elements);
236    	for ($i = 0; $i < $cnt; $i++) {
237    		$this->elements[$i]->attachObserver($observer);
238    	}
239		return true;
240	}
241
242   /**
243	* adds an element to the form - has to be a patForms_Element object. Use the {@link createElement()}
244	* method to create a new element object. Also takes care of passing on the form's configuration
245	* including the mode, format and submitted flags to the element.
246	*
247	* @access	public
248	* @param	object	&$element	The patForms_Element object to add to this form.
249	* @return	bool	$success	True if everythng went well, false otherwise.
250	* @see		patForms_Element
251	* @see		createElement()
252	*/
253	function addElement( &$element )
254	{
255		if( !is_object( $element ) ) {
256			return patErrorManager::raiseError( 
257				PATFORMS_ERROR_ELEMENT_IS_NO_OBJECT, 
258				"Given element is not an object" 
259			);
260		}
261		
262		if( patErrorManager::isError( $element ) ) {
263			return patErrorManager::raiseError( 
264				PATFORMS_ERROR_UNEXPECTED_ERROR, 
265				"Unexpected Error Object!" 
266			);
267		}
268
269		if (!$element->getId()) {
270			$element->setId( $this->getElementId() );
271		}
272		$element->setMode( $this->getMode() );
273		$element->setFormat( $this->getFormat() );
274		$element->setSubmitted( $this->getSubmitted() );
275		
276		array_push( $this->elements, &$element );
277		
278		return true;
279	}
280
281   /**
282	* retreives a new element id, used to give each added element a unique id for this
283	* form (id can be overwritten by setting the id attribute specifically).
284	*
285	* @access	private
286	* @return	int	$elementId	The new element id.
287	*/
288	function getElementId()
289	{
290		$this->elementCounter++;
291	
292		return "pfo" . $this->getName() . $this->elementCounter;
293	}
294
295   /**
296	* element creation method for the 'HTML' format in the 'default' form mode.
297	*
298	* @access	public
299	* @param	mixed	value of the element
300	* @return	mixed	$element	The element, or false if failed.
301	*/
302	function serializeHtmlDefault( $value )
303	{
304		// manage display attribute. If set, only the needed hidden
305		// elements for the subelements will be created. 
306		if( $this->attributes['display'] == 'no' )
307		{
308			return $this->createDisplaylessTag( $value );
309		}
310
311		if( $this->renderer === null )
312		{
313			return patErrorManager::raiseError( 
314				PATFORMS_ERROR_NO_RENDERER_SET, 
315				"No renderer has been set." 
316			);
317		}
318		
319		// edit attribute is inherited by all subelements
320		if( $this->attributes['edit'] == 'no' )
321		{
322			$cnt = count( $this->elements );
323
324			for( $i=0; $i < $cnt; $i++ )
325			{
326				$this->elements[$i]->setAttribute( 'edit', 'no' );
327			}
328		}
329		
330		return $this->renderer->render( $this );
331	}
332	
333   /**
334	* rewritten for the speciality of the group - creates a collection
335	* of hidden elements for all subelements of the group.
336	*
337	* @access	public
338	* @param	mixed	value of the element
339	* @return	string	$value	The element's value
340	*/
341	function createDisplaylessTag( $value )
342	{
343		$this->getAttributesFor( $this->getFormat() );
344		
345		$tag = '';
346		$cnt = count( $this->elements );
347		
348		for( $i=0; $i < $cnt; $i++ )
349		{
350			$this->elements[$i]->setAttribute( 'display', 'no' );
351			$tag .= $this->elements[$i]->serialize();
352		}
353		
354		return $tag;
355	}
356	
357   /**
358	* element creation method for the 'HTML' format in the 'readonly' form mode.
359	* Very simple; just returns the stored element value.
360	*
361	* @access	public
362	* @param	mixed	value of the element
363	* @return	string	$value	The element's value
364	*/
365	function serializeHtmlReadonly( $value )
366	{
367		// manage display attribute. 
368		if( $this->attributes['display'] == 'no' )
369		{
370			return $this->createDisplaylessTag( $value );
371		}
372
373		return $this->renderer->render( $this );
374	}
375
376   /**
377	* validates the element.
378	*
379	* @access	public
380	* @param	mixed	value of the element
381	* @return	bool	$isValid	True if element could be validated, false otherwise.
382	*/
383	function validateElement( $value )
384	{
385		$valid	=	true;
386	
387		$cnt	=	count( $this->elements );
388		for( $i = 0; $i < $cnt; ++$i ) {
389			if( !$this->elements[$i]->validate() ) {
390				$valid = false;
391			}
392		}
393		if( $valid == false ) {
394			return	false;		
395		}
396
397		return true;
398	}
399
400   /**
401	* Get an element by its name.
402	*
403	* @access	public
404	* @param	string	$name	name of the element
405	* @return	mixed			either a patForms element or an array containing patForms elements
406	* @see		getElementById()
407	*/
408	function &getElementByName( $name )
409	{
410		if( $name == '__form' ) {
411			return $this;
412		}
413		
414		$elements = array();
415		$cnt      = count( $this->elements );
416		for ($i = 0; $i < $cnt; $i++) {
417			if ($this->elements[$i]->getName() == $name) {
418				$elements[]	= &$this->elements[$i];
419				continue;
420			}
421			if (method_exists($this->elements[$i], 'getElementById')) {
422				patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
423				$result = &$this->elements[$i]->getElementByName($name);
424				patErrorManager::popExpect();
425				if (!patErrorManager::isError($result)) {
426					if (is_array($result)) {
427						$cnt2 = count( $result );
428						for ($j = 0; $j < $cnt2; $j++) {
429							$elements[]	= &$result[$j];
430						}
431					} else {
432						$elements[]	= &$result;
433					}
434				}
435			}
436		}
437		
438		switch( count( $elements ) )
439		{
440			case	0:
441				return patErrorManager::raiseError( 
442					PATFORMS_ERROR_ELEMENT_NOT_FOUND, 
443					'Element '.$name.' could not be found.'
444				);
445				break;
446			case	1:
447				return	$elements[0];
448				break;
449			default:
450				return	$elements;
451				break;
452		}
453	}
454
455   /**
456	* Get an element by its id.
457	*
458	* @access	public
459	* @param	string	$id		id of the element
460	* @return	object			patForms element
461	*/
462	function &getElementById( $id )
463	{
464		$cnt	=	count( $this->elements );
465		for( $i = 0; $i < $cnt; $i++ )
466		{
467			if( $this->elements[$i]->getId() == $id ) {
468				return $this->elements[$i];
469			}
470			if (method_exists($this->elements[$i], 'getElementById')) {
471				patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
472				$result = &$this->elements[$i]->getElementById($id);
473				patErrorManager::popExpect();
474				if (!patErrorManager::isError($result)) {
475					return $result;
476				}
477			}
478		}
479		return patErrorManager::raiseError( 
480			PATFORMS_ERROR_ELEMENT_NOT_FOUND, 
481			'Element '.$name.' could not be found.'
482		);
483	}
484
485   /**
486	* Get all elements of the group
487	*
488	* @access	public
489	* @return	array	all elements of the group
490	*/
491	function &getElements()
492	{
493		return	$this->elements;
494	}
495
496   /**
497	* serialize start of group
498	*
499	* @return	null
500	*/
501	function serializeStart()
502	{
503		return null;
504	}
505
506   /**
507	* serialize end of group
508	*
509	* @return	null
510	*/
511	function serializeEnd()
512	{
513		return null;
514	}
515	
516	/**
517	* getValidationErrors
518	*
519	* @access	public
520	* @return 	array	errors that occured during the validation
521	*/
522    function getValidationErrors()
523    {
524    	$this->validationErrors = array();
525    	foreach ($this->elements as $element) {
526    		$childErrors = $element->getValidationErrors();
527    		$this->validationErrors = array_merge($this->validationErrors, $childErrors);
528    	}
529    	return parent::getValidationErrors();
530    }
531
532   /**
533	* sets the current submitted state of the element. Set this to true if you want the element
534	* to pick up its submitted data.
535	*
536	* @access	public
537	* @param	bool	$state	True if it has been submitted, false otherwise (default).
538	* @see		getSubmitted()
539	* @see		$submitted
540	*/
541	function setSubmitted( $state )
542	{
543		$this->submitted = $state;
544		$cnt = count($this->elements);
545    	for ($i = 0; $i < $cnt; $i++) {
546    		$this->elements[$i]->setSubmitted($state);
547    	}
548	}
549	
550   /**
551	* retrieves the current value of the element. If none is set, will try to retrieve the
552	* value from submitted form data.
553	*
554	* @access	public
555	* @param	boolean		Determines whether the method is used from an external script
556	* @return	mixed		The value, or an empty string if none found.
557	* @see		setValue()
558	* @see		value
559	* @see		resolveValue()
560	*/
561	function getValue($external = true)
562	{
563		$value = array();
564		$cnt = count($this->elements);
565		for ($i = 0; $i < $cnt; $i++) {
566			$elName = $this->elements[$i]->getName();
567			$elVal  = $this->elements[$i]->getValue($external);
568			$value[$elName] = $elVal;
569		}
570		return $value;
571	}
572
573   /**
574	* sets the value of the element, which will be used to fill the element with. If none is
575	* set and the element needs a value, it will load it using the {@link resolveValue()} method.
576	*
577	* @access	public
578	* @param	mixed	$value	The value to set
579	* @see		$value
580	* @see		resolveValue()
581	* @see		getValue()
582	*/
583	function setValue($value)
584	{
585		patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
586		foreach ($values as $elName => $value) {
587			$el = &$this->getElementByName($elName);
588			if (patErrorManager::isError($el)) {
589				continue;
590			}
591			$el->setValue($value);
592		}
593		patErrorManager::popExpect();
594		return true;
595	}
596
597   /**
598	* sets the default value of the element, which will be used to fill the element with.
599	*
600	* @access	public
601	* @param	mixed	$value	The value to set
602	* @see		$value
603	* @see		resolveValue()
604	* @see		getValue()
605	*/
606	function setDefaultValue($value)
607	{
608		patErrorManager::pushExpect(PATFORMS_ERROR_ELEMENT_NOT_FOUND);
609		foreach ($values as $elName => $value) {
610			$el = &$this->getElementByName($elName);
611			if (patErrorManager::isError($el)) {
612				continue;
613			}
614			$el->setDefaultValue($value);
615		}
616		patErrorManager::popExpect();
617		return true;
618	}
619
620   /**
621	* replaces an element in the form
622	*
623	* @access	public
624	* @param	object	$element	The patForms_Element object to be replaced
625	* @param	object	&$replace	The element that will replace the old element
626	* @return	bool	$success	True if everything went well, false otherwise.
627	* @see		patForms_Element
628	* @see		addElement()
629	*/
630	function replaceElement( $element, &$replace )
631	{
632		if (is_object($element)) {
633			$element = $element->getId();
634		}
635		
636		$cnt = count($this->elements);
637		for ($i = 0; $i < $cnt; $i++) {
638			if ($this->elements[$i]->getId() !== $element) {
639				continue;
640			}
641
642			if( !$replace->getId() ) {
643				$replace->setId( $this->getElementId() );
644			}
645			$replace->setMode( $this->getMode() );
646			$replace->setFormat( $this->getFormat() );
647			$replace->setSubmitted( $this->isSubmitted() );
648			$replace->setLocale( $this->getLocale() );
649
650			$this->elements[$i] = &$replace;
651			return true;
652		}
653		
654		return false;
655	}
656}
657?>