PageRenderTime 39ms CodeModel.GetById 8ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/system/cms/modules/streams_core/models/fields_m.php

https://github.com/gsake/pyrocms
PHP | 811 lines | 430 code | 147 blank | 234 comment | 84 complexity | 894b3c42db2bf30f6b2a924fb9745993 MD5 | raw file
  1<?php defined('BASEPATH') or exit('No direct script access allowed');
  2
  3/**
  4 * PyroStreams Fields Model
  5 *
  6 * @package		PyroCMS\Core\Modules\Streams Core\Models
  7 * @author		Parse19
  8 * @copyright	Copyright (c) 2011 - 2012, Parse19
  9 * @license		http://parse19.com/pyrostreams/docs/license
 10 * @link		http://parse19.com/pyrostreams
 11 */
 12class Fields_m extends CI_Model {
 13
 14	public $table;
 15
 16    // --------------------------------------------------------------------------
 17
 18	/**
 19	 * Fields Validation
 20	 */
 21	public $fields_validation = array(
 22		array(
 23			'field'	=> 'field_name',
 24			'label' => 'lang:streams.label.field_name',
 25			'rules'	=> 'trim|required|max_length[60]'
 26		),
 27		array(
 28			'field'	=> 'field_slug',
 29			'label' => 'lang:streams.label.field_slug',
 30			'rules'	=> 'trim|required|max_length[60]|slug_safe'
 31		),
 32		array(
 33			'field'	=> 'field_type',
 34			'label' => 'lang:streams.label.field_type',
 35			'rules'	=> 'trim|required|max_length[50]|type_valid'
 36		)
 37	);
 38
 39	// --------------------------------------------------------------------------
 40
 41	public $fields_cache;
 42
 43	// --------------------------------------------------------------------------
 44
 45	function __construct()
 46	{
 47		$this->table = FIELDS_TABLE;
 48	}
 49    
 50    // --------------------------------------------------------------------------
 51    
 52    /**
 53     * Get some fields
 54     *
 55     * @access	public
 56     * @param	[string - field namespace]
 57     * @param	[int limit]
 58     * @param	[int offset]
 59     * @return	obj
 60     */
 61    public function get_fields($namespace = NULL, $limit = FALSE, $offset = 0, $skips = array())
 62	{
 63		if (!empty($skips)) $this->db->or_where_not_in('field_slug', $skips);
 64		
 65		if ($namespace) $this->db->where('field_namespace', $namespace);
 66	
 67		if ($offset) $this->db->offset($offset);
 68		
 69		if ($limit) $this->db->limit($limit);
 70
 71		$query = $this->db->order_by('field_name', 'asc')->get($this->table);
 72     
 73    	return $query->result();
 74	}
 75    
 76    // --------------------------------------------------------------------------
 77    
 78    /**
 79     * Get all fields with extra field info
 80     *
 81     * @access	public
 82     * @param	int limit
 83     * @param	int offset
 84     * @return	obj
 85     */
 86    public function get_all_fields()
 87	{
 88		$obj = $this->db->order_by('field_name', 'asc')->get($this->table);
 89		
 90		$fields = $obj->result_array();
 91		
 92		$return_fields = array();
 93
 94		foreach($fields as $key => $field)
 95		{
 96			$return_fields[$field['field_slug']] = $field;
 97 			$return_fields[$field['field_slug']]['field_data'] = unserialize($field['field_data']);
 98		}
 99    	
100    	return $return_fields;
101	}
102
103    // --------------------------------------------------------------------------
104    
105    /**
106     * Count fields
107     *
108     * @access	public
109     * @return	int
110     */
111	public function count_fields($namespace)
112	{
113		if ( ! $namespace) return 0;
114
115		return $this->db
116				->where('field_namespace', $namespace)
117				->from($this->table)
118				->count_all_results();
119	}
120
121    // --------------------------------------------------------------------------
122
123	/**
124	 * Insert a field
125	 *
126	 * @access	public
127	 * @param	string - the field name
128	 * @param	string - the field slug
129	 * @param	string - the field type
130	 * @param	[array - any extra data]
131	 * @return	bool
132	 */
133	public function insert_field($field_name, $field_slug, $field_type, $field_namespace, $extra = array(), $locked = 'no')
134	{
135		if ( ! $locked)
136		{
137			$locked = 'no';
138		}
139
140		if ($locked != 'yes' and $locked != 'no')
141		{
142			$locked = 'no';
143		}
144
145		$insert_data = array(
146			'field_name' 		=> $field_name,
147			'field_slug'		=> $field_slug,
148			'field_namespace'	=> $field_namespace,
149			'field_type'		=> $field_type,
150			'is_locked'			=> $locked
151		);
152	
153		// Load the type to see if there are other fields
154		$field_type = $this->type->types->$field_type;
155		
156		if (isset($field_type->custom_parameters))
157		{
158			$extra_data = array();
159		
160			foreach ($field_type->custom_parameters as $param)
161			{
162				if (method_exists($field_type, 'param_'.$param.'_pre_save'))
163				{
164					$extra_data[$param] = $field_type->{'param_'.$param.'_pre_save'}($insert_data);
165				}
166				elseif(isset($extra[$param]))
167				{
168					$extra_data[$param] = $extra[$param];
169				}
170			}
171		
172			$insert_data['field_data'] = serialize($extra_data);
173		}
174		
175		return $this->db->insert($this->table, $insert_data);
176	}
177
178	// --------------------------------------------------------------------------
179	
180	/**
181	 * Take field data and parse it into an array
182	 * the the DB forge class can use
183	 *
184	 * @access	public
185	 * @param	obj
186	 * @param	array
187	 * @param	string
188	 * @return	array
189	 */
190	public function field_data_to_col_data($type, $field_data, $method = 'add')
191	{
192		$col_data = array();
193
194		// -------------------------------------		
195		// Name
196		// -------------------------------------
197		
198		if ($method == 'edit')
199		{
200			$col_data['name'] 			= $field_data['field_slug'];
201		}
202		
203		// -------------------------------------		
204		// Col Type
205		// -------------------------------------		
206	
207		$col_data['type'] 				= strtoupper($type->db_col_type);
208		
209		// -------------------------------------		
210		// Constraint
211		// -------------------------------------
212		
213		// First we check and see if a constraint has been added
214		if (isset($type->col_constraint) and $type->col_constraint)
215		{
216			$col_data['constraint']		= $type->col_constraint;
217		}	
218		// Otherwise, we'll check for a max_length field
219		elseif (isset($field_data['max_length']) and is_numeric($field_data['max_length']))
220		{	
221			$col_data['constraint']		= $field_data['max_length'];
222		}
223
224		// -------------------------------------		
225		// Text field varchar change
226		// -------------------------------------
227		
228		if ($type->field_type_slug == 'text')		
229		{
230			if (isset($col_data['constraint']) and $col_data['constraint'] > 255)
231			{
232				$col_data['type'] 				= 'TEXT';
233				
234				// Don't need a constraint no more
235				unset($col_data['constraint']);
236			}
237			else
238			{
239				$col_data['type'] 				= 'VARCHAR';
240			}
241		}
242
243		// -------------------------------------		
244		// Default
245		// -------------------------------------		
246		
247		if (isset($field_data['default_value']) and $field_data['default_value'] != '')
248		{
249			$col_data['default']		= $field_data['default_value'];
250		}
251
252		// -------------------------------------		
253		// Remove Default for some col types:
254		// -------------------------------------
255		// * TEXT
256		// * LONGTEXT
257		// -------------------------------------
258		
259		$no_default = array('TEXT', 'LONGTEXT');
260		
261		if (in_array($col_data['type'], $no_default))
262		{
263			unset($col_data['default']);
264		}
265
266		// -------------------------------------		
267		// Default to allow null
268		// -------------------------------------		
269
270		$col_data['null'] = true;
271
272		// -------------------------------------		
273		// Check for varchar with no constraint
274		// -------------------------------------
275		// Catch it and default to 255
276		// -------------------------------------		
277
278		if ($col_data['type'] == 'VARCHAR' and ( ! isset($col_data['constraint']) || !is_numeric($col_data['constraint']) || $col_data['constraint'] == ''))
279		{
280			$col_data['constraint'] = 255;
281		}
282
283		// -------------------------------------	
284		
285		return $col_data;	
286	}
287
288	// --------------------------------------------------------------------------
289	
290	/**
291	 * Update field
292	 *
293	 * @access	public
294	 * @param	obj
295	 * @param	array - data
296	 * @param	int
297	 */
298	public function update_field($field, $data)
299	{	
300		$type = $this->type->types->{$data['field_type']};
301		
302		// -------------------------------------
303		// Alter Columns	
304		// -------------------------------------		
305		// We want to change columns if the
306		// following change:
307		//		
308		// * Field Type
309		// * Field Slug
310		// * Max Length
311		// * Default Value
312		// -------------------------------------		
313
314		$assignments = $this->get_assignments($field->id);
315	
316		if(
317			$field->field_type != $data['field_type'] or 
318			$field->field_slug != $data['field_slug'] or 
319			( isset( $field->field_data['max_length'] ) and  $field->field_data['max_length'] != $data['max_length'] ) or  
320			( isset( $field->field_data['default_value'] ) and  $field->field_data['default_value'] != $data['default_value'] )
321		)
322		{						
323			// If so, we need to update some table columns
324			// Get the field assignments and change the table names
325						
326			// Check first to see if there are any assignments
327			if ($assignments)
328			{
329				// Alter the table names and types
330				$this->load->dbforge();
331				
332				foreach ($assignments as $assignment)
333				{				
334					if ( ! method_exists($type, 'alt_rename_column'))
335					{
336						if ( ! $this->dbforge->modify_column($assignment->stream_prefix.$assignment->stream_slug, array($field->field_slug => $this->field_data_to_col_data($type, $data, 'edit'))))
337						{
338							return false;
339						}
340					}
341					
342					// Update the view options
343					$view_options = unserialize($assignment->stream_view_options);
344					
345					if (is_array($view_options))
346					{
347						foreach ($view_options as $key => $option)
348						{
349							if ($option == $field->field_slug)
350							{
351								// Replace with the new field slug so nothing goes apeshit
352								$view_options[$key] = $data['field_slug'];
353							}
354						}
355					}
356					else
357					{
358						$view_options = array();
359					}
360					
361					$vo_update_data['view_options'] = serialize($view_options);
362	
363					$this->db->where('id', $assignment->stream_id)->update(STREAMS_TABLE, $vo_update_data);
364	
365					$vo_update_data 	= array();
366					$view_options 		= array();
367				}
368			}
369
370			// Run though alt rename column routines. Needs to be done
371			// after the above loop through assignments.
372			if ($assignments)
373			{
374				foreach ($assignments as $assignment)
375				{
376					if (method_exists($type, 'alt_rename_column'))
377					{
378						// We run a different function for alt_process
379						$type->alt_rename_column($field, $this->streams_m->get_stream($assignment->stream_slug), $assignment);
380					}
381				}
382			}
383		}
384
385		// Run edit field update hook
386		if (method_exists($type, 'update_field'))					
387		{
388			$type->update_field($field, $assignments);
389		}
390			
391		// Update field information		
392		if (isset($data['field_name']))			$update_data['field_name']		= $data['field_name'];
393		if (isset($data['field_slug'])) 		$update_data['field_slug']		= $data['field_slug'];
394		if (isset($data['field_namespace'])) 	$update_data['field_namespace']	= $data['field_namespace'];
395		if (isset($data['field_type']))			$update_data['field_type']		= $data['field_type'];
396
397		if (isset($data['is_locked']))
398		{
399			if ( ! $data['is_locked'])
400			{
401				$data['is_locked'] = 'no';
402			}
403
404			if ($data['is_locked'] != 'yes' and $data['is_locked']!= 'no')
405			{
406				$data['is_locked'] = 'no';
407			}
408		}
409
410		// Gather extra data		
411		if ( ! isset($type->custom_parameters) or $type->custom_parameters == '')
412		{
413			$update_data['field_data'] = null;
414		}
415		else
416		{
417			$custom_params = array();
418
419			foreach ($type->custom_parameters as $param)
420			{
421				if (method_exists($type, 'param_'.$param.'_pre_save'))
422				{
423					$custom_params[$param] = $type->{'param_'.$param.'_pre_save'}($update_data);
424				}
425				elseif(isset($data[$param]))
426				{
427					$custom_params[$param] = $data[$param];
428				}
429			}
430
431			if ( ! empty($custom_params))
432			{
433				$update_data['field_data'] = serialize($custom_params);
434			}
435		}
436		
437		$this->db->where('id', $field->id);
438					
439		if ($this->db->update('data_fields', $update_data))
440		{
441			$tc_update['title_column']	= $data['field_slug'];
442		
443			// Success. Now let's update the title column.
444			$this->db->where('title_column', $field->field_slug);
445			return $this->db->update(STREAMS_TABLE, $tc_update);
446		}	
447		else
448		{
449			// Boo.
450			return false;
451		}
452	}
453
454	// --------------------------------------------------------------------------
455
456    /**
457     * Count assignments
458     *
459     * @access	public
460     * @return	int
461     */
462	public function count_assignments($field_id)
463	{
464		if ( ! $field_id) return 0;
465
466		return $this->db
467				->where('field_id', $field_id)
468				->from($this->db->dbprefix(ASSIGN_TABLE))
469				->count_all_results();
470	}
471
472	// --------------------------------------------------------------------------
473	
474	/**
475	 * Get assignments for a field
476	 *
477	 * @access	public
478	 * @param	int
479	 * @return	mixed
480	 */
481	public function get_assignments($field_id)
482	{
483		$this->db->select(STREAMS_TABLE.'.*, '.STREAMS_TABLE.'.view_options as stream_view_options, '.STREAMS_TABLE.'.id as stream_id, '.FIELDS_TABLE.'.id as field_id, '.FIELDS_TABLE.'.*, '.FIELDS_TABLE.'.view_options as field_view_options');
484		$this->db->from(STREAMS_TABLE.', '.ASSIGN_TABLE.', '.FIELDS_TABLE);
485		$this->db->where($this->db->dbprefix(STREAMS_TABLE).'.id', $this->db->dbprefix(ASSIGN_TABLE).'.stream_id', FALSE);
486		$this->db->where($this->db->dbprefix(FIELDS_TABLE).'.id', $this->db->dbprefix(ASSIGN_TABLE).'.field_id', FALSE);
487		$this->db->where($this->db->dbprefix(ASSIGN_TABLE).'.field_id', $field_id, FALSE);
488		
489		$obj = $this->db->get();
490		
491		if ($obj->num_rows() == 0)
492		{
493			return false;
494		}
495		
496		return $obj->result();
497	}
498
499	// --------------------------------------------------------------------------
500	
501	/**
502	 * Get assignments for a stream
503	 *
504	 * @access	public
505	 * @param	int
506	 * @return	mixed
507	 */
508	public function get_assignments_for_stream($stream_id)
509	{
510		$this->db->select(STREAMS_TABLE.'.*, '.STREAMS_TABLE.'.view_options as stream_view_options, '.ASSIGN_TABLE.'.id as assign_id, '.STREAMS_TABLE.'.id as stream_id, '.FIELDS_TABLE.'.id as field_id, '.FIELDS_TABLE.'.*, '.FIELDS_TABLE.'.view_options as field_view_options, '.ASSIGN_TABLE.'.instructions, '.ASSIGN_TABLE.'.is_required, '.ASSIGN_TABLE.'.is_unique');
511		$this->db->from(STREAMS_TABLE.', '.ASSIGN_TABLE.', '.FIELDS_TABLE);
512		$this->db->where($this->db->dbprefix(STREAMS_TABLE).'.id', $this->db->dbprefix(ASSIGN_TABLE).'.stream_id', FALSE);
513		$this->db->where($this->db->dbprefix(FIELDS_TABLE).'.id', $this->db->dbprefix(ASSIGN_TABLE).'.field_id', FALSE);
514		$this->db->where($this->db->dbprefix(ASSIGN_TABLE).'.stream_id', $stream_id, FALSE);
515		$this->db->order_by('sort_order', 'ASC');
516		
517		$obj = $this->db->get();
518			
519		if ($obj->num_rows() == 0)
520		{
521			return false;
522		}
523		
524		return $obj->result();
525	}
526
527	// --------------------------------------------------------------------------
528	
529	/**
530	 * Delete a field
531	 *
532	 * @access	public
533	 * @param	int
534	 * @return	bool
535	 */
536	public function delete_field($field_id)
537	{
538		// Make sure field exists		
539		if ( ! $field = $this->get_field($field_id))
540		{
541			return false;
542		}
543	
544		// Find assignments, and delete rows from table
545		$assignments = $this->get_assignments($field_id);
546		
547		if ($assignments)
548		{
549			$this->load->dbforge();
550		
551			$outcome = true;
552		
553			// Cycle and delete columns			
554			foreach ($assignments as $assignment)
555			{
556				$this->cleanup_assignment($assignment);
557			}
558			
559			if ( ! $outcome) return $outcome;
560		}
561		
562		// Delete field assignments		
563		$this->db->where('field_id', $field->id);
564		
565		if ( ! $this->db->delete(ASSIGN_TABLE))
566		{
567			return false;
568		}
569		
570		// Reset instances where the title column
571		// is the field we are deleting. PyroStreams will
572		// always just use the ID in place of the field.
573		$this->db->where('title_column', $field->field_slug);
574		$this->db->update(STREAMS_TABLE, array('title_column' => null));
575		
576		// Delete from actual fields table		
577		$this->db->where('id', $field->id);
578		
579		if ( ! $this->db->delete(FIELDS_TABLE))
580		{
581			return false;
582		}
583
584		return true;
585	}
586
587	// --------------------------------------------------------------------------
588
589	/**
590	 * Field garbage cleanup
591	 *
592	 * @access	public
593	 * @param	obj - the assignment
594	 * @return	void
595	 */
596	function cleanup_assignment($assignment)
597	{
598		// Drop the column if it exists
599		if ($this->db->field_exists($assignment->field_slug, $assignment->stream_prefix.$assignment->stream_slug))
600		{
601			if ( ! $this->dbforge->drop_column($assignment->stream_prefix.$assignment->stream_slug, $assignment->field_slug) )
602			{
603				$outcome = false;
604			}
605		}
606
607		// Run the destruct
608		if (method_exists($this->type->types->{$assignment->field_type}, 'field_assignment_destruct'))
609		{
610			$this->type->types->{$assignment->field_type}->field_assignment_destruct($this->get_field($assignment->field_id), $this->streams_m->get_stream($assignment->stream_slug, true));
611		}
612		
613		// Update that stream's view options
614		$view_options = unserialize($assignment->stream_view_options);
615		
616		if (is_array($view_options))
617		{
618			foreach ($view_options as $key => $option)
619			{
620				if ($option == $assignment->field_slug)
621				{
622					unset($view_options[$key]);
623				}
624			}
625		}
626		else
627		{
628			$view_options = array();
629		}
630		
631		$update_data['view_options'] = serialize($view_options);
632	
633		$this->db->where('id', $assignment->stream_id)->update(STREAMS_TABLE, $update_data);
634	
635		unset($update_data);
636		unset($view_options);
637	}
638
639	// --------------------------------------------------------------------------
640
641	/**
642	 * Get a single field
643	 *
644	 * @access	public
645	 * @param	int
646	 * @return	obj
647	 */
648	public function get_field($field_id)
649	{
650		// Check for already cached value
651		if (isset($this->fields_cache['by_id'][$field_id]))
652		{
653			return $this->fields_cache['by_id'][$field_id];
654		}
655
656		$this->db->limit(1)->where('id', $field_id);
657		
658		$obj = $this->db->get($this->table);
659		
660		if ($obj->num_rows() == 0)
661		{
662			return false;
663		}
664		
665		$field = $obj->row();
666		
667		$field->field_data = unserialize($field->field_data);
668
669		// Save for later use
670		$this->fields_cache['by_id'][$field_id] = $field;
671		
672		return $field;
673	}
674
675	// --------------------------------------------------------------------------
676
677	/**
678	 * Get a single field by the field slug
679	 *
680	 * @access	public
681	 * @param	string - field slug
682	 * @param	string - field namespace
683	 * @return	obj
684	 */
685	public function get_field_by_slug($field_slug, $field_namespace)
686	{
687		// Check for already cached value
688		if (isset($this->fields_cache['by_slug'][$field_slug]))
689		{
690			return $this->fields_cache['by_slug'][$field_slug];
691		}
692
693		$obj = $this->db
694				->limit(1)
695				->where('field_namespace', $field_namespace)
696				->where('field_slug', $field_slug)
697				->get($this->table);
698		
699		if ($obj->num_rows() == 0)
700		{
701			return false;
702		}
703		
704		$field = $obj->row();
705		
706		$field->field_data = unserialize($field->field_data);
707
708		// Save for later use
709		$this->fields_cache['by_slug'][$field_slug] = $field;
710		
711		return $field;
712	}
713
714	// --------------------------------------------------------------------------
715
716	/**
717	 * Assignment Exists
718	 *
719	 * @access 	public
720	 * @param 	int - stream ID
721	 * @param 	int - field ID
722	 * @return 	bool
723	 */
724	public function assignment_exists($stream_id, $field_id)
725	{
726		if ($this->db->select('id')->where('stream_id', $stream_id)->where('field_id', $field_id)->get(ASSIGN_TABLE)->num_rows() > 0)
727		{
728			return true;
729		}
730		else
731		{
732			return false;
733		}
734	}
735
736	// --------------------------------------------------------------------------
737
738	/**
739	 * Edit Assignment
740	 *
741	 * @access	public
742	 * @param	int
743	 * @param	obj
744	 * @param	obj
745	 * @param	[string - instructions]
746	 * return	bool
747	 */
748	public function edit_assignment($assignment_id, $stream, $field, $data)
749	{
750		// -------------------------------------
751		// Title Column
752		// -------------------------------------
753
754		// Scenario A: The title column is the field slug, and we 
755		// have it unchecked.
756		if (
757			$stream->title_column == $field->field_slug and
758			( ! isset($data['title_column']) or $data['title_column'] == 'no' or ! $data['title_column'])
759		)
760		{
761			// In this case, they don't want this to
762			// be the title column anymore, so we wipe it out
763			$this->db
764				->limit(1)
765				->where('id', $stream->id)
766				->update('data_streams', array('title_column' => null));
767		}
768		elseif (
769			isset($data['title_column']) and
770			($data['title_column'] == 'yes' or $data['title_column'] === true) and
771			$stream->title_column != $field->field_slug
772		)
773		{
774			// Scenario B: They have checked the title column
775			// and this field it not the current field.
776			$this->db
777					->limit(1)
778					->where('id', $stream->id)
779					->update('data_streams', array('title_column' => $field->field_slug));
780		}
781
782		// Is required	
783		if( isset($data['is_required']) and $data['is_required'] == 'yes' ):
784
785			$update_data['is_required'] = 'yes';
786
787		else:
788
789			$update_data['is_required'] = 'no';
790
791		endif;
792
793		// Is unique
794		if( isset($data['is_unique']) and $data['is_unique'] == 'yes' ):
795
796			$update_data['is_unique'] = 'yes';
797
798		else:
799
800			$update_data['is_unique'] = 'no';
801
802		endif;
803
804		// Add in instructions		
805		$update_data['instructions'] = $data['instructions'];
806
807		$this->db->where('id', $assignment_id);
808		return $this->db->update(ASSIGN_TABLE, $update_data);
809	}
810
811}