public function onSolrQuery(&$p) { $result =& $p['result']; $data =& $result['data']; $actionLogIds = array(); $comments = new Objects\Plugins\Comments(); //format ago date and collect log action ids foreach ($data as &$doc) { $la = Objects::getCachedObject($doc['id'])->getLastActionData(); $la['agoText'] = Util\formatAgoTime($la['time']); $la['uids'] = array_reverse(array_keys($la['users'])); $doc['lastAction'] = $la; $actionLogId = $la['users'][$la['uids'][0]]; $doc['comments'] = $comments->getData($doc['id']); $actionLogIds[$actionLogId] =& $doc; } $logRecs = DM\Log::getRecords(array_keys($actionLogIds)); foreach ($logRecs as $r) { $d = Util\jsonDecode($r['data']); $obj = Objects::getCachedObject($actionLogIds[$r['id']]['id']); $diff = $obj->getDiff($d); if (!empty($diff)) { $html = ''; foreach ($diff as $fn => $fv) { $html .= "<tr><th>{$fn}</th><td>{$fv}</td></tr>"; } $actionLogIds[$r['id']]['diff'] = "<table class=\"as-diff\">{$html}</table>"; } } }
protected function getObjectClass() { $rez = null; if (empty($this->objectClass) && !empty($this->id)) { $this->objectClass = \CB\Objects::getCachedObject($this->id); $rez =& $this->objectClass; } return $rez; }
public function getData($id = false) { $rez = array('success' => true); parent::getData($id); $preview = Objects::getPreview($this->id); $obj = Objects::getCachedObject($this->id); if (empty($obj)) { return $rez; } $data = $obj->getData(); if (!empty($preview)) { $rez['data'] = array('preview' => $preview); } if (!empty($data)) { if (!empty($data['pids'])) { $path = explode(',', $data['pids']); array_pop($path); $rez['data']['pids'] = $rez['data']['path'] = implode('/', $path); $arr = array(&$rez['data']); Search::setPaths($arr); } foreach ($data as $k => $v) { if (in_array($k, array('id', 'template_id', 'date_end', 'cid', 'uid', 'cdate', 'udate'))) { if (in_array($k, array('date', 'date_end', 'cdate', 'udate'))) { $v = Util\dateMysqlToISO($v); } $rez['data'][$k] = $v; //add ago udate text if (in_array($k, array('cdate', 'udate'))) { $rez['data'][$k . '_ago_text'] = Util\formatAgoTime($v); } } } $rez['data']['name'] = $obj->getName(); } $rez['data']['can'] = $obj->getActionFlags(); //set status info for tasks if not active if ($obj->getType() == 'task') { $d =& $rez['data']; $d['status'] = ''; switch ($obj->getStatus()) { case Objects\Task::$STATUS_ACTIVE: break; case Objects\Task::$STATUS_CLOSED: //just add title css class and continue with default $d['titleCls'] = 'task-completed'; // break; // break; default: $d['status'] = $obj->getStatusText(); $d['statusCls'] = $obj->getStatusCSSClass(); } } return $rez; }
/** * update comment * @param array $p optional properties. If not specified then $this-data is used * @return boolean */ public function update($p = false) { //disable default log from parent Object class //we'll set comments add as comment action for parent Config::setFlag('disableActivityLog', true); $rez = parent::update($p); Config::setFlag('disableActivityLog', false); $p =& $this->data; $this->logAction('comment_update', array('new' => Objects::getCachedObject($p['pid']), 'comment' => $p['data']['_title'])); return $rez; }
/** * create method * @return void */ public function create($p = false) { //disable default log from parent Object class //we'll set comments add as comment action for parent $disableLogFlag = \CB\Config::getFlag('disableActivityLog'); \CB\Config::setFlag('disableActivityLog', true); $rez = parent::create($p); \CB\Config::setFlag('disableActivityLog', $disableLogFlag); $p =& $this->data; $this->parentObj = Objects::getCachedObject($p['pid']); $this->updateParentFollowers(); $this->logAction('file_upload', array('file' => array('id' => $p['id'], 'name' => $p['name']))); return $rez; }
/** * update objects custom data * @return boolean */ protected function updateCustomData() { parent::updateCustomData(); /* saving template data to templates and templates_structure tables */ $p =& $this->data; $data = $this->collectCustomModelData(); $data['id'] = $this->id; $data['template_id'] = $this->detectParentTemplate(); DM\TemplatesStructure::update($data); if ($this->isSolrConfigUpdated()) { $tpl = \CB\Objects::getCachedObject($data['template_id']); $tpl->setSysDataProperty('solrConfigUpdated', true); } }
public function getData($id = false) { $rez = array('success' => true); parent::getData($id); $o = Objects::getCachedObject($this->id); $data = $o->getData(); //show current version only if have more other versions if (!empty($data['versions'])) { $data['ago_text'] = Util\formatAgoTime($data['cdate']); $data['user'] = User::getDisplayName($data['oid'], true); $data['cls'] = 'sel'; $rez['data'] = array($data); } return $rez; }
public function getData($id = false) { $rez = array('success' => true); parent::getData($id); // echo $this->id.'!!'; $o = Objects::getCachedObject($this->id); $data = $o->getData(); if (!empty($data['versions'])) { $rez['data'] = $data['versions']; foreach ($rez['data'] as &$version) { $version['ago_text'] = Util\formatAgoTime($version['cdate']); $version['user'] = User::getDisplayName($version['cid'], true); } } return $rez; }
/** * This function is designed to prepeare all necessary nodes properties for graph rendering. * * used properties for graph: * id * ,$this->labelField - will be used as node label * ,hint = $this->hintField * ,date = $this->dateField * ,shape - node shape * ,style - custom node style * ,fillcolor * ,margin * ,penwith * ,leftSideNodes - for decisions with associated violations * ,rightSideNodes */ private function prepareGraphNodes(&$nodesArray) { for ($i = 0; $i < sizeof($nodesArray); $i++) { /* define a reference for easy use */ $node =& $nodesArray[$i]; /* adjust title field if needed */ $t = trim($node[$this->labelField]); $node[$this->hintField] = nl2br($t); $node[$this->labelField] = strlen($t) > 30 ? substr($t, 0, 30) . ' ...' : $t; /* adjusting date field format */ if (!empty($node[$this->dateField])) { $node[$this->dateField] = substr($node[$this->dateField], 0, 10); $node[$this->dateField] = implode('.', array_reverse(explode('-', $node[$this->dateField]))); } /* end of adjusting date field format */ /* SETTING NODE STYLE (SHAPE AND COLOR) */ /* getting node object */ $o = Objects::getCachedObject($node['id']); $node['style'] = 'filled'; $color = $o->getFieldValue('color', 0)['value']; if (!empty($color)) { $t = $o->getTemplate(); $color = $t->formatValueForDisplay($t->getField('color'), $color, false); $node['fillcolor'] = @$this->colors[$color]; } else { $node['fillcolor'] = $this->colors['gray']; } $inLinks = Util\toNumericArray($o->getFieldValue('in_links', 0)['value']); $outLinks = Util\toNumericArray($o->getFieldValue('out_links', 0)['value']); foreach ($inLinks as $inNode) { $this->links[$inNode][$node['id']] = 1; } foreach ($outLinks as $outNode) { $this->links[$node['id']][$outNode] = 1; } /* setting node shape */ $node['shape'] = "box"; //set default shape // $this->switchNodeShowTitles($node); } }
/** * just a test method to upload a file and execute methods from * DataModel to check the result * @return void */ public function testDataModelFilesMethods() { $api = new Api\Files(); $fn = tempnam(sys_get_temp_dir(), 'cb_test'); file_put_contents($fn, 'testing'); $data = array('pid' => 1, 'localFile' => $fn, 'oid' => 1); $rez = $api->upload($data); $this->assertTrue($rez['success'], 'Upload test file failed: ' . $fn); $fileData = $rez['data']['file']; $id = $fileData['id']; $rez = DM\Files::getContentIds($id); $this->assertTrue(!empty($rez[$id]), 'Cant get content id'); $rez = DM\Files::getContentPaths($id); $this->assertTrue(!empty($rez[$id]), 'Cant get content path'); //delete the file from system and check if same actions return empty results $f = Objects::getCachedObject($id); $f->delete(true); // permanently delete unset($f); $rez = DM\Files::getContentIds($id); $this->assertTrue(empty($rez[$id]), 'Obtaining content id for a permanently deleted file'); $rez = DM\Files::getContentPaths($id); $this->assertTrue(empty($rez[$id]), 'Obtaining content path for a permanently deleted file'); }
/** * update create menus * @return void */ protected function updateCreateMenus() { $rootId = \CB\Browser::getRootFolderId(); $pid = Objects::getChildId($rootId, 'System'); if (!empty($pid)) { $pid = Objects::getChildId($pid, 'Menus'); if (!empty($pid)) { $res = DB\dbQuery('SELECT id FROM tree WHERE pid = $1 AND dstatus = 0', $pid) or die(DB\dbQueryError()); if ($r = $res->fetch_assoc()) { $o = Objects::getCachedObject($r['id']); $d = $o->getData(); $d['data']['menu'] = $this->templateIds['Case'] . ',' . $this->templateIds['Contact'] . ',' . $this->templateIds['Organization'] . ',' . $d['data']['menu']; $o->update($d); } $res->close(); } } }
/** * get parent object * @return object | null */ protected function getParentObject() { if (empty($this->parentObj)) { $this->parentObj = null; if (!empty($this->data['pid'])) { $this->parentObj = \CB\Objects::getCachedObject($this->data['pid']); } } return $this->parentObj; }
/** * update file * @param array $p optional properties. If not specified then $this-data is used * @return boolean */ public function update($p = false) { //disable default log from parent Object class Config::setFlag('disableActivityLog', true); $rez = parent::update($p); Config::setFlag('disableActivityLog', false); $p =& $this->data; // log the action $logParams = array('type' => 'file_update', 'new' => Objects::getCachedObject($p['pid']), 'file' => array('id' => $p['id'], 'name' => $p['name'])); Log::add($logParams); return $rez; }
/** * test notifications module * * @return [type] [description] */ public function testNotifications() { //check if everything is prepeared $this->assertTrue(sizeof($this->userIds) > 3, 'Less than 4 users created'); $this->assertTrue(sizeof($this->objectIds) > 2, 'Less than 3 tasks created'); //add a comment to obj 1 with user 1 referencing user 2 $firstUserId = $this->userIds[0]; $secondUserId = $this->userIds[1]; $thirdUserId = $this->userIds[2]; $forthUserId = $this->userIds[3]; $rootUserId = $this->oldValues['user_id']; $pid = $this->objectIds[0]; $commentData = array('pid' => $pid, 'template_id' => 9, 'data' => array('_title' => 'Hello to user @bow!')); $_SESSION['user']['id'] = $firstUserId; /* make a check - user should be denied to add comments */ try { $commentId = $this->createObject($commentData); } catch (\Exception $e) { $msg = $e->getMessage(); $this->assertTrue($msg == 'Access is denied', $msg); } $_SESSION['user']['id'] = $rootUserId; $this->addAllowSecurityRule(); // try again adding a comment, // now it should work without access exceptions $_SESSION['user']['id'] = $firstUserId; $commentId = $this->createObject($commentData); $this->assertTrue(is_numeric($commentId), 'Wrong comment ID.'); //check notifications for user bow, //he should receive 2 new notifications from root and andrew $this->assertTrue($this->checkLastNotification($secondUserId, array('user_id' => $firstUserId, 'object_id' => $pid, 'read' => 0)), 'Wrong last notification'); //check notifications for root user, he also should receive a new notification from andrew //as owner of the object $this->assertTrue($this->checkLastNotification($rootUserId, array('user_id' => $firstUserId, 'object_id' => $pid, 'read' => 0)), 'No notification for root (owner) user.'); //add comments with all 4 users and check notifications to cover //code for 3 and more users notifications grouping //and check root notifications with each comment for ($i = 0; $i < 4; $i++) { $_SESSION['user']['id'] = $this->userIds[$i]; $commentData['data']['_title'] = 'Comment from user #' . $i . '.'; $this->createObject($commentData); $this->assertTrue($this->checkLastNotification($rootUserId, array('user_id' => $this->userIds[$i], 'object_id' => $pid, 'read' => 0)), 'Wrong last notification for root from user #' . $i . '.'); } $_SESSION['user']['id'] = $rootUserId; /*-------- answer back to previous comment with root and see if notifications are created */ $commentData['data']['_title'] = 'Reply to Hellow comment.'; $commentId = $this->createObject($commentData); //check notifications for all 4 users for ($i = 0; $i < 3; $i++) { $this->assertTrue($this->checkLastNotification($this->userIds[$i], array('object_id' => $pid, 'read' => 0)), 'Wrong last notification from root for user #' . $i . '.'); } $this->checkMarkingNotificationsAsRead(); //end of big testing schema //cover for now some simple code from Notifications $this->assertTrue(\CB\Notifications::getActionDeclination('reopen', 'en') == 'reopened', 'Declination not correct for reopen.'); $this->assertTrue(\CB\Notifications::getActionDeclination('SomeWrongValue!>', 'en') == 'SomeWrongValue!>', 'Declination not correct for a wrong value.'); $this->assertTrue(\CB\Notifications::getActionDeclination('file_upload', 'en') == 'uploaded a file to', 'Declination not correct for file_upload.'); $this->assertTrue(\CB\Notifications::getActionDeclination('file_update', 'en') == 'updated a file in', 'Declination not correct for file_update.'); //update a task and delete them all $obj = \CB\Objects::getCachedObject($pid); $data = $obj->getData(); $data['data']['due_date'] = '2012-12-17T00:00:00Z'; unset($data['data']['importance']); $data['data']['description'] .= ' *update* '; $obj->update($data); foreach ($this->objectIds as $id) { $obj->delete(false); } //get unset notifications and and access functions for preparing email $recs = DM\Notifications::getUnsent(); foreach ($recs as $action) { $userData = \CB\User::getPreferences($action['to_user_id']); $sender = \CB\Notifications::getSender($action['from_user_id']); $body = \CB\Notifications::getMailBodyForAction($action, $userData); } }
/** * function to check if a user cam manage task * * This function returns true if specified user can manage/update specified task. * User can manage a task if he is Administrator, Creator of the task * or is one of the responsible task users. * * @param int $taskId id of the task to be checked * @param int $userId id of the user to be checked * @return boolean returns true in case of the user can manage the task */ public static function canManageTask($taskId, $userId = false) { $rez = false; if ($userId == false) { $userId = User::getId(); } $task = Objects::getCachedObject($taskId); $data = $task->getData(); $rez = $data['cid'] == $userId || in_array($userId, $data['sys_data']['task_u_ongoing']) || in_array($userId, $data['sys_data']['task_u_done']); if (!$rez) { $rez = Security::isAdmin($userId); } return $rez; }
/** * get mail body diff for a generic object * @param array $action * @param array $colors * @return varchar */ protected static function getActionDiffMailBody($action, $colors = false) { $rez = ''; $rows = array(); $obj = Objects::getCachedObject($action['object_id']); $tpl = $obj->getTemplate(); $ad =& $action['data']; $oldData = empty($ad['old']) ? array() : $ad['old']; $newData = empty($ad['new']) ? array() : $ad['new']; $keys = array_keys($oldData + $newData); foreach ($keys as $fieldName) { $field = $tpl->getField($fieldName); $oldValue = null; if (!empty($oldData[$fieldName])) { $oldValue = array(); foreach ($oldData[$fieldName] as $v) { $v = $tpl->formatValueForDisplay($field, $v, true); if (!empty($v)) { $oldValue[] = $v; } } $oldValue = implode('<br />', $oldValue); } $newValue = null; if (!empty($newData[$fieldName])) { $newValue = array(); foreach ($newData[$fieldName] as $v) { $v = $tpl->formatValueForDisplay($field, $v, true); if (!empty($v)) { $newValue[] = $v; } } $newValue = implode('<br />', $newValue); } $type = 'none'; if (!empty($newValue) && empty($oldValue)) { $type = 'added'; } elseif (!empty($oldValue) && empty($newValue)) { $type = 'removed'; } elseif (!empty($oldValue) && !empty($newValue) && $oldValue != $newValue) { $type = 'updated'; } $color = empty($colors[$type]) ? '' : ' style="background-color: ' . $colors[$type] . '"'; $value = empty($oldValue) ? '' : "<del>{$oldValue}</del><br />"; $value .= $newValue; if (!empty($value)) { $rows[] = '<tr><td style="vertical-align: top"><strong>' . $field['title'] . '</strong></td>' . '<td' . $color . '>' . $value . '</td></tr>'; } } if (!empty($rows)) { $rez = '<table border="1" style="border-collapse: collapse" cellpadding="3">' . '<th style="background-color: #d9d9d9">' . L\get('Property') . '</th>' . '<th style="background-color: #d9d9d9">' . L\get('Value') . '</th></tr>' . implode("\n", $rows) . '</table>'; } return $rez; }
/** * method used to implement custom logic on solr query * @param array $p search params * @return void */ public function onSolrQuery(&$p) { $this->params =& $p; $ip =& $p['inputParams']; if (@$ip['view']['type'] !== $this->fromParam) { return; } // $sp = &$p['params']; $result =& $p['result']; $view =& $result['view']; $data =& $result['data']; $rez = array(); $displayColumns = $this->getDC(); //This if remains as backward compatible, but will be removed in future commits if (!empty($displayColumns['sort'])) { $view['sort'] = $displayColumns['sort']; } //get state $stateFrom = empty($displayColumns['from']) ? 'default' : $displayColumns['from']; $state = $this->getState($stateFrom); $customColumns = $this->prepareColumnsConfig($displayColumns); //set custom display columns data if (!empty($displayColumns['data'])) { // fill custom columns data foreach ($data as &$doc) { if (!is_numeric($doc['id'])) { continue; } $obj = \CB\Objects::getCachedObject($doc['id']); if (!is_object($obj)) { \CB\debug('DisplayColumns object not found: ' . $doc['id']); continue; } $template = $obj->getTemplate(); foreach ($customColumns as $fieldName => &$col) { $templateField = $template->getField($col['fieldName']); $values = array(); if (!empty($col['solr_column_name'])) { if (isset($doc[$col['solr_column_name']]) && $col['solr_column_name'] !== $col['fieldName']) { $v = $doc[$col['solr_column_name']]; $doc[$col['fieldName']] = $v; unset($doc[$col['solr_column_name']]); $values = array($v); } if (empty($templateField)) { $templateField = array('type' => empty($col['fieldType']) ? 'varchar' : $col['fieldType'], 'name' => $col['solr_column_name'], 'title' => Util\detectTitle($col)); } } elseif (!empty($col['lookup'])) { //lookup field $values = $obj->getLookupValues($col['lookup'], $templateField); } else { //default $values = isset($doc[$col['fieldName']]) ? array($doc[$col['fieldName']]) : $obj->getFieldValue($col['fieldName']); } //populate column properties if empty if (empty($col['title'])) { $col['title'] = $templateField['title']; } if (empty($col['sortType']) && empty($col['solr_column_name'])) { switch ($templateField['type']) { case 'date': case 'datetime': $col['sortType'] = 'asDate'; break; case 'float': $col['sortType'] = 'asFloat'; break; case 'checkbox': case 'int': $col['sortType'] = 'asInt'; break; case 'html': case 'memo': case 'text': $col['sortType'] = 'asUCText'; break; case '_objects': default: $col['sortType'] = 'asUCString'; break; } } //update value from document if empty from solr query if (empty($doc[$fieldName]) || in_array($templateField['type'], array('_objects', 'time'))) { $dv = array(); foreach ($values as $value) { $value = is_array($value) ? @$value['value'] : $value; $dv[] = $template->formatValueForDisplay($templateField, $value, false); } $doc[$fieldName] = implode(', ', $dv); } } } /* remove columns without title */ foreach ($customColumns as $fieldName => &$col) { if (empty($col['title'])) { unset($customColumns[$fieldName]); } } $rez = $customColumns; } /* merge the state with display columns */ $defaultColumns = array_keys(Config::getDefaultGridViewColumns()); if (!empty($state['columns'])) { $rez = array(); foreach ($state['columns'] as $k => $c) { if (!empty($customColumns[$k])) { unset($customColumns[$k]['hidden']); $c = array_merge($customColumns[$k], $c); unset($customColumns[$k]); $rez[$k] = $c; } elseif (in_array($k, $defaultColumns)) { $rez[$k] = $c; } } if (!empty($customColumns)) { $rez = array_merge($rez, $customColumns); } } /* user clicked a column to sort by */ if (!empty($ip['userSort'])) { $view['sort'] = array('property' => $ip['sort'][0]['property'], 'direction' => $ip['sort'][0]['direction']); } elseif (!empty($state['sort'])) { $view['sort'] = $state['sort']; } /* end of get user state and merge the state with display columns */ //check grouping params if (!empty($ip['userGroup']) && !empty($ip['group'])) { $view['group'] = array('property' => $ip['sourceGroupField'], 'direction' => $ip['group']['direction']); } elseif (isset($state['group'])) { $view['group'] = $state['group']; } elseif (isset($displayColumns['group'])) { $view['group'] = $displayColumns['group']; } //analize grouping $this->analizeGrouping($p); if (!empty($rez)) { $result['DC'] = $rez; } /* check if we need to sort records using php (in case sort field is not from solr)*/ if (!empty($view['sort']) && !empty($rez[$view['sort']['property']]['localSort']) && !in_array($view['sort']['property'], $defaultColumns)) { $s =& $view['sort']; Util\sortRecordsArray($data, $s['property'], $s['direction'], empty($rez[$s['property']]['sortType']) ? 'asString' : $rez[$s['property']]['sortType']); } }
/** * set the flags for actions that could be made to the tasks by a specific or current user * @param reference $object_records * @return void */ public static function setTasksActionFlags(&$tasksDataArray, $userId = false) { $userId = $userId; // dummy codacy assignment $taskTemplates = DM\Templates::getIdsByType('task'); foreach ($tasksDataArray as &$d) { if (!in_array(@$d['template_id'], $taskTemplates) || empty($d['status'])) { continue; } $task = Objects::getCachedObject($d['id']); $d['can'] = $task->getActionFlags(); } }