/**
  * Return all report column names
  *
  * @param report_id
  * @return array
  */
 static function getReportColumnNames($report_id)
 {
     $colNames = array();
     $columns = self::findAll(array('conditions' => array("`report_id` = ?", $report_id)));
     // findAll
     foreach ($columns as $col) {
         if ($col->getCustomPropertyId() > 0) {
             $cp = CustomProperties::getCustomProperty($col->getCustomPropertyId());
             if ($cp instanceof CustomProperty) {
                 $colNames[] = $cp->getName();
             }
         } else {
             $colNames[] = $col->getFieldName();
         }
     }
     return $colNames;
 }
	/**
	 * Validate before save
	 *
	 * @access public
	 * @param array $errors
	 * @return null
	 */
	function validate(&$errors) {
		$cp = CustomProperties::getCustomProperty($this->getCustomPropertyId());
		if($cp instanceof CustomProperty){
			if($cp->getIsRequired() && ($this->getValue() == '')){
				$errors[] = lang('custom property value required', $cp->getName());
			}
			if($cp->getType() == 'numeric'){
				if($cp->getIsMultipleValues()){
					foreach(explode(',', $this->getValue()) as $value){
						if($value != '' && !is_numeric($value)){
							$errors[] = lang('value must be numeric', $cp->getName());
						}
					}
				}else{
					if($this->getValue() != '' && !is_numeric($this->getValue())){
						$errors[] = lang('value must be numeric', $cp->getName());
					}
				}
			}
		}//if
	} // validate
 static function removeDuplicateRows($rows)
 {
     $duplicateIds = array();
     foreach ($rows as $row) {
         if (!isset($duplicateIds[$row['id']])) {
             $duplicateIds[$row['id']] = 0;
         }
         $duplicateIds[$row['id']]++;
     }
     foreach ($duplicateIds as $id => $count) {
         if ($count < 2) {
             unset($duplicateIds[$id]);
         }
     }
     $duplicateIds = array_keys($duplicateIds);
     foreach ($rows as $row) {
         if (in_array($row['id'], $duplicateIds)) {
             foreach ($row as $col => $value) {
                 $cp = CustomProperties::getCustomProperty($col);
                 if ($cp instanceof CustomProperty && $cp->getIsMultipleValues()) {
                 }
             }
         }
     }
     return $rows;
 }
 private function get_report_column_types($report_id)
 {
     $col_types = array();
     $report = Reports::getReport($report_id);
     $model = $report->getObjectType();
     $manager = new $model();
     $columns = ReportColumns::getAllReportColumns($report_id);
     foreach ($columns as $col) {
         $cp_id = $col->getCustomPropertyId();
         if ($cp_id == 0) {
             $col_types[$col->getFieldName()] = $manager->getColumnType($col->getFieldName());
         } else {
             $cp = CustomProperties::getCustomProperty($cp_id);
             if ($cp) {
                 $col_types[$cp->getName()] = $cp->getOgType();
             }
         }
     }
     return $col_types;
 }
 /**
  * List custom properties
  *
  * @access public
  * @param void
  * @return null
  */
 function custom_properties()
 {
     if (!can_manage_configuration(logged_user())) {
         flash_error(lang('no access permissions'));
         ajx_current("empty");
         return;
     }
     $object_types = ObjectTypes::instance()->findAll(array("conditions" => "`type` IN ('content_object')  AND `name` <> 'template_task' AND name <> 'template_milestone' AND `name` <> 'file revision'", "order" => "name"));
     $ordered_object_types = array();
     foreach ($object_types as $ot) {
         $ordered_object_types[$ot->getId()] = lang($ot->getName());
     }
     asort($ordered_object_types, SORT_STRING);
     $select_options = array('<option value="" selected>' . lang('select one') . '</option>');
     foreach ($ordered_object_types as $k => $v) {
         $select_options[] = '<option value="' . $k . '">' . $v . '</option>';
     }
     tpl_assign('object_types', $select_options);
     $custom_properties = array_var($_POST, 'custom_properties');
     $obj_type_id = array_var($_POST, 'objectType');
     $delete = 0;
     if (is_array($custom_properties)) {
         try {
             DB::beginWork();
             foreach ($custom_properties as $id => $data) {
                 $new_cp = null;
                 if ($data['id'] != '') {
                     $new_cp = CustomProperties::getCustomProperty($data['id']);
                 }
                 if ($new_cp == null) {
                     $new_cp = new CustomProperty();
                 }
                 if ($data['deleted'] == "1") {
                     $delete = $delete + 1;
                     if (!$new_cp->isNew()) {
                         $new_cp->delete();
                     }
                     continue;
                 }
                 $new_cp->setObjectTypeId($obj_type_id);
                 $new_cp->setName($data['name']);
                 $new_cp->setType($data['type']);
                 $new_cp->setDescription($data['description']);
                 if ($data['type'] == 'list') {
                     $values = array();
                     $list = explode(",", $data['values']);
                     foreach ($list as $l) {
                         $values[] = trim($l);
                     }
                     $value = implode(",", $values);
                     $new_cp->setValues($value);
                 } else {
                     $new_cp->setValues($data['values']);
                 }
                 if ($data['type'] == 'boolean') {
                     $new_cp->setDefaultValue(isset($data['default_value_boolean']));
                 } else {
                     $new_cp->setDefaultValue($data['default_value']);
                 }
                 $new_cp->setIsRequired(isset($data['required']));
                 $new_cp->setIsMultipleValues(isset($data['multiple_values']));
                 $new_cp->setOrder($data['order'] - $delete);
                 $new_cp->setVisibleByDefault(isset($data['visible_by_default']));
                 $new_cp->save();
                 if (is_array(array_var($data, 'applyto'))) {
                     $applyto = array_var($data, 'applyto');
                     foreach ($applyto as $co_type => $value) {
                         if ($value == 'true') {
                             if (!CustomPropertiesByCoType::findById(array('co_type_id' => $co_type, 'cp_id' => $new_cp->getId()))) {
                                 $obj = new CustomPropertyByCoType();
                                 $obj->setCoTypeId($co_type);
                                 $obj->setCpId($new_cp->getId());
                                 $obj->save();
                             }
                         } else {
                             $obj = CustomPropertiesByCoType::findById(array('co_type_id' => $co_type, 'cp_id' => $new_cp->getId()));
                             if ($obj) {
                                 $obj->delete();
                             }
                         }
                     }
                 }
             }
             DB::commit();
             flash_success(lang('custom properties updated'));
             ajx_current('back');
         } catch (Exception $ex) {
             DB::rollback();
             flash_error($ex->getMessage());
         }
     }
 }
?>
</b></td>
			<td style="text-align:center;padding:0 10px 10px 10px;"><b><?php 
echo lang('condition');
?>
</b></td>
			<td style="text-align:center;padding:0 10px 10px 10px;"><b><?php 
echo lang('value');
?>
</b></td>
		</tr>
		
		<?php 
foreach ($conditions as $condition) {
    if ($condition->getCustomPropertyId() > 0) {
        $cp = CustomProperties::getCustomProperty($condition->getCustomPropertyId());
        if (!$cp) {
            continue;
        }
    }
    $tiCount++;
    ?>
			<tr style='height:30px;'>
			<?php 
    if ($condition->getCustomPropertyId() > 0) {
        $name = clean($cp->getName());
    } else {
        if ($condition->getFieldName() != 'workspace' && $condition->getFieldName() != 'tag') {
            $name = lang('field ' . $model . ' ' . $condition->getFieldName());
        } else {
            $name = lang($condition->getFieldName());
                        //for normal properties
                        //currently disabled as at the moment the only columns that can be added are custom properties
                        $value = format_value_to_print_task($task->getColumnValue($i), $task->getColumnType($i));
                        ?>
<td style="padding:4px;max-width:250px;<?php 
                        echo $isAlt ? 'background-color:#F2F2F2' : '';
                        ?>
"><?php 
                        echo $value;
                        ?>
</td><?php 
                    } else {
                        //for custom properties
                        $values = CustomPropertyValues::getCustomPropertyValue($task->getId(), $i);
                        if ($values != null) {
                            $cp = CustomProperties::getCustomProperty($i);
                            $value = format_value_to_print_task($values->getValue(), $cp->getOgType());
                            ?>
<td style="padding:4px;max-width:250px;<?php 
                            echo $isAlt ? 'background-color:#F2F2F2' : '';
                            ?>
"><?php 
                            echo $value;
                            ?>
</td><?php 
                        } else {
                            ?>
<td style="padding:4px;max-width:250px;<?php 
                            echo $isAlt ? 'background-color:#F2F2F2' : '';
                            ?>
"><?php 
 /**
  * Returns timeslots based on the set query parameters
  *
  * @param User $user
  * @param string $workspacesCSV
  * @param DateTimeValue $start_date
  * @param DateTimeValue $end_date
  * @param string $object_manager
  * @param string $object_id
  * @param array $group_by
  * @param array $order_by
  * @return array
  */
 static function getTaskTimeslots($workspace = null, $user = null, $workspacesCSV = null, $start_date = null, $end_date = null, $object_id = 0, $group_by = null, $order_by = null, $limit = 0, $offset = 0, $timeslot_type = 0, $custom_conditions = null, $object_subtype = null)
 {
     $wslevels = 0;
     foreach ($group_by as $gb) {
         if ($gb == "project_id") {
             $wslevels++;
         }
     }
     $wsDepth = 0;
     if ($workspace instanceof Project) {
         $wsDepth = $workspace->getDepth();
     }
     $wslevels = min(array($wslevels, 10 - $wsDepth));
     if ($wslevels < 0) {
         $wslevels = 0;
     }
     $select = "SELECT `ts`.*";
     for ($i = 0; $i < $wslevels; $i++) {
         $select .= ", `ws" . $i . "`.`name` AS `wsName" . $i . "`, `ws" . $i . "`.`id` AS `wsId" . $i . "`";
     }
     $preFrom = " FROM ";
     for ($i = 0; $i < $wslevels; $i++) {
         $preFrom .= "(";
     }
     $postFrom = "";
     for ($i = 0; $i < $wslevels; $i++) {
         $postFrom .= ") LEFT OUTER JOIN `" . TABLE_PREFIX . "projects` AS `ws" . $i . "` ON `pr`.`p" . ($wsDepth + $i + 1) . "` = `ws" . $i . "`.`id`";
     }
     $commonConditions = "";
     if ($start_date) {
         $commonConditions .= DB::prepareString(' AND `ts`.`start_time` >= ? ', array($start_date));
     }
     if ($end_date) {
         $commonConditions .= DB::prepareString(' AND (`ts`.`paused_on` <> 0 OR `ts`.`end_time` <> 0) AND `ts`.`end_time` < ? ', array($end_date));
     }
     //$commonConditions .= DB::prepareString(' AND (`ts`.`paused_on` <> 0 OR `ts`.`end_time` <> 0) AND `ts`.`end_time` > 0 AND `ts`.`end_time` < ? ', array($end_date));  -- another fix reported by a user, but we have to test it yet
     //User condition
     $commonConditions .= $user ? ' AND `ts`.`user_id` = ' . $user->getId() : '';
     //Object condition
     $commonConditions .= $object_id > 0 ? ' AND `ts`.`object_manager` = "ProjectTasks" AND `ts`.`object_id` = ' . $object_id : '';
     //Only applies to tasks
     $sql = '';
     //Custom properties conditions
     $custom_cond = '';
     $custom = false;
     if (count($custom_conditions) > 0) {
         $custom = true;
         foreach ($custom_conditions as $condCp) {
             //array_var($condCp, 'custom_property_id');
             $cp = CustomProperties::getCustomProperty(array_var($condCp, 'custom_property_id'));
             //$skip_condition = false;
             $dateFormat = 'm/d/Y';
             if (isset($params[array_var($condCp, 'id') . "_" . $cp->getName()])) {
                 $value = $params[array_var($condCp, 'id') . "_" . $cp->getName()];
                 if ($cp->getType() == 'date') {
                     $dateFormat = user_config_option('date_format');
                 }
             } else {
                 $value = array_var($condCp, 'value');
             }
             $custom_cond .= ' AND `pt`.id IN ( SELECT object_id as id FROM ' . TABLE_PREFIX . 'custom_property_values cpv WHERE ';
             $custom_cond .= ' cpv.custom_property_id = ' . array_var($condCp, 'custom_property_id');
             if (array_var($condCp, 'condition') == 'like' || array_var($condCp, 'condition') == 'not like') {
                 $value = '%' . $value . '%';
             }
             if ($cp->getType() == 'date') {
                 $dtValue = DateTimeValueLib::dateFromFormatAndString($dateFormat, $value);
                 $value = $dtValue->format('Y-m-d H:i:s');
             }
             if (array_var($condCp, 'condition') != '%') {
                 if ($cp->getType() == 'numeric') {
                     $custom_cond .= ' AND cpv.value ' . array_var($condCp, 'condition') . ' ' . mysql_real_escape_string($value);
                 } else {
                     $custom_cond .= ' AND cpv.value ' . array_var($condCp, 'condition') . ' "' . mysql_real_escape_string($value) . '"';
                 }
             } else {
                 $custom_cond .= ' AND cpv.value like "%' . mysql_real_escape_string($value) . '"';
             }
             $custom_cond .= ')';
         }
     }
     switch ($timeslot_type) {
         case 0:
             //Task timeslots
             $from = "`" . TABLE_PREFIX . "timeslots` AS `ts`, `" . TABLE_PREFIX . "project_tasks` AS `pt`, `" . TABLE_PREFIX . "projects` AS `pr`, `" . TABLE_PREFIX . "workspace_objects` AS `wo`";
             $conditions = " WHERE `ts`.`object_manager` = 'ProjectTasks'  AND `pt`.`id` = `ts`.`object_id` AND `pt`.`trashed_on` = " . DB::escape(EMPTY_DATETIME) . " AND `pt`.`archived_by_id` = 0 AND `wo`.`object_manager` = 'ProjectTasks' AND `wo`.`object_id` = `ts`.`object_id` AND `wo`.`workspace_id` = `pr`.`id`";
             //Project condition
             $conditions .= $workspacesCSV ? ' AND `pr`.`id` IN (' . $workspacesCSV . ')' : '';
             if ($custom) {
                 $commonConditions .= $custom_cond;
             }
             if ($object_subtype) {
                 $conditions .= " AND `pt`.`object_subtype`={$object_subtype}";
             }
             $sql = $select . $preFrom . $from . $postFrom . $conditions . $commonConditions;
             break;
         case 1:
             //Time timeslots
             $from = "`" . TABLE_PREFIX . "timeslots` AS `ts`, `" . TABLE_PREFIX . "projects` AS `pr`";
             $conditions = " WHERE `ts`.`object_manager` = 'Projects'";
             $conditions .= $workspacesCSV ? ' AND `ts`.`object_id` IN (' . $workspacesCSV . ") AND `ts`.`object_id` = `pr`.`id`" : " AND `ts`.`object_id` = `pr`.`id`";
             $sql = $select . $preFrom . $from . $postFrom . $conditions . $commonConditions;
             break;
         case 2:
             //All timeslots
             $from1 = "`" . TABLE_PREFIX . "timeslots` AS `ts`, `" . TABLE_PREFIX . "project_tasks` AS `pt`, `" . TABLE_PREFIX . "projects` AS `pr`, `" . TABLE_PREFIX . "workspace_objects` AS `wo`";
             $from2 = "`" . TABLE_PREFIX . "timeslots` AS `ts`, `" . TABLE_PREFIX . "projects` AS `pr`";
             $conditions1 = " WHERE `ts`.`object_manager` = 'ProjectTasks'  AND `pt`.`id` = `ts`.`object_id` AND `pt`.`trashed_on` = " . DB::escape(EMPTY_DATETIME) . " AND `pt`.`archived_by_id` = 0 AND `wo`.`object_manager` = 'ProjectTasks' AND `wo`.`object_id` = `ts`.`object_id` AND `wo`.`workspace_id` = `pr`.`id`";
             //Project condition
             $conditions1 .= $workspacesCSV ? ' AND `pr`.`id` IN (' . $workspacesCSV . ')' : '';
             if ($object_subtype) {
                 $conditions1 .= " AND `pt`.`object_subtype`={$object_subtype}";
             }
             $conditions2 = " WHERE `object_manager` = 'Projects'";
             $conditions2 .= $workspacesCSV ? ' AND `ts`.`object_id` IN (' . $workspacesCSV . ") AND `ts`.`object_id` = `pr`.`id`" : " AND `ts`.`object_id` = `pr`.`id`";
             $sql = $select . $preFrom . $from1 . $postFrom . $conditions1 . $commonConditions . $custom_cond . ' UNION ' . $select . $preFrom . $from2 . $postFrom . $conditions2 . $commonConditions;
             break;
         default:
             throw new Error("Timeslot type not recognised: " . $timeslot_type);
     }
     //Group by
     $wsCount = 0;
     $sql .= ' ORDER BY ';
     if (is_array($group_by)) {
         foreach ($group_by as $gb) {
             switch ($gb) {
                 case 'project_id':
                     $sql .= "`wsName" . $wsCount . "` ASC, ";
                     $wsCount++;
                     break;
                 case 'id':
                 case 'priority':
                 case 'milestone_id':
                 case 'state':
                     if ($timeslot_type == 0) {
                         $sql .= "`pt`.`{$gb}` ASC, ";
                     }
                     break;
                 default:
                     if (is_string($gb) && trim($gb) != '') {
                         $sql .= "`{$gb}` ASC, ";
                     }
                     break;
             }
         }
     }
     //Order by
     if (is_array($order_by)) {
         foreach ($order_by as $ob) {
             if (is_string($ob) && trim($ob) != '') {
                 $sql .= "`{$ob}` ASC, ";
             }
         }
     }
     $sql .= " `start_time`";
     if ($limit > 0 && $offset > 0) {
         $sql .= " LIMIT {$offset}, {$limit}";
     }
     $timeslots = array();
     $rows = DB::executeAll($sql);
     if (is_array($rows)) {
         foreach ($rows as $row) {
             $tsRow = array("ts" => Timeslots::instance()->loadFromRow($row));
             for ($i = 0; $i < $wslevels; $i++) {
                 $tsRow["wsId" . $i] = $row["wsId" . $i];
             }
             $timeslots[] = $tsRow;
         }
         // foreach
     }
     // if
     return count($timeslots) ? $timeslots : null;
 }
 /**
  * List custom properties
  *
  * @access public
  * @param void
  * @return null
  */
 function custom_properties()
 {
     if (!logged_user()->isCompanyAdmin(owner_company())) {
         flash_error(lang('no access permissions'));
         ajx_current("empty");
         return;
     }
     // if
     tpl_assign('object_types', array('<option value="" selected>' . lang('select one') . '</option>', '<option value="Companies">' . lang('company') . '</option>', '<option value="Contacts">' . lang('contact') . '</option>', '<option value="MailContents">' . lang('email type') . '</option>', '<option value="ProjectEvents">' . lang('events') . '</option>', '<option value="ProjectFiles">' . lang('file') . '</option>', '<option value="ProjectMilestones">' . lang('milestone') . '</option>', '<option value="ProjectMessages">' . lang('message') . '</option>', '<option value="ProjectTasks">' . lang('task') . '</option>', '<option value="Users">' . lang('user') . '</option>', '<option value="ProjectWebPages">' . lang('webpage') . '</option>', '<option value="Projects">' . lang('workspace') . '</option>'));
     $custom_properties = array_var($_POST, 'custom_properties');
     $obj_type = array_var($_POST, 'objectType');
     if (is_array($custom_properties)) {
         try {
             DB::beginWork();
             foreach ($custom_properties as $id => $data) {
                 $new_cp = new CustomProperty();
                 if ($data['id'] != '') {
                     $new_cp = CustomProperties::getCustomProperty($data['id']);
                 }
                 if ($data['deleted'] == "1") {
                     $new_cp->delete();
                     continue;
                 }
                 $new_cp->setObjectType($obj_type);
                 $new_cp->setName($data['name']);
                 $new_cp->setType($data['type']);
                 $new_cp->setDescription($data['description']);
                 if ($data['type'] == 'list') {
                     $values = array();
                     $list = explode(",", $data['values']);
                     foreach ($list as $l) {
                         $values[] = trim($l);
                     }
                     $value = implode(",", $values);
                     $new_cp->setValues($value);
                 } else {
                     $new_cp->setValues($data['values']);
                 }
                 if ($data['type'] == 'boolean') {
                     $new_cp->setDefaultValue(isset($data['default_value_boolean']));
                 } else {
                     $new_cp->setDefaultValue($data['default_value']);
                 }
                 $new_cp->setIsRequired(isset($data['required']));
                 $new_cp->setIsMultipleValues(isset($data['multiple_values']));
                 $new_cp->setOrder($id);
                 $new_cp->setVisibleByDefault(isset($data['visible_by_default']));
                 $new_cp->save();
                 if (is_array(array_var($data, 'applyto'))) {
                     $applyto = array_var($data, 'applyto');
                     foreach ($applyto as $co_type => $value) {
                         if ($value == 'true') {
                             if (!CustomPropertiesByCoType::findById(array('co_type_id' => $co_type, 'cp_id' => $new_cp->getId()))) {
                                 $obj = new CustomPropertyByCoType();
                                 $obj->setCoTypeId($co_type);
                                 $obj->setCpId($new_cp->getId());
                                 $obj->save();
                             }
                         } else {
                             $obj = CustomPropertiesByCoType::findById(array('co_type_id' => $co_type, 'cp_id' => $new_cp->getId()));
                             if ($obj) {
                                 $obj->delete();
                             }
                         }
                     }
                 }
             }
             DB::commit();
             flash_success(lang('custom properties updated'));
             ajx_current('back');
         } catch (Exception $ex) {
             DB::rollback();
             flash_error($ex->getMessage());
         }
     }
 }