/**
  * Adds a value to property $name
  *
  * @param string $name
  * @param string $value
  */
 function addProperty($name, $value)
 {
     $op = new ObjectProperty();
     $op->setRelObjectId($this->getId());
     $op->setRelObjectManager(get_class($this->manager()));
     $op->setPropertyName($name);
     $op->setPropertyValue($value);
     $op->save();
 }
	/**
	 * Adds the custom properties of an object into the database.
	 * 
	 * @param $object
	 * @return unknown_type
	 */
	function add_custom_properties($object) {
		if (logged_user()->isGuest()) {
			flash_error(lang('no access permissions'));
			ajx_current("empty");
			return;
		}
		$obj_custom_properties = array_var($_POST, 'object_custom_properties');
		
		$customProps = CustomProperties::getAllCustomPropertiesByObjectType($object->getObjectTypeId());
		//Sets all boolean custom properties to 0. If any boolean properties are returned, they are subsequently set to 1.
		foreach($customProps as $cp){
			if($cp->getType() == 'boolean'){
				$custom_property_value = CustomPropertyValues::getCustomPropertyValue($object->getId(), $cp->getId());
				if(!$custom_property_value instanceof CustomPropertyValue){
					$custom_property_value = new CustomPropertyValue();
				}
				$custom_property_value->setObjectId($object->getId());
				$custom_property_value->setCustomPropertyId($cp->getId());
				$custom_property_value->setValue(0);
				$custom_property_value->save();
			}
		}
		if (is_array($obj_custom_properties)){
			
			foreach($obj_custom_properties as $id => $value){
				//Get the custom property
				$custom_property = null;
				foreach ($customProps as $cp){
					if ($cp->getId() == $id){
						$custom_property = $cp;
						break;
					}
				}
				
				if ($custom_property instanceof CustomProperty){
					// save dates in standard format "Y-m-d H:i:s", because the column type is string
					if ($custom_property->getType() == 'date') {
						if(is_array($value)){
							$newValues = array();
							foreach ($value as $val) {
								$dtv = DateTimeValueLib::dateFromFormatAndString(user_config_option('date_format'), $val);
								$newValues[] = $dtv->format("Y-m-d H:i:s");
							}
							$value = $newValues;
						} else {
							$dtv = DateTimeValueLib::dateFromFormatAndString(user_config_option('date_format'), $value);
							$value = $dtv->format("Y-m-d H:i:s");
						}
					}
					
					//Save multiple values
					if(is_array($value)){
						CustomPropertyValues::deleteCustomPropertyValues($object->getId(), $id);
						foreach($value as &$val){
							if (is_array($val)) {
								// CP type == table
								$str_val = '';
								foreach ($val as $col_val) {
									$col_val = str_replace("|", "\|", $col_val);
									$str_val .= ($str_val == '' ? '' : '|') . $col_val;
								}
								$val = $str_val;
							}
							if($val != ''){
								if(strpos($val, ',')) {
									$val = str_replace(',', '|', $val);
								}
								
								$custom_property_value = new CustomPropertyValue();
								$custom_property_value->setObjectId($object->getId());
								$custom_property_value->setCustomPropertyId($id);
								$custom_property_value->setValue($val);
								$custom_property_value->save();
							}
						}
					}else{
						if($custom_property->getType() == 'boolean'){
							$value = isset($value);
						}
						$cpv = CustomPropertyValues::getCustomPropertyValue($object->getId(), $id);
						if($cpv instanceof CustomPropertyValue){
							$custom_property_value = $cpv;
						} else 
							$custom_property_value = new CustomPropertyValue();
						$custom_property_value->setObjectId($object->getId());
						$custom_property_value->setCustomPropertyId($id);
						$custom_property_value->setValue($value);
						$custom_property_value->save();
					}
					
					//Add to searchable objects
					if ($object->isSearchable() && 
						($custom_property->getType() == 'text' || $custom_property->getType() == 'list' || $custom_property->getType() == 'numeric')){
						
						$name = $custom_property->getName();
						$searchable_object = SearchableObjects::findOne(array("conditions" => "`rel_object_id` = ".$object->getId()." AND `column_name` = '$name'"));
						if (!$searchable_object)
							$searchable_object = new SearchableObject();
						
						if (is_array($value))
							$value = implode(', ', $value);
							
						$searchable_object->setRelObjectId($object->getId());
						$searchable_object->setColumnName($name);
						$searchable_object->setContent($value);
						
						$searchable_object->save();
					}
				}
			}
		}
		
		//Save the key - value pair custom properties (object_properties table)
		$object->clearObjectProperties();
		$names = array_var($_POST, 'custom_prop_names');
		$values = array_var($_POST, 'custom_prop_values');
		if (!is_array($names)) return;
		for ($i=0; $i < count($names); $i++) {
			$name = trim($names[$i]);
			$value = trim($values[$i]);
			if ($name != '' && $value != '') {
				$property = new ObjectProperty();
				$property->setObject($object);
				$property->setPropertyName($name);
				$property->setPropertyValue($value);
				$property->save();
				if ($object->isSearchable()) {
					$object->addPropertyToSearchableObject($property);
				}
			}
		}

	}
 /**
  * Adds the custom properties of an object into the database.
  * 
  * @param $object
  * @return unknown_type
  */
 function add_custom_properties($object)
 {
     if (logged_user()->isGuest()) {
         flash_error(lang('no access permissions'));
         ajx_current("empty");
         return;
     }
     $obj_custom_properties = array_var($_POST, 'object_custom_properties');
     if (is_array($obj_custom_properties)) {
         foreach ($obj_custom_properties as $id => &$val) {
             $val = remove_scripts($val);
         }
     }
     $date_format = user_config_option('date_format');
     $date_format_tip = date_format_tip($date_format);
     $required_custom_props = array();
     $object_type_id = $object instanceof TemplateTask ? ProjectTasks::instance()->getObjectTypeId() : $object->getObjectTypeId();
     $customProps = CustomProperties::getAllCustomPropertiesByObjectType($object_type_id);
     //Sets all boolean custom properties to 0. If any boolean properties are returned, they are subsequently set to 1.
     foreach ($customProps as $cp) {
         if ($cp->getType() == 'boolean') {
             $custom_property_value = CustomPropertyValues::getCustomPropertyValue($object->getId(), $cp->getId());
             if (!$custom_property_value instanceof CustomPropertyValue) {
                 $custom_property_value = new CustomPropertyValue();
             }
             $custom_property_value->setObjectId($object->getId());
             $custom_property_value->setCustomPropertyId($cp->getId());
             $custom_property_value->setValue(0);
             $custom_property_value->save();
         }
         if ($cp->getIsRequired()) {
             $required_custom_props[] = $cp;
         }
     }
     foreach ($required_custom_props as $req_cp) {
         if (!isset($obj_custom_properties[$req_cp->getId()])) {
             throw new Exception(lang('custom property value required', $req_cp->getName()));
         }
     }
     if (is_array($obj_custom_properties)) {
         // check required custom properties
         foreach ($obj_custom_properties as $id => $value) {
             //Get the custom property
             $custom_property = null;
             foreach ($customProps as $cp) {
                 if ($cp->getId() == $id) {
                     $custom_property = $cp;
                     break;
                 }
             }
             if ($custom_property instanceof CustomProperty) {
                 // save dates in standard format "Y-m-d H:i:s", because the column type is string
                 if ($custom_property->getType() == 'date') {
                     if (is_array($value)) {
                         $newValues = array();
                         foreach ($value as $val) {
                             if (trim($val) != '' && trim($val) != $date_format_tip) {
                                 $dtv = DateTimeValueLib::dateFromFormatAndString($date_format, $val);
                                 $newValues[] = $dtv->format("Y-m-d H:i:s");
                             }
                         }
                         $value = $newValues;
                     } else {
                         if (trim($value) != '' && trim($val) != $date_format_tip) {
                             $dtv = DateTimeValueLib::dateFromFormatAndString($date_format, $value);
                             $value = $dtv->format("Y-m-d H:i:s");
                         } else {
                             $value = '';
                         }
                     }
                 }
                 foreach (array_var($_REQUEST, 'remove_custom_properties', array()) as $cpropid => $remove) {
                     if ($remove) {
                         CustomPropertyValues::deleteCustomPropertyValues($object->getId(), $cpropid);
                     }
                 }
                 Hook::fire('before_save_custom_property_value', array('custom_prop' => $custom_property), $value);
                 if (is_array($value)) {
                     if ($custom_property->getType() == 'address') {
                         if ($custom_property->getIsRequired()) {
                             if (array_var($value, 'street') == '' && array_var($value, 'city') == '' && array_var($value, 'state') == '' && array_var($value, 'country') == '' && array_var($value, 'zip_code') == '') {
                                 throw new Exception(lang('custom property value required', $custom_property->getName()));
                             }
                             $errors = array(lang('error form validation'));
                             Env::useHelper('form');
                             $ok = checkAddressInputMandatoryFields($value, $custom_property->getName(), $errors);
                             if (!$ok) {
                                 throw new Exception(implode("\n - ", $errors));
                             }
                         }
                         // Address custom property
                         $val = array_var($value, 'type') . '|' . array_var($value, 'street') . '|' . array_var($value, 'city') . '|' . array_var($value, 'state') . '|' . array_var($value, 'country') . '|' . array_var($value, 'zip_code');
                         CustomPropertyValues::deleteCustomPropertyValues($object->getId(), $id);
                         $custom_property_value = new CustomPropertyValue();
                         $custom_property_value->setObjectId($object->getId());
                         $custom_property_value->setCustomPropertyId($id);
                         $custom_property_value->setValue($val);
                         $custom_property_value->save();
                     } else {
                         //Save multiple values
                         CustomPropertyValues::deleteCustomPropertyValues($object->getId(), $id);
                         foreach ($value as &$val) {
                             if (is_array($val)) {
                                 // CP type == table
                                 $str_val = '';
                                 foreach ($val as $col_val) {
                                     $col_val = str_replace("|", "\\|", $col_val);
                                     $str_val .= ($str_val == '' ? '' : '|') . $col_val;
                                 }
                                 $val = $str_val;
                             }
                             if ($val != '') {
                                 $custom_property_value = new CustomPropertyValue();
                                 $custom_property_value->setObjectId($object->getId());
                                 $custom_property_value->setCustomPropertyId($id);
                                 $custom_property_value->setValue($val);
                                 $custom_property_value->save();
                             }
                         }
                     }
                 } else {
                     if ($custom_property->getType() == 'boolean') {
                         $value = isset($value);
                     }
                     $cpv = CustomPropertyValues::getCustomPropertyValue($object->getId(), $id);
                     if ($cpv instanceof CustomPropertyValue) {
                         $custom_property_value = $cpv;
                     } else {
                         $custom_property_value = new CustomPropertyValue();
                         $custom_property_value->setObjectId($object->getId());
                         $custom_property_value->setCustomPropertyId($id);
                     }
                     $custom_property_value->setValue($value);
                     $custom_property_value->save();
                 }
                 //Add to searchable objects
                 if ($object->isSearchable() && ($custom_property->getType() == 'text' || $custom_property->getType() == 'list' || $custom_property->getType() == 'numeric')) {
                     $name = str_replace("'", "\\'", $custom_property->getName());
                     if (is_array($value)) {
                         $value = implode(', ', $value);
                     }
                     $value = str_replace("'", "\\'", $value);
                     $sql = "INSERT INTO " . TABLE_PREFIX . "searchable_objects (rel_object_id, column_name, content)\r\n\t\t\t\t\t\tVALUES ('" . $object->getId() . "', '" . $name . "', '" . $value . "')\r\n\t\t\t\t\t\tON DUPLICATE KEY UPDATE content='" . $value . "'";
                     DB::execute($sql);
                 }
             }
         }
     }
     //Save the key - value pair custom properties (object_properties table)
     $object->clearObjectProperties();
     $names = array_var($_POST, 'custom_prop_names');
     $values = array_var($_POST, 'custom_prop_values');
     if (!is_array($names)) {
         return;
     }
     for ($i = 0; $i < count($names); $i++) {
         $name = trim($names[$i]);
         $value = trim($values[$i]);
         if ($name != '' && $value != '') {
             $property = new ObjectProperty();
             $property->setObject($object);
             $property->setPropertyName($name);
             $property->setPropertyValue($value);
             $property->save();
             if ($object->isSearchable()) {
                 $object->addPropertyToSearchableObject($property);
             }
         }
     }
 }
 function cloneTask($new_st_date = '', $new_due_date = '', $copy_status = false, $copy_repeat_options = true, $parent_subtask = 0)
 {
     $new_task = new TemplateTask();
     if ($parent_subtask != 0) {
         $new_task->setParentId($parent_subtask);
     } else {
         $new_task->setParentId($this->getParentId());
     }
     $new_task->setObjectName($this->getObjectName());
     $new_task->setText($this->getText());
     $new_task->setAssignedToContactId($this->getAssignedToContactId());
     $new_task->setAssignedOn($this->getAssignedOn());
     $new_task->setAssignedById($this->getAssignedById());
     $new_task->setTimeEstimate($this->getTimeEstimate());
     $new_task->setStartedOn($this->getStartedOn());
     $new_task->setStartedById($this->getStartedById());
     $new_task->setPriority($this->getPriority());
     $new_task->setState($this->getState());
     $new_task->setOrder($this->getOrder());
     $new_task->setMilestoneId($this->getMilestoneId());
     $new_task->setFromTemplateId($this->getFromTemplateId());
     $new_task->setUseStartTime($this->getUseStartTime());
     $new_task->setUseDueTime($this->getUseDueTime());
     $new_task->setTypeContent($this->getTypeContent());
     if ($this->getParentId() == 0) {
         //if not subtask
         if ($this->getOriginalTaskId() == 0) {
             $new_task->setOriginalTaskId($this->getObjectId());
         } else {
             $new_task->setOriginalTaskId($this->getOriginalTaskId());
         }
     }
     if ($this->getDueDate() instanceof DateTimeValue) {
         $new_task->setDueDate(new DateTimeValue($this->getDueDate()->getTimestamp()));
     }
     if ($this->getStartDate() instanceof DateTimeValue) {
         $new_task->setStartDate(new DateTimeValue($this->getStartDate()->getTimestamp()));
     }
     if ($copy_status) {
         $new_task->setCompletedById($this->getCompletedById());
         $new_task->setCompletedOn($this->getCompletedOn());
     }
     if ($copy_repeat_options) {
         $new_task->setRepeatEnd($this->getRepeatEnd());
         $new_task->setRepeatForever($this->getRepeatForever());
         $new_task->setRepeatNum($this->getRepeatNum());
         $new_task->setRepeatBy($this->getRepeatBy());
         $new_task->setRepeatD($this->getRepeatD());
         $new_task->setRepeatM($this->getRepeatM());
         $new_task->setRepeatY($this->getRepeatY());
     }
     if ($new_st_date != "") {
         if ($new_task->getStartDate() instanceof DateTimeValue) {
             $new_task->setStartDate($new_st_date);
         }
     }
     if ($new_due_date != "") {
         if ($new_task->getDueDate() instanceof DateTimeValue) {
             $new_task->setDueDate($new_due_date);
         }
     }
     $new_task->save();
     if (is_array($this->getAllLinkedObjects())) {
         foreach ($this->getAllLinkedObjects() as $lo) {
             $new_task->linkObject($lo);
         }
     }
     $sub_tasks = $this->getAllSubTasks();
     foreach ($sub_tasks as $st) {
         $new_dates = $this->getNextRepetitionDatesSubtask($st, $new_task, $new_st_date, $new_due_date);
         if ($st->getParentId() == $this->getId()) {
             $new_st = $st->cloneTask(array_var($new_dates, 'st'), array_var($new_dates, 'due'), $copy_status, $copy_repeat_options, $new_task->getId());
             if ($copy_status) {
                 $new_st->setCompletedById($st->getCompletedById());
                 $new_st->setCompletedOn($st->getCompletedOn());
                 $new_st->save();
             }
             $new_task->attachTask($new_st);
         }
     }
     foreach ($this->getAllComments() as $com) {
         $new_com = new Comment();
         $new_com->setAuthorEmail($com->getAuthorEmail());
         $new_com->setAuthorName($com->getAuthorName());
         $new_com->setAuthorHomepage($com->getAuthorHomepage());
         $new_com->setCreatedById($com->getCreatedById());
         $new_com->setCreatedOn($com->getCreatedOn());
         $new_com->setUpdatedById($com->getUpdatedById());
         $new_com->setUpdatedOn($com->getUpdatedOn());
         $new_com->setText($com->getText());
         $new_com->setRelObjectId($new_task->getId());
         $new_com->save();
     }
     $_POST['subscribers'] = array();
     foreach ($this->getSubscribers() as $sub) {
         $_POST['subscribers']["user_" . $sub->getId()] = "checked";
     }
     $obj_controller = new ObjectController();
     $obj_controller->add_to_members($new_task, $this->getMemberIds());
     $obj_controller->add_subscribers($new_task);
     foreach ($this->getCustomProperties() as $prop) {
         $new_prop = new ObjectProperty();
         $new_prop->setRelObjectId($new_task->getId());
         $new_prop->setPropertyName($prop->getPropertyName());
         $new_prop->setPropertyValue($prop->getPropertyValue());
         $new_prop->save();
     }
     $custom_props = CustomProperties::getAllCustomPropertiesByObjectType("TemplateTasks");
     foreach ($custom_props as $c_prop) {
         $values = CustomPropertyValues::getCustomPropertyValues($this->getId(), $c_prop->getId());
         if (is_array($values)) {
             foreach ($values as $val) {
                 $cp = new CustomPropertyValue();
                 $cp->setObjectId($new_task->getId());
                 $cp->setCustomPropertyId($val->getCustomPropertyId());
                 $cp->setValue($val->getValue());
                 $cp->save();
             }
         }
     }
     $reminders = ObjectReminders::getByObject($this);
     foreach ($reminders as $reminder) {
         $copy_reminder = new ObjectReminder();
         $copy_reminder->setContext($reminder->getContext());
         $reminder_date = $new_task->getColumnValue($reminder->getContext());
         if ($reminder_date instanceof DateTimeValue) {
             $reminder_date = new DateTimeValue($reminder_date->getTimestamp());
             $reminder_date->add('m', -$reminder->getMinutesBefore());
         }
         $copy_reminder->setDate($reminder_date);
         $copy_reminder->setMinutesBefore($reminder->getMinutesBefore());
         $copy_reminder->setObject($new_task);
         $copy_reminder->setType($reminder->getType());
         $copy_reminder->setUserId($reminder->getUserId());
         $copy_reminder->save();
     }
     return $new_task;
 }
 function cloneTask($copy_status = false)
 {
     $new_task = new ProjectTask();
     $new_task->setParentId($this->getParentId());
     $new_task->setTitle($this->getTitle());
     $new_task->setText($this->getText());
     $new_task->setAssignedToCompanyId($this->getAssignedToCompanyId());
     $new_task->setAssignedToUserId($this->getAssignedToUserId());
     $new_task->setAssignedOn($this->getAssignedOn());
     $new_task->setAssignedById($this->getAssignedById());
     $new_task->setTimeEstimate($this->getTimeEstimate());
     $new_task->setStartedOn($this->getStartedOn());
     $new_task->setStartedById($this->getStartedById());
     $new_task->setPriority($this->getPriority());
     $new_task->setState($this->getState());
     $new_task->setOrder($this->getOrder());
     $new_task->setMilestoneId($this->getMilestoneId());
     $new_task->setIsPrivate($this->getIsPrivate());
     $new_task->setIsTemplate($this->getIsTemplate());
     $new_task->setFromTemplateId($this->getFromTemplateId());
     if ($this->getDueDate() instanceof DateTimeValue) {
         $new_task->setDueDate(new DateTimeValue($this->getDueDate()->getTimestamp()));
     }
     if ($this->getStartDate() instanceof DateTimeValue) {
         $new_task->setStartDate(new DateTimeValue($this->getStartDate()->getTimestamp()));
     }
     if ($copy_status) {
         $new_task->setCompletedById($this->getCompletedById());
         $new_task->setCompletedOn($this->getCompletedOn());
     }
     $new_task->save();
     $new_task->setTagsFromCSV(implode(",", $this->getTagNames()));
     foreach ($this->getWorkspaces() as $ws) {
         $new_task->addToWorkspace($ws);
     }
     if (is_array($this->getAllLinkedObjects())) {
         foreach ($this->getAllLinkedObjects() as $lo) {
             $new_task->linkObject($lo);
         }
     }
     $sub_tasks = $this->getAllSubTasks();
     foreach ($sub_tasks as $st) {
         if ($st->getParentId() == $this->getId()) {
             $new_st = $st->cloneTask($copy_status);
             if ($copy_status) {
                 $new_st->setCompletedById($st->getCompletedById());
                 $new_st->setCompletedOn($st->getCompletedOn());
                 $new_st->save();
             }
             $new_task->attachTask($new_st);
         }
     }
     foreach ($this->getAllComments() as $com) {
         $new_com = new Comment();
         $new_com->setAuthorEmail($com->getAuthorEmail());
         $new_com->setAuthorName($com->getAuthorName());
         $new_com->setAuthorHomepage($com->getAuthorHomepage());
         $new_com->setCreatedById($com->getCreatedById());
         $new_com->setCreatedOn($com->getCreatedOn());
         $new_com->setUpdatedById($com->getUpdatedById());
         $new_com->setUpdatedOn($com->getUpdatedOn());
         $new_com->setIsAnonymous($com->getIsAnonymous());
         $new_com->setIsPrivate($com->getIsPrivate());
         $new_com->setText($com->getText());
         $new_com->setRelObjectId($new_task->getId());
         $new_com->setRelObjectManager("ProjectTasks");
         $new_com->save();
     }
     $_POST['subscribers'] = array();
     foreach ($this->getSubscribers() as $sub) {
         $_POST['subscribers']["user_" . $sub->getId()] = "checked";
     }
     $obj_controller = new ObjectController();
     $obj_controller->add_subscribers($new_task);
     foreach ($this->getCustomProperties() as $prop) {
         $new_prop = new ObjectProperty();
         $new_prop->setRelObjectId($new_task->getId());
         $new_prop->setRelObjectManager($prop->getRelObjectManager());
         $new_prop->setPropertyName($prop->getPropertyName());
         $new_prop->setPropertyValue($prop->getPropertyValue());
         $new_prop->save();
     }
     $custom_props = CustomProperties::getAllCustomPropertiesByObjectType("ProjectTasks");
     foreach ($custom_props as $c_prop) {
         $values = CustomPropertyValues::getCustomPropertyValues($this->getId(), $c_prop->getId());
         if (is_array($values)) {
             foreach ($values as $val) {
                 $cp = new CustomPropertyValue();
                 $cp->setObjectId($new_task->getId());
                 $cp->setCustomPropertyId($val->getCustomPropertyId());
                 $cp->setValue($val->getValue());
                 $cp->save();
             }
         }
     }
     $reminders = ObjectReminders::getByObject($this);
     foreach ($reminders as $reminder) {
         $copy_reminder = new ObjectReminder();
         $copy_reminder->setContext($reminder->getContext());
         $reminder_date = $new_task->getColumnValue($reminder->getContext());
         if ($reminder_date instanceof DateTimeValue) {
             $reminder_date = new DateTimeValue($reminder_date->getTimestamp());
             $reminder_date->add('m', -$reminder->getMinutesBefore());
         }
         $copy_reminder->setDate($reminder_date);
         $copy_reminder->setMinutesBefore($reminder->getMinutesBefore());
         $copy_reminder->setObject($new_task);
         $copy_reminder->setType($reminder->getType());
         $copy_reminder->setUserId($reminder->getUserId());
         $copy_reminder->save();
     }
     return $new_task;
 }