diff --git a/include/class.attachment.php b/include/class.attachment.php index 15f3fd9b1dec6de619247e1158771a73434ba797..bcda6d08af5d757c01b691b78a29b28f03def623 100644 --- a/include/class.attachment.php +++ b/include/class.attachment.php @@ -108,15 +108,23 @@ extends InstrumentedList { */ function keepOnlyFileIds($ids, $inline=false, $lang=false) { if (!$ids) $ids = array(); - $new = array_fill_keys($ids, 1); + $new = array_flip($ids); foreach ($this as $A) { if (!isset($new[$A->file_id]) && $A->lang == $lang && $A->inline == $inline) // Not in the $ids list, delete $this->remove($A); unset($new[$A->file_id]); } - // Everything remaining in $new is truly new - $this->upload(array_keys($new), $inline, $lang); + $attachments = array(); + // Format $new for upload() with new name + foreach ($new as $id=>$name) { + $attachments[] = array( + 'id' => $id, + 'name' => $name + ); + } + // Everything remaining in $attachments is truly new + $this->upload($attachments, $inline, $lang); } function upload($files, $inline=false, $lang=false) { diff --git a/include/class.filter.php b/include/class.filter.php index 1827342284a3bab796bc1db2244dd53c527e0e0b..690a97e62f7a2ea852d69583ab5d20ebe757bf25 100644 --- a/include/class.filter.php +++ b/include/class.filter.php @@ -265,7 +265,7 @@ class Filter { 'starts' => array('stripos', 0), 'ends' => array('iendsWith', true), 'match' => array('pregMatchB', 1), - 'not_match' => array('pregMatchB', null, 0), + 'not_match' => array('pregMatchB', null, 1), ); $match = false; diff --git a/include/class.format.php b/include/class.format.php index 96764f2027126caa966f0bcad2b3119ff83030ef..05d8699881bfb67ea117b916bb22aa8f45fb8f96 100644 --- a/include/class.format.php +++ b/include/class.format.php @@ -907,17 +907,10 @@ class Format { return sprintf($timeDiff >= 0 ? __('%d hours ago') : __('in %d hours'), $absTimeDiff / 3600); } - // within 2 days - $days2 = 2 * 86400; - if ($absTimeDiff < $days2) { - // XXX: yesterday / tomorrow? - return $absTimeDiff >= 0 ? __('yesterday') : __('tomorrow'); - } - // within 29 days $days29 = 29 * 86400; if ($absTimeDiff < $days29) { - return sprintf($timeDiff >= 0 ? __('%d days ago') : __('in %d days'), $absTimeDiff / 86400); + return sprintf($timeDiff >= 0 ? __('%d days ago') : __('in %d days'), round($absTimeDiff / 86400)); } // within 60 days diff --git a/include/class.forms.php b/include/class.forms.php index 1c5700b5278a7e1c27bdd446481e0869e9959e37..1915257b7faf6d3c38480545781f7aca7ffbe821 100644 --- a/include/class.forms.php +++ b/include/class.forms.php @@ -3425,10 +3425,10 @@ class FileUploadField extends FormField { function display($value) { $links = array(); - foreach ($this->getFiles() as $f) { + foreach ($this->getAttachments() as $a) { $links[] = sprintf('<a class="no-pjax" href="%s">%s</a>', - Format::htmlchars($f->file->getDownloadUrl()), - Format::htmlchars($f->file->name)); + Format::htmlchars($a->file->getDownloadUrl()), + Format::htmlchars($a->getFilename())); } return implode('<br/>', $links); } @@ -4382,7 +4382,7 @@ class FileUploadWidget extends Widget { function($t) { return strpos($t, '/') !== false; } ); $maxfilesize = ($config['size'] ?: 1048576) / 1048576; - $files = $F = array(); + $files = array(); $new = array_fill_keys($this->field->getClean(), 1); //get file ids stored in session when creating tickets/tasks from thread @@ -4391,25 +4391,24 @@ class FileUploadWidget extends Widget { $new = array_fill_keys($_SESSION[':form-data'][$this->field->get('name')], 1); foreach ($attachments as $a) { - $F[] = $a->file; unset($new[$a->file_id]); } // Add in newly added files not yet saved (if redisplaying after an // error) if ($new) { - $F = array_merge($F, AttachmentFile::objects() - ->filter(array('id__in' => array_keys($new))) + $attachments = array_merge($attachments, GenericAttachment::objects() + ->filter(array('file_id__in' => array_keys($new))) ->all() ); } - foreach ($F as $file) { + foreach ($attachments as $att) { $files[] = array( - 'id' => $file->getId(), - 'name' => $file->getName(), - 'type' => $file->getType(), - 'size' => $file->getSize(), - 'download_url' => $file->getDownloadUrl(), + 'id' => $att->file->getId(), + 'name' => $att->getFilename(), + 'type' => $att->file->getType(), + 'size' => $att->file->getSize(), + 'download_url' => $att->file->getDownloadUrl(), ); } ?><div id="<?php echo $id; diff --git a/include/class.pdf.php b/include/class.pdf.php index cc395f388999d1230b0da195747e9a9990ee22df..10398fd65d171a23231795f32dbb2288014d08da 100644 --- a/include/class.pdf.php +++ b/include/class.pdf.php @@ -90,6 +90,7 @@ class Ticket2PDF extends mPDFWithLocalImages return; $html = ob_get_clean(); + $this->SetAutoFont(); $this->WriteHtml($html, 0, true, true); } } @@ -119,6 +120,7 @@ class Task2PDF extends mPDFWithLocalImages { ob_start(); include STAFFINC_DIR.'templates/task-print.tmpl.php'; $html = ob_get_clean(); + $this->SetAutoFont(); $this->WriteHtml($html, 0, true, true); } diff --git a/include/class.queue.php b/include/class.queue.php index dfa3846425c8d86c867d491f52c2b75be4fafb1e..6b4c1adc1cab13613ffd170f80a6d568e4cf5518 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -246,6 +246,7 @@ class CustomQueue extends VerySimpleModel { function getCurrentSearchFields($source=array(), $criteria=array()) { static $basic = array( 'Ticket' => array( + 'status__id', 'status__state', 'dept_id', 'assignee', @@ -937,10 +938,14 @@ class CustomQueue extends VerySimpleModel { return $agent && $this->isPrivate() && $this->checkOwnership($agent); } + function isSaved() { + return true; + } + function ignoreVisibilityConstraints(Staff $agent) { - // For saved searches (not queues), some staff can have a permission to + // For searches (not queues), some staff can have a permission to // see all records - return (!$this->isASubQueue() + return ($this->isASearch() && $this->isOwner($agent) && $agent->canSearchEverything()); } @@ -994,6 +999,10 @@ class CustomQueue extends VerySimpleModel { return $this->hasFlag(self::FLAG_QUEUE); } + function isASearch() { + return !$this->isAQueue() || !$this->isSaved(); + } + function isPrivate() { return !$this->isAQueue() && !$this->isPublic() && $this->staff_id; @@ -1992,7 +2001,16 @@ extends VerySimpleModel { // These getters fetch data from the annotated overlay from the // queue_column table function getQueue() { - return $this->_queue ?: $this->queue; + if (!isset($this->_queue)) { + $queue = $this->queue; + + if (!$queue && ($queue_id = $this->queue_id)) + $queue = CustomQueue::lookup($queue_id); + + $this->_queue = $queue; + } + + return $this->_queue; } /** * If a column is inherited into a child queue and there are conditions @@ -2239,7 +2257,7 @@ extends VerySimpleModel { if ($include_queue && ($q = $this->getQueue()) && ($q_conds = $q->getConditions()) ) { - $this->_conditions = array_merge($this->_conditions, $q_conds); + $this->_conditions = array_merge($q_conds, $this->_conditions); } } return $this->_conditions; diff --git a/include/class.role.php b/include/class.role.php index 0b34853220e1ea29bb2c607a646b1063c50efac9..7898bb9b67d424c3bbbb468c5a06bf44a7c24a2d 100644 --- a/include/class.role.php +++ b/include/class.role.php @@ -321,6 +321,16 @@ class RolePermission { } static function allPermissions() { + static $sorted = false; + + if (!$sorted) { + // Sort permissions in alphabetical order + foreach (static::$_permissions as $k => $v) { + asort(static::$_permissions[$k]); + } + $sorted = true; + } + return static::$_permissions; } diff --git a/include/class.search.php b/include/class.search.php index be17902260dd53b308ffdd3a47ad30156ac7d811..e4c6111b5fe313438577394dcbae5cebf271ec3a 100644 --- a/include/class.search.php +++ b/include/class.search.php @@ -912,6 +912,10 @@ extends SavedSearch { return false; } + function isOwner(Staff $staff) { + return $this->ht['staff_id'] == $staff->getId(); + } + function checkAccess($staff) { return true; } @@ -921,6 +925,7 @@ extends SavedSearch { } function load($key) { + global $thisstaff; if (strpos($key, 'adhoc') === 0) list(, $key) = explode(',', $key, 2); @@ -933,6 +938,7 @@ extends SavedSearch { $queue = new AdhocSearch(array( 'id' => "adhoc,$key", 'root' => 'T', + 'staff_id' => $thisstaff->getId(), 'title' => __('Advanced Search'), )); $queue->config = $config; diff --git a/include/mpdf/ttfonts/XB Riyaz.ttf b/include/mpdf/ttfonts/XB Riyaz.ttf new file mode 100644 index 0000000000000000000000000000000000000000..80e15803dc0aa7b0d8758e0e26793d10fa484ef1 Binary files /dev/null and b/include/mpdf/ttfonts/XB Riyaz.ttf differ diff --git a/include/mpdf/ttfonts/XB RiyazBd.ttf b/include/mpdf/ttfonts/XB RiyazBd.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e6cf58f93bb2d2093a9b858ab74393416537c46b Binary files /dev/null and b/include/mpdf/ttfonts/XB RiyazBd.ttf differ diff --git a/include/mpdf/ttfonts/XB RiyazBdIt.ttf b/include/mpdf/ttfonts/XB RiyazBdIt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..19fba7887e965c9f331479862c53ec97f4caf22e Binary files /dev/null and b/include/mpdf/ttfonts/XB RiyazBdIt.ttf differ diff --git a/include/mpdf/ttfonts/XB RiyazIt.ttf b/include/mpdf/ttfonts/XB RiyazIt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..cc9cc3ab2a7da6ee26b3d78b18f2c18de42474a4 Binary files /dev/null and b/include/mpdf/ttfonts/XB RiyazIt.ttf differ diff --git a/include/mpdf/ttfonts/XB Zar Bd.ttf b/include/mpdf/ttfonts/XB Zar Bd.ttf new file mode 100644 index 0000000000000000000000000000000000000000..52a2e38f977989124e657b0d197cf78b5af7a8d8 Binary files /dev/null and b/include/mpdf/ttfonts/XB Zar Bd.ttf differ diff --git a/include/mpdf/ttfonts/XB Zar BdIt.ttf b/include/mpdf/ttfonts/XB Zar BdIt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a7f19d97b7e85f5fa95ad99c58a6a847da78bd8e Binary files /dev/null and b/include/mpdf/ttfonts/XB Zar BdIt.ttf differ diff --git a/include/mpdf/ttfonts/XB Zar It.ttf b/include/mpdf/ttfonts/XB Zar It.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4365d1d78ec95f847d650c89f65c91105df71dd8 Binary files /dev/null and b/include/mpdf/ttfonts/XB Zar It.ttf differ diff --git a/include/mpdf/ttfonts/XB Zar.ttf b/include/mpdf/ttfonts/XB Zar.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7a168b6ee5eb76c3ef3731017c604e25ce30b995 Binary files /dev/null and b/include/mpdf/ttfonts/XB Zar.ttf differ diff --git a/include/staff/ticket-tasks.inc.php b/include/staff/ticket-tasks.inc.php index aa765aef5cd39eebf3f68f53f4d02227f5ca4641..ec19431ac78f1bd772377e31212e1d31be32bab0 100644 --- a/include/staff/ticket-tasks.inc.php +++ b/include/staff/ticket-tasks.inc.php @@ -79,9 +79,13 @@ if ($count) { ?> $id = $task->getId(); $access = $task->checkStaffPerm($thisstaff); $assigned=''; - if ($task->staff) - $assigned=sprintf('<span class="Icon staffAssigned">%s</span>', - Format::truncate($task->staff->getName(),40)); + if ($task->staff || $task->team) { + $assigneeType = $task->staff ? 'staff' : 'team'; + $icon = $assigneeType == 'staff' ? 'staffAssigned' : 'teamAssigned'; + $assigned=sprintf('<span class="Icon %s">%s</span>', + $icon, + Format::truncate($task->getAssigned(),40)); + } $status = $task->isOpen() ? '<strong>open</strong>': 'closed'; diff --git a/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php b/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php index 619dfa4e98cab1a4619e4737d4fbd708d1a8ea0e..509c7b2f8284c1e3faae2268401f477496026988 100644 --- a/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php +++ b/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php @@ -23,14 +23,16 @@ class QueueSortCreator extends MigrationTask { foreach ($old ?: array() as $row) { // Only save entries with "valid" criteria if (!$row['title'] - || !($config = JsonDataParser::parse($row['config'], true)) - || !($criteria = self::isolateCriteria($config))) + || !($config = JsonDataParser::parse($row['config'], + true))) continue; $row['root'] = 'T'; // Ticket Queue - $row['flags'] = 0; // Saved Search - $row['config'] = JsonDataEncoder::encode(array( - 'criteria' => $criteria, 'conditions' => array())); + $row['flags'] = 16; // Saved Search + if (($criteria = self::isolateCriteria($config))) + $row['config'] = JsonDataEncoder::encode(array( + 'criteria' => $criteria, + 'conditions' => array())); CustomQueue::__create(array_intersect_key($row, array_flip( array('staff_id', 'title', 'config', 'flags', 'root', 'created', 'updated')))); diff --git a/scp/canned.php b/scp/canned.php index ae8ded5fe76017b4a65b3c75929088e4110127b6..88fdf4b81360e4b49b1b7208b14e56e723652449 100644 --- a/scp/canned.php +++ b/scp/canned.php @@ -37,6 +37,13 @@ $canned_form = new SimpleForm(array( )), )); +// Set fields' attachments so exsting files stay put +if ($canned + && $canned->attachments + && ($attachments = $canned_form->getField('attachments'))) { + $attachments->setAttachments($canned->attachments); +} + if ($_POST) { switch(strtolower($_POST['do'])) { case 'update': diff --git a/scp/faq.php b/scp/faq.php index 310809947f82b90d7b2f4238802aecda6a8b36a4..8b948c1421ff0b51e044410ce3f9d8ba0b296cb5 100644 --- a/scp/faq.php +++ b/scp/faq.php @@ -48,6 +48,21 @@ if ($langs = $cfg->getSecondaryLanguages()) { $faq_form = new SimpleForm($form_fields, $_POST); +// Set fields' attachments so exsting files stay put +if ($faq + && $faq->getAttachments()->window(array('inline' => false)) + && ($common_attachments = $faq_form->getField('attachments'))) { + // Common attachments + $common_attachments->setAttachments($faq->getAttachments()->window(array('inline' => false))); +} +if ($langs && $faq) { + // Multi-lingual system + foreach ($langs as $lang) { + $attachments = $faq_form->getField('attachments.'.$lang); + $attachments->setAttachments($faq->getAttachments($lang)->window(array('inline' => false))); + } +} + if ($_POST) { $errors=array(); // General attachments @@ -126,21 +141,6 @@ if ($_POST) { } } -else { - // Not a POST — load database-backed attachments to attachment fields - if ($langs && $faq) { - // Multi-lingual system - foreach ($langs as $lang) { - $attachments = $faq_form->getField('attachments.'.$lang); - $attachments->setAttachments($faq->getAttachments($lang)->window(array('inline' => false))); - } - } - if ($faq) { - // Common attachments - $attachments = $faq_form->getField('attachments'); - $attachments->setAttachments($faq->getAttachments()->window(array('inline' => false))); - } -} $inc='faq-categories.inc.php'; //FAQs landing page. if($faq) { diff --git a/setup/test/tests/test.git-conflicts.php b/setup/test/tests/test.git-conflicts.php new file mode 100644 index 0000000000000000000000000000000000000000..5aa27bfb951a0d43d5eb8df02fcdbb31b5e05697 --- /dev/null +++ b/setup/test/tests/test.git-conflicts.php @@ -0,0 +1,27 @@ +<?php +require_once "class.test.php"; + +class GitConflicts extends Test { + var $name = "Git Conflicts Checks"; + + function testFindGitConflicts() { + $regex = '/^[\t ]*?<{3,} ?HEAD[\t ]*?|^[\t ]*?>{3,}[\t ]*?/m'; + foreach ($this->getAllScripts('*') as $s) { + $matches = array(); + $content = file_get_contents($s); + if (preg_match_all($regex, + $content, $matches, + PREG_OFFSET_CAPTURE) > 0) { + foreach ($matches[0] as $match) { + $this->fail( + $s, + $this->line_number_for_offset($content, $match[1]), + trim($match[0])); + } + } + else $this->pass(); + } + } +} +return 'GitConflicts'; +?>