mirror of https://github.com/itflow-org/itflow
Merge pull request #875 from twetech/0.1.8.2
0.1.8.2 (Scheduled tickets, and Email Improvements)
This commit is contained in:
commit
d78b667e0b
|
|
@ -25,6 +25,7 @@ require_once "calendar_event_add_modal.php";
|
|||
|
||||
require_once "calendar_add_modal.php";
|
||||
|
||||
|
||||
//loop through IDs and create a modal for each
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
|
|
@ -40,18 +41,16 @@ while ($row = mysqli_fetch_array($sql)) {
|
|||
$client_id = intval($row['event_client_id']);
|
||||
|
||||
require "calendar_event_edit_modal.php";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<?php require_once "footer.php";
|
||||
?>
|
||||
?>
|
||||
|
||||
<script src='plugins/fullcalendar/main.min.js'></script>
|
||||
|
||||
<script>
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
|
||||
|
|
@ -120,7 +119,32 @@ while ($row = mysqli_fetch_array($sql)) {
|
|||
$event_start = json_encode($row['ticket_created_at']);
|
||||
|
||||
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'orange', url: 'ticket.php?ticket_id=$event_id' },";
|
||||
}
|
||||
|
||||
//Tickets Scheduled
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN tickets ON client_id = ticket_client_id LEFT JOIN users ON ticket_assigned_to = user_id WHERE ticket_schedule IS NOT NULL");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$event_id = intval($row['ticket_id']);
|
||||
if (empty($username)) {
|
||||
$username = "Unassigned";
|
||||
} else {
|
||||
$username = $row['user_name'];
|
||||
}
|
||||
|
||||
if (strtotime($row['ticket_schedule']) < time()) {
|
||||
if ($row['ticket_status'] == 'Scheduled') {
|
||||
$event_color = "red";
|
||||
} else {
|
||||
$event_color = "green";
|
||||
}
|
||||
} else {
|
||||
$event_color = "grey";
|
||||
}
|
||||
|
||||
$event_title = json_encode($row['ticket_prefix'] . $row['ticket_number'] . " " . $row['ticket_subject'] . " [" . $username . "]");
|
||||
$event_start = json_encode($row['ticket_schedule']);
|
||||
|
||||
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'ticket.php?ticket_id=$event_id' },";
|
||||
}
|
||||
|
||||
//Vendors Added Created
|
||||
|
|
@ -148,13 +172,12 @@ while ($row = mysqli_fetch_array($sql)) {
|
|||
|
||||
],
|
||||
eventClick: function(editEvent) {
|
||||
$('#editEventModal'+editEvent.event.id).modal();
|
||||
$('#editEventModal' + editEvent.event.id).modal();
|
||||
}
|
||||
});
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Automatically set new event end date to 1 hr after start date -->
|
||||
|
|
@ -183,4 +206,4 @@ while ($row = mysqli_fetch_array($sql)) {
|
|||
// Update the end date field
|
||||
document.getElementById("event_add_end").value = new_end;
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
@ -24,7 +24,7 @@ if ($config_enable_cron == 0) {
|
|||
}
|
||||
|
||||
// Check Cron Key
|
||||
if ( $argv[1] !== $config_cron_key ) {
|
||||
if ($argv[1] !== $config_cron_key) {
|
||||
exit("Cron Key invalid -- Quitting..");
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ $lock_file_path = "{$temp_dir}/itflow_mail_queue_{$installation_id}.lock";
|
|||
// Check for lock file to prevent concurrent script runs
|
||||
if (file_exists($lock_file_path)) {
|
||||
$file_age = time() - filemtime($lock_file_path);
|
||||
|
||||
|
||||
// If file is older than 10 minutes (600 seconds), delete and continue
|
||||
if ($file_age > 600) {
|
||||
unlink($lock_file_path);
|
||||
|
|
@ -61,7 +61,7 @@ file_put_contents($lock_file_path, "Locked");
|
|||
|
||||
// Get Mail Queue that has status of Queued and send it to the function sendSingleEmail() located in functions.php
|
||||
|
||||
$sql_queue = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_status = 0 AND email_queued_at <= NOW()");
|
||||
$sql_queue = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_status = 0");
|
||||
|
||||
if (mysqli_num_rows($sql_queue) > 0) {
|
||||
while ($row = mysqli_fetch_array($sql_queue)) {
|
||||
|
|
@ -74,6 +74,7 @@ if (mysqli_num_rows($sql_queue) > 0) {
|
|||
$email_content = $row['email_content'];
|
||||
$email_queued_at = $row['email_queued_at'];
|
||||
$email_sent_at = $row['email_sent_at'];
|
||||
$email_ics_str = $row['email_cal_str'];
|
||||
|
||||
// Sanitized Input
|
||||
$email_recipient_logging = sanitizeInput($row['email_recipient']);
|
||||
|
|
@ -96,7 +97,8 @@ if (mysqli_num_rows($sql_queue) > 0) {
|
|||
$email_recipient,
|
||||
$email_recipient_name,
|
||||
$email_subject,
|
||||
$email_content
|
||||
$email_content,
|
||||
$email_ics_str
|
||||
);
|
||||
|
||||
if ($mail !== true) {
|
||||
|
|
@ -109,7 +111,7 @@ if (mysqli_num_rows($sql_queue) > 0) {
|
|||
// Update Message
|
||||
mysqli_query($mysqli, "UPDATE email_queue SET email_status = 3, email_sent_at = NOW(), email_attempts = 1 WHERE email_id = $email_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +131,7 @@ if (mysqli_num_rows($sql_failed_queue) > 0) {
|
|||
$email_content = $row['email_content'];
|
||||
$email_queued_at = $row['email_queued_at'];
|
||||
$email_sent_at = $row['email_sent_at'];
|
||||
$email_ics_str = $row['email_cal_str'];
|
||||
// Increment the attempts
|
||||
$email_attempts = intval($row['email_attempts']) + 1;
|
||||
|
||||
|
|
@ -153,7 +156,8 @@ if (mysqli_num_rows($sql_failed_queue) > 0) {
|
|||
$email_recipient,
|
||||
$email_recipient_name,
|
||||
$email_subject,
|
||||
$email_content
|
||||
$email_content,
|
||||
$email_ics_str
|
||||
);
|
||||
|
||||
if ($mail !== true) {
|
||||
|
|
@ -166,7 +170,7 @@ if (mysqli_num_rows($sql_failed_queue) > 0) {
|
|||
// Update Message
|
||||
mysqli_query($mysqli, "UPDATE email_queue SET email_status = 3, email_sent_at = NOW(), email_attempts = $email_attempts WHERE email_id = $email_id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1451
dashboard.php
1451
dashboard.php
File diff suppressed because it is too large
Load Diff
|
|
@ -1559,6 +1559,8 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
|
|||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.2'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '1.0.2') {
|
||||
//Insert queries here required to update to DB version 1.0.3
|
||||
mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_stripe_expense_vendor` INT(11) NOT NULL DEFAULT 0 AFTER `config_stripe_account`");
|
||||
|
|
@ -1586,10 +1588,21 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
|
|||
// Please add this same comment block to the bottom of this file, and update the version number.
|
||||
// Uncomment Below Lines, to add additional database updates
|
||||
//
|
||||
// if (CURRENT_DATABASE_VERSION == '1.0.4') {
|
||||
// // Insert queries here required to update to DB version 1.0.5
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '1.0.4') {
|
||||
//Insert queries here required to update to DB version 1.0.5
|
||||
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_schedule` DATETIME DEFAULT NULL AFTER `ticket_billable`");
|
||||
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_onsite` TINYINT(1) NOT NULL DEFAULT 0 AFTER `ticket_schedule`");
|
||||
mysqli_query($mysqli, "ALTER TABLE `email_queue` ADD `email_cal_str` VARCHAR(1024) DEFAULT NULL AFTER `email_content`");
|
||||
|
||||
// Then, update the database to the next sequential version
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.5'");
|
||||
}
|
||||
|
||||
// if (CURRENT_DATABASE_VERSION == '1.0.5') {
|
||||
// // Insert queries here required to update to DB version 1.0.6
|
||||
// // Then, update the database to the next sequential version
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.5'");
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.0.6'");
|
||||
// }
|
||||
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@
|
|||
* It is used in conjunction with database_updates.php
|
||||
*/
|
||||
|
||||
DEFINE("LATEST_DATABASE_VERSION", "1.0.4");
|
||||
DEFINE("LATEST_DATABASE_VERSION", "1.0.5");
|
||||
|
||||
|
|
|
|||
1
db.sql
1
db.sql
|
|
@ -1573,6 +1573,7 @@ CREATE TABLE `tickets` (
|
|||
`ticket_priority` varchar(200) DEFAULT NULL,
|
||||
`ticket_status` varchar(200) NOT NULL,
|
||||
`ticket_billable` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`ticket_schedule` DATETIME DEFAULT NULL,
|
||||
`ticket_vendor_ticket_number` varchar(255) DEFAULT NULL,
|
||||
`ticket_feedback` varchar(200) DEFAULT NULL,
|
||||
`ticket_created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||||
|
|
|
|||
294
functions.php
294
functions.php
File diff suppressed because one or more lines are too long
|
|
@ -15,7 +15,7 @@ function populateScheduledTicketEditModal(client_id, ticket_id) {
|
|||
const assets = response.assets;
|
||||
|
||||
// Populate the scheduled ticket modal fields
|
||||
document.getElementById("editHeader").innerText = " Edit Scheduled ticket: " + ticket.scheduled_ticket_subject;
|
||||
document.getElementById("editHeader").innerText = " Edit Recurring ticket: " + ticket.scheduled_ticket_subject;
|
||||
document.getElementById("editTicketId").value = ticket_id;
|
||||
document.getElementById("editClientId").value = client_id;
|
||||
document.getElementById("editTicketSubject").value = ticket.scheduled_ticket_subject;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
# Zap Calendar iCalendar Library
|
||||
|
||||
(https://github.com/zcontent/icalendar)
|
||||
|
||||
The Zap Calendar iCalendar Library is a PHP library for supporting the iCalendar (RFC 5545) standard.
|
||||
|
||||
This PHP library is for reading and writing iCalendar formatted feeds and
|
||||
files. Features of the library include:
|
||||
|
||||
- Read AND write support for iCalendar files
|
||||
- Object based creation and manipulation of iCalendar files
|
||||
- Supports expansion of RRULE to a list of repeating dates
|
||||
- Supports adding timezone info to iCalendar file
|
||||
|
||||
All iCalendar data is stored in a PHP object tree.
|
||||
This allows any property to be added to the iCalendar feed without
|
||||
requiring specialized library function calls.
|
||||
With power comes responsibility. Missing or invalid properties can cause
|
||||
the resulting iCalendar file to be invalid. Visit [iCalendar.org](http://icalendar.org) to view valid
|
||||
properties and test your feed using the site's [iCalendar validator tool](http://icalendar.org/validator.html).
|
||||
|
||||
Library API documentation can be found at http://icalendar.org/zapcallibdocs
|
||||
|
||||
See the examples folder for programs that read and write iCalendar
|
||||
files. At its simpliest, you need to include the library at the top of your program:
|
||||
|
||||
```php
|
||||
require_once($path_to_library . "/zapcallib.php");
|
||||
```
|
||||
|
||||
Create an ical object using the ZCiCal object:
|
||||
|
||||
```php
|
||||
$icalobj = new ZCiCal();
|
||||
```
|
||||
|
||||
Add an event object:
|
||||
|
||||
```php
|
||||
$eventobj = new ZCiCalNode("VEVENT", $icalobj->curnode);
|
||||
```
|
||||
|
||||
Add a start and end date to the event:
|
||||
|
||||
```php
|
||||
// add start date
|
||||
$eventobj->addNode(new ZCiCalDataNode("DTSTART:" . ZCiCal::fromSqlDateTime("2020-01-01 12:00:00")));
|
||||
|
||||
// add end date
|
||||
$eventobj->addNode(new ZCiCalDataNode("DTEND:" . ZCiCal::fromSqlDateTime("2020-01-01 13:00:00")));
|
||||
```
|
||||
|
||||
Write the object in iCalendar format using the export() function call:
|
||||
|
||||
```php
|
||||
echo $icalobj->export();
|
||||
```
|
||||
|
||||
This example will not validate since it is missing some required elements.
|
||||
Look at the simpleevent.php example for the minimum # of elements
|
||||
needed for a validated iCalendar file.
|
||||
|
||||
To create a multi-event iCalendar file, simply create multiple event objects. For example:
|
||||
|
||||
```php
|
||||
$icalobj = new ZCiCal();
|
||||
$eventobj1 = new ZCiCalNode("VEVENT", $icalobj->curnode);
|
||||
$eventobj1->addNode(new ZCiCalDataNode("SUMMARY:Event 1"));
|
||||
...
|
||||
$eventobj2 = new ZCiCalNode("VEVENT", $icalobj->curnode);
|
||||
$eventobj2->addNode(new ZCiCalDataNode("SUMMARY:Event 2"));
|
||||
...
|
||||
```
|
||||
|
||||
To read an existing iCalendar file/feed, create the ZCiCal object with a string representing the contents of the iCalendar file:
|
||||
|
||||
```php
|
||||
$icalobj = new ZCiCal($icalstring);
|
||||
```
|
||||
|
||||
Large iCalendar files can be read in chunks to reduce the amount of memory needed to hold the iCalendar feed in memory. This example reads 500 events at a time:
|
||||
|
||||
```php
|
||||
$icalobj = null;
|
||||
$eventcount = 0;
|
||||
$maxevents = 500;
|
||||
do
|
||||
{
|
||||
$icalobj = newZCiCal($icalstring, $maxevents, $eventcount);
|
||||
...
|
||||
$eventcount +=$maxevents;
|
||||
}
|
||||
while($icalobj->countEvents() >= $eventcount);
|
||||
```
|
||||
|
||||
You can read the events from an imported (or created) iCalendar object in this manner:
|
||||
|
||||
```php
|
||||
foreach($icalobj->tree->child as $node)
|
||||
{
|
||||
if($node->getName() == "VEVENT")
|
||||
{
|
||||
foreach($node->data as $key => $value)
|
||||
{
|
||||
if($key == "SUMMARY")
|
||||
{
|
||||
echo "event title: " . $value->getValues() . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- Since the library utilizes objects to read and write iCalendar data, the
|
||||
size of the iCalendar data is limited to the amount of available memory on the machine.
|
||||
The ZCiCal() object supports reading a range of events to minimize memory
|
||||
space.
|
||||
- The library ignores timezone info when importing files, instead utilizing PHP's timezone
|
||||
library for calculations (timezones are supported when exporting files).
|
||||
Imported timezones need to be aliased to a [PHP supported timezone](http://php.net/manual/en/timezones.php).
|
||||
- At this time, the library does not support the "BYSETPOS" option in RRULE items.
|
||||
- At this time, the maximum date supported is 2036 to avoid date math issues
|
||||
with 32 bit systems.
|
||||
- Repeating events are limited to a maximum of 5,000 dates to avoid memory or infinite loop issues
|
||||
|
||||
|
|
@ -0,0 +1,568 @@
|
|||
<?php
|
||||
/**
|
||||
* date.php - date helper class
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
// No direct access
|
||||
defined('_ZAPCAL') or die( 'Restricted access' );
|
||||
|
||||
/**
|
||||
* Zap Calendar Date Helper Class
|
||||
*
|
||||
* Helper class for various date functions
|
||||
*/
|
||||
class ZDateHelper {
|
||||
|
||||
/**
|
||||
* Find the number of days in a month
|
||||
*
|
||||
* @param int $month Month is between 1 and 12 inclusive
|
||||
*
|
||||
* @param int $year is between 1 and 32767 inclusive
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static function DayInMonth($month, $year) {
|
||||
$daysInMonth = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
|
||||
if ($month != 2) return $daysInMonth[$month - 1];
|
||||
return (checkdate($month, 29, $year)) ? 29 : 28;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date today?
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isToday($date, $tzid = "UTC") {
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return gmdate('Y-m-d', $date) == gmdate('Y-m-d', $now);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date before today?
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isBeforeToday($date, $tzid = "UTC"){
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return mktime(0,0,0,date('m',$now),date('d',$now),date('Y',$now)) >
|
||||
mktime(0,0,0,date('m',$date),date('d',$date),date('Y',$now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date after today?
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isAfterToday($date, $tzid = "UTC"){
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return mktime(0,0,0,date('m',$now),date('d',$now),date('Y',$now)) <
|
||||
mktime(0,0,0,date('m',$date),date('d',$date),date('Y',$now));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date tomorrow?
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isTomorrow($date, $tzid = "UTC") {
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return gmdate('Y-m-d', $date) == gmdate('Y-m-d', $now + 60 * 60 * 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date in the future?
|
||||
*
|
||||
* This routine differs from isAfterToday() in that isFuture() will
|
||||
* return true for date-time values later in the same day.
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isFuture($date, $tzid = "UTC"){
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return $date > $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date in the past?
|
||||
*
|
||||
* This routine differs from isBeforeToday() in that isPast() will
|
||||
* return true for date-time values earlier in the same day.
|
||||
*
|
||||
* @param int $date date in Unix timestamp format
|
||||
*
|
||||
* @param int $tzid PHP recognized timezone (default is UTC)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isPast($date, $tzid = "UTC") {
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return $date < $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current Unix timestamp in local timezone
|
||||
*
|
||||
* @param string $tzid PHP recognized timezone
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
static function now($tzid = "UTC"){
|
||||
$dtz = new DateTimeZone($tzid);
|
||||
$dt = new DateTime("now", $dtz);
|
||||
$now = time() + $dtz->getOffset($dt);
|
||||
return $now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given date fall on a weekend?
|
||||
*
|
||||
* @param int $date Unix timestamp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function isWeekend($date) {
|
||||
$dow = gmdate('w',$date);
|
||||
return $dow == 0 || $dow == 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Unix timestamp to SQL date-time
|
||||
*
|
||||
* @param int $t Unix timestamp
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function toSqlDateTime($t = 0)
|
||||
{
|
||||
date_default_timezone_set('GMT');
|
||||
if($t == 0)
|
||||
return gmdate('Y-m-d H:i:s',self::now());
|
||||
return gmdate('Y-m-d H:i:s', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Unix timestamp to SQL date
|
||||
*
|
||||
* @param int $t Unix timestamp
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function toSqlDate($t = 0)
|
||||
{
|
||||
date_default_timezone_set('GMT');
|
||||
if($t == 0)
|
||||
return gmdate('Y-m-d',self::now());
|
||||
return gmdate('Y-m-d', $t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format iCal date-time string to Unix timestamp
|
||||
*
|
||||
* @param string $datetime in iCal time format ( YYYYMMDD or YYYYMMDDTHHMMSS or YYYYMMDDTHHMMSSZ )
|
||||
*
|
||||
* @return int Unix timestamp
|
||||
*/
|
||||
static function fromiCaltoUnixDateTime($datetime) {
|
||||
// first check format
|
||||
$formats = array();
|
||||
$formats[] = "/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/";
|
||||
$formats[] = "/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]/";
|
||||
$formats[] = "/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]Z/";
|
||||
$ok = false;
|
||||
foreach($formats as $format){
|
||||
if(preg_match($format,$datetime)){
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$ok)
|
||||
return null;
|
||||
$year = substr($datetime,0,4);
|
||||
$month = substr($datetime,4,2);
|
||||
$day = substr($datetime,6,2);
|
||||
$hour = 0;
|
||||
$minute = 0;
|
||||
$second = 0;
|
||||
if(strlen($datetime) > 8 && $datetime[8] == "T") {
|
||||
$hour = substr($datetime,9,2);
|
||||
$minute = substr($datetime,11,2);
|
||||
$second = substr($datetime,13,2);
|
||||
}
|
||||
return gmmktime($hour, $minute, $second, $month, $day, $year);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Unix timestamp to iCal date-time string
|
||||
*
|
||||
* @param int $datetime Unix timestamp
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function fromUnixDateTimetoiCal($datetime){
|
||||
date_default_timezone_set('GMT');
|
||||
return gmdate("Ymd\THis",$datetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert iCal duration string to # of seconds
|
||||
*
|
||||
* @param string $duration iCal duration string
|
||||
*
|
||||
* return int
|
||||
*/
|
||||
static function iCalDurationtoSeconds($duration) {
|
||||
$secs = 0;
|
||||
if($duration[0] == "P") {
|
||||
$duration = str_replace(array("H","M","S","T","D","W","P"),array("H,","M,","S,","","D,","W,",""),$duration);
|
||||
$dur2 = explode(",",$duration);
|
||||
foreach($dur2 as $dur){
|
||||
$val=intval($dur);
|
||||
if(strlen($dur) > 0){
|
||||
switch($dur[strlen($dur) - 1]) {
|
||||
case "H":
|
||||
$secs += 60*60 * $val;
|
||||
break;
|
||||
case "M":
|
||||
$secs += 60 * $val;
|
||||
break;
|
||||
case "S":
|
||||
$secs += $val;
|
||||
break;
|
||||
case "D":
|
||||
$secs += 60*60*24 * $val;
|
||||
break;
|
||||
case "W":
|
||||
$secs += 60*60*24*7 * $val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $secs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if day falls within date range
|
||||
*
|
||||
* @param int $daystart start of day in Unix timestamp format
|
||||
*
|
||||
* @param int $begin Unix timestamp of starting date range
|
||||
*
|
||||
* @param int $end Unix timestamp of end date range
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function inDay($daystart, $begin, $end)
|
||||
{
|
||||
//$dayend = $daystart + 60*60*24 - 60;
|
||||
// add 1 day to determine end of day
|
||||
// don't use 24 hours, since twice a year DST Sundays are 23 hours and 25 hours in length
|
||||
// adding 1 day takes this into account
|
||||
$dayend = self::addDate($daystart, 0,0,0,0,1,0);
|
||||
|
||||
$end = max($begin, $end); // $end can't be less than $begin
|
||||
$inday =
|
||||
($daystart <= $begin && $begin < $dayend)
|
||||
||($daystart < $end && $end < $dayend)
|
||||
||($begin <= $daystart && $end > $dayend)
|
||||
;
|
||||
return $inday;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert SQL date or date-time to Unix timestamp
|
||||
*
|
||||
* @param string $datetime SQL date or date-time
|
||||
*
|
||||
* @return int Unix date-time timestamp
|
||||
*/
|
||||
static function toUnixDate($datetime)
|
||||
{
|
||||
$year = substr($datetime,0,4);
|
||||
$month = substr($datetime,5,2);
|
||||
$day = substr($datetime,8,2);
|
||||
|
||||
return mktime(0, 0, 0, $month, $day, $year);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert SQL date or date-time to Unix date timestamp
|
||||
*
|
||||
* @param string $datetime SQL date or date-time
|
||||
*
|
||||
* @return int Unix timestamp
|
||||
*/
|
||||
static function toUnixDateTime($datetime)
|
||||
{
|
||||
// convert to absolute dates if neccessary
|
||||
$datetime = self::getAbsDate($datetime);
|
||||
$year = substr($datetime,0,4);
|
||||
$month = substr($datetime,5,2);
|
||||
$day = substr($datetime,8,2);
|
||||
$hour = 0;
|
||||
$minute = 0;
|
||||
$second = 0;
|
||||
if(strlen($datetime) > 10) {
|
||||
$hour = substr($datetime,11,2);
|
||||
$minute = substr($datetime,14,2);
|
||||
$second = substr($datetime,17,2);
|
||||
}
|
||||
return gmmktime($hour, $minute, $second, $month, $day, $year);
|
||||
}
|
||||
|
||||
/**
|
||||
* Date math: add or substract from current date to get a new date
|
||||
*
|
||||
* @param int $date date to add or subtract from
|
||||
*
|
||||
* @param int $hour add or subtract hours from date
|
||||
*
|
||||
* @param int $min add or subtract minutes from date
|
||||
*
|
||||
* @param int $sec add or subtract seconds from date
|
||||
*
|
||||
* @param int $month add or subtract months from date
|
||||
*
|
||||
* @param int $day add or subtract days from date
|
||||
*
|
||||
* @param int $year add or subtract years from date
|
||||
*
|
||||
* @param string $tzid PHP recognized timezone (default is UTC)
|
||||
*/
|
||||
static function addDate($date, $hour, $min, $sec, $month, $day, $year, $tzid = "UTC") {
|
||||
date_default_timezone_set($tzid);
|
||||
$sqldate = self::toSQLDateTime($date);
|
||||
$tdate = array();
|
||||
$tdate["year"] = substr($sqldate,0,4);
|
||||
$tdate["mon"] = substr($sqldate,5,2);
|
||||
$tdate["mday"] = substr($sqldate,8,2);
|
||||
$tdate["hours"] = substr($sqldate,11,2);
|
||||
$tdate["minutes"] = substr($sqldate,14,2);
|
||||
$tdate["seconds"] = substr($sqldate,17,2);
|
||||
$newdate=mktime($tdate["hours"] + $hour, $tdate["minutes"] + $min, $tdate["seconds"] + $sec, $tdate["mon"] + $month, $tdate["mday"] + $day, $tdate["year"] + $year);
|
||||
date_default_timezone_set("UTC");
|
||||
//echo self::toSQLDateTime($date) . " => " . self::toSQLDateTime($newdate) . " ($hour:$min:$sec $month/$day/$year)<br/>\n";
|
||||
return $newdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Date math: get date from week and day in specifiec month
|
||||
*
|
||||
* This routine finds actual dates for the second Tuesday of the month, last Friday of the month, etc.
|
||||
* For second Tuesday, use $week = 1, $wday = 2
|
||||
* for last Friday, use $week = -1, $wday = 5
|
||||
*
|
||||
* @param int $date Unix timestamp
|
||||
*
|
||||
* @param int $week week number, 0 is first week, -1 is last
|
||||
*
|
||||
* @param int $wday day of week, 0 is Sunday, 6 is Saturday
|
||||
*
|
||||
* @param string $tzid PHP supported timezone
|
||||
*
|
||||
* @return int Unix timestamp
|
||||
*/
|
||||
static function getDateFromDay($date, $week, $wday,$tzid="UTC") {
|
||||
//echo "getDateFromDay(" . self::toSqlDateTime($date) . ",$week,$wday)<br/>\n";
|
||||
// determine first day in month
|
||||
$tdate = getdate($date);
|
||||
$monthbegin = gmmktime(0,0,0, $tdate["mon"],1,$tdate["year"]);
|
||||
$monthend = self::addDate($monthbegin, 0,0,0,1,-1,0,$tzid); // add 1 month and subtract 1 day
|
||||
$day = self::addDate($date,0,0,0,0,1 - $tdate["mday"],0,$tzid);
|
||||
$month = array(array());
|
||||
while($day <= $monthend) {
|
||||
$tdate=getdate($day);
|
||||
$month[$tdate["wday"]][]=$day;
|
||||
//echo self::toSQLDateTime($day) . "<br/>\n";
|
||||
$day = self::addDate($day, 0,0,0,0,1,0,$tzid); // add 1 day
|
||||
}
|
||||
$dayinmonth=0;
|
||||
if($week >= 0)
|
||||
$dayinmonth = $month[$wday][$week];
|
||||
else
|
||||
$dayinmonth = $month[$wday][count($month[$wday]) - 1];
|
||||
//echo "return " . self::toSQLDateTime($dayinmonth);
|
||||
//exit;
|
||||
return $dayinmonth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UTC date-time to local date-time
|
||||
*
|
||||
* @param string $sqldate SQL date-time string
|
||||
*
|
||||
* @param string $tzid PHP recognized timezone (default is "UTC")
|
||||
*
|
||||
* @return string SQL date-time string
|
||||
*/
|
||||
static function toLocalDateTime($sqldate, $tzid = "UTC" ){
|
||||
try
|
||||
{
|
||||
$timezone = new DateTimeZone($tzid);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// bad time zone specified
|
||||
return $sqldate;
|
||||
}
|
||||
$udate = self::toUnixDateTime($sqldate);
|
||||
$daydatetime = new DateTime("@" . $udate);
|
||||
$tzoffset = $timezone->getOffset($daydatetime);
|
||||
return self::toSqlDateTime($udate + $tzoffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert local date-time to UTC date-time
|
||||
*
|
||||
* @param string $sqldate SQL date-time string
|
||||
*
|
||||
* @param string $tzid PHP recognized timezone (default is "UTC")
|
||||
*
|
||||
* @return string SQL date-time string
|
||||
*/
|
||||
static function toUTCDateTime($sqldate, $tzid = "UTC" ){
|
||||
|
||||
date_default_timezone_set("UTC");
|
||||
try
|
||||
{
|
||||
$date = new DateTime($sqldate, $tzid);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// bad time zone specified
|
||||
return $sqldate;
|
||||
}
|
||||
$offset = $date->getOffsetFromGMT();
|
||||
if($offset >= 0)
|
||||
$date->sub(new DateInterval("PT".$offset."S"));
|
||||
else
|
||||
$date->add(new DateInterval("PT".abs($offset)."S"));
|
||||
return $date->toSql(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from a relative date to an absolute date
|
||||
*
|
||||
* Examples of relative dates are "-2y" for 2 years ago, "18m"
|
||||
* for 18 months after today. Relative date uses "y", "m" and "d" for
|
||||
* year, month and day. Relative date can be combined into comma
|
||||
* separated list, i.e., "-1y,-1d" for 1 year and 1 day ago.
|
||||
*
|
||||
* @param string $date relative date string (i.e. "1y" for 1 year from today)
|
||||
*
|
||||
* @param string $rdate reference date, or blank for current date (in SQL date-time format)
|
||||
*
|
||||
* @return string in SQL date-time format
|
||||
*/
|
||||
static function getAbsDate($date,$rdate = ""){
|
||||
if(str_replace(array("y","m","d","h","n"),"",strtolower($date)) != strtolower($date)){
|
||||
date_default_timezone_set("UTC");
|
||||
if($rdate == "")
|
||||
$udate = time();
|
||||
else
|
||||
$udate = self::toUnixDateTime($rdate);
|
||||
$values=explode(",",strtolower($date));
|
||||
$y = 0;
|
||||
$m = 0;
|
||||
$d = 0;
|
||||
$h = 0;
|
||||
$n = 0;
|
||||
foreach($values as $value){
|
||||
$rtype = substr($value,strlen($value)-1);
|
||||
$rvalue = intval(substr($value,0,strlen($value) - 1));
|
||||
switch($rtype){
|
||||
case 'y':
|
||||
$y = $rvalue;
|
||||
break;
|
||||
case 'm':
|
||||
$m = $rvalue;
|
||||
break;
|
||||
case 'd':
|
||||
$d = $rvalue;
|
||||
break;
|
||||
case 'h':
|
||||
$h = $rvalue;
|
||||
break;
|
||||
case 'n':
|
||||
$n = $rvalue;
|
||||
break;
|
||||
}
|
||||
// for "-" values, move to start of day , otherwise, move to end of day
|
||||
if($rvalue[0] == '-')
|
||||
$udate = mktime(0,0,0,date('m',$udate),date('d',$udate),date('Y',$udate));
|
||||
else
|
||||
$udate = mktime(0,-1,0,date('m',$udate),date('d',$udate)+1,date('Y',$udate));
|
||||
$udate = self::addDate($udate,$h,$n,0,$m,$d,$y);
|
||||
}
|
||||
$date = self::toSqlDateTime($udate);
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Unix timestamp to iCal date-time format
|
||||
*
|
||||
* @param int $datetime Unix timestamp
|
||||
*
|
||||
* @return string iCal date-time string
|
||||
*/
|
||||
static function toiCalDateTime($datetime = null){
|
||||
date_default_timezone_set('UTC');
|
||||
if($datetime == null)
|
||||
$datetime = time();
|
||||
return gmdate("Ymd\THis",$datetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format Unix timestamp to iCal date format
|
||||
*
|
||||
* @param int $datetime Unix timestamp
|
||||
*
|
||||
* @return string iCal date-time string
|
||||
*/
|
||||
static function toiCalDate($datetime = null){
|
||||
date_default_timezone_set('UTC');
|
||||
if($datetime == null)
|
||||
$datetime = time();
|
||||
return gmdate("Ymd",$datetime);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* framework.php - framework file
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
// No direct access
|
||||
defined('_ZAPCAL') or die( 'Restricted access' );
|
||||
|
||||
/**
|
||||
* set MAXYEAR to 2036 for 32 bit systems, can be higher for 64 bit systems
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
define('_ZAPCAL_MAXYEAR', 2036);
|
||||
|
||||
/**
|
||||
* set MAXREVENTS to maximum # of repeating events
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
define('_ZAPCAL_MAXREVENTS', 5000);
|
||||
|
||||
require_once(_ZAPCAL_BASE . '/includes/date.php');
|
||||
require_once(_ZAPCAL_BASE . '/includes/recurringdate.php');
|
||||
require_once(_ZAPCAL_BASE . '/includes/ical.php');
|
||||
require_once(_ZAPCAL_BASE . '/includes/timezone.php');
|
||||
|
|
@ -0,0 +1,986 @@
|
|||
<?php
|
||||
/**
|
||||
* ical.php create iCalendar data structure
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
// No direct access
|
||||
defined('_ZAPCAL') or die( 'Restricted access' );
|
||||
|
||||
/**
|
||||
* Object for storing an unfolded iCalendar line
|
||||
*
|
||||
* The ZCiCalDataNode class contains data from an unfolded iCalendar line
|
||||
*
|
||||
*/
|
||||
class ZCiCalDataNode {
|
||||
/**
|
||||
* The name of the node
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $name = "";
|
||||
|
||||
/**
|
||||
* Node parameters (before the colon ":")
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $parameter=array();
|
||||
|
||||
/**
|
||||
* Node values (after the colon ":")
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $value=array();
|
||||
|
||||
/**
|
||||
* Create an object from an unfolded iCalendar line
|
||||
*
|
||||
* @param string $line An unfolded iCalendar line
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*/
|
||||
function __construct( $line ) {
|
||||
//echo "ZCiCalDataNode($line)<br/>\n";
|
||||
//separate line into parameters and value
|
||||
// look for colon separating name or parameter and value
|
||||
// first change any escaped colons temporarily to make it easier
|
||||
$tline = str_replace("\\:", "`~", $line);
|
||||
// see if first colon is inside a quoted string
|
||||
$i = 0;
|
||||
$datafind = false;
|
||||
$inquotes = false;
|
||||
while(!$datafind && ($i < strlen($tline))) {
|
||||
//echo "$i: " . $tline[$i] . ", ord() = " . ord($tline[$i]) . "<br>\n";
|
||||
if(!$inquotes && $tline[$i] == ':')
|
||||
$datafind=true;
|
||||
else{
|
||||
$i += 1;
|
||||
if(substr($tline,$i,1) == '"')
|
||||
$inquotes = !$inquotes;
|
||||
}
|
||||
}
|
||||
if($datafind){
|
||||
$value = str_replace("`~","\\:",substr($line,$i+1));
|
||||
// fix escaped characters (don't see double quotes in spec but Apple apparently uses it in iCal)
|
||||
$value = str_replace(array('\\N' , '\\n', '\\"' ), array("\n", "\n" , '"'), $value);
|
||||
$tvalue = str_replace("\\,", "`~", $value);
|
||||
//echo "value: " . $tvalue . "<br>\n";
|
||||
$tvalue = explode(",",$tvalue);
|
||||
$value = str_replace("`~","\\,",$tvalue);
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
$parameter = trim(substr($line,0,$i));
|
||||
|
||||
$parameter = str_replace("\\;", "`~", $parameter);
|
||||
$parameters = explode(";", $parameter);
|
||||
$parameters = str_replace("`~", "\\;", $parameters);
|
||||
$this->name = array_shift($parameters);
|
||||
foreach($parameters as $parameter){
|
||||
$pos = strpos($parameter,"=");
|
||||
if($pos > 0){
|
||||
$param = substr($parameter,0,$pos);
|
||||
$paramvalue = substr($parameter,$pos+1);
|
||||
$tvalue = str_replace("\\,", "`~", $paramvalue);
|
||||
//$tvalue = explode(",",$tvalue);
|
||||
$paramvalue = str_replace("`~","\\,",$tvalue);
|
||||
$this->parameter[strtolower($param)] = $paramvalue;
|
||||
//$this->paramvalue[] = $paramvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getName()
|
||||
*
|
||||
* Return the name of the object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getName(){
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get $ith parameter from array
|
||||
* @param int $i
|
||||
*
|
||||
* @return var
|
||||
*/
|
||||
function getParameter($i){
|
||||
return $this->parameter[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getParameters(){
|
||||
return $this->parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comma separated values
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getValues(){
|
||||
return implode(",",$this->value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Object for storing a list of unfolded iCalendar lines (ZCiCalDataNode objects)
|
||||
*
|
||||
* @property object $parentnode Parent of this node
|
||||
*
|
||||
* @property array $child Array of children for this node
|
||||
*
|
||||
* @property data $data Array of data for this node
|
||||
*
|
||||
* @property object $next Next sibling of this node
|
||||
*
|
||||
* @property object $prev Previous sibling of this node
|
||||
*/
|
||||
|
||||
class ZCiCalNode {
|
||||
/**
|
||||
* The name of the node
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $name="";
|
||||
|
||||
/**
|
||||
* The parent of this node
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $parentnode=null;
|
||||
|
||||
/**
|
||||
* Array of children for this node
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $child= array();
|
||||
|
||||
/**
|
||||
* Array of $data for this node
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $data= array();
|
||||
|
||||
|
||||
/**
|
||||
* Next sibling of this node
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $next=null;
|
||||
|
||||
/**
|
||||
* Previous sibling of this node
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $prev=null;
|
||||
|
||||
/**
|
||||
* Create ZCiCalNode
|
||||
*
|
||||
* @param string $_name Name of node
|
||||
*
|
||||
* @param object $_parent Parent node for this node
|
||||
*
|
||||
* @param bool $first Is this the first child for this parent?
|
||||
*/
|
||||
function __construct( $_name, & $_parent, $first = false) {
|
||||
$this->name = $_name;
|
||||
$this->parentnode = $_parent;
|
||||
if($_parent != null){
|
||||
if(count($this->parentnode->child) > 0) {
|
||||
if($first)
|
||||
{
|
||||
$first = & $this->parentnode->child[0];
|
||||
$first->prev = & $this;
|
||||
$this->next = & $first;
|
||||
}
|
||||
else
|
||||
{
|
||||
$prev =& $this->parentnode->child[count($this->parentnode->child)-1];
|
||||
$prev->next =& $this;
|
||||
$this->prev =& $prev;
|
||||
}
|
||||
}
|
||||
if($first)
|
||||
{
|
||||
array_unshift($this->parentnode->child, $this);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parentnode->child[] =& $this;
|
||||
}
|
||||
}
|
||||
/*
|
||||
echo "creating " . $this->getName();
|
||||
if($_parent != null)
|
||||
echo " child of " . $_parent->getName() . "/" . count($this->parentnode->child);
|
||||
echo "<br/>";
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add node to list
|
||||
*
|
||||
* @param object $node
|
||||
*
|
||||
*/
|
||||
function addNode($node) {
|
||||
if(array_key_exists($node->getName(), $this->data))
|
||||
{
|
||||
if(!is_array($this->data[$node->getName()]))
|
||||
{
|
||||
$this->data[$node->getName()] = array($this->data[$node->getName()]);
|
||||
}
|
||||
$this->data[$node->getName()][] = $node;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->data[$node->getName()] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Attribute
|
||||
*
|
||||
* @param int $i array id of attribute to get
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getAttrib($i) {
|
||||
return $this->attrib[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Attribute
|
||||
*
|
||||
* @param string $value value of attribute to set
|
||||
*
|
||||
*/
|
||||
function setAttrib($value) {
|
||||
$this->attrib[] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent object of this object
|
||||
*
|
||||
* @return object parent of this object
|
||||
*/
|
||||
function &getParent() {
|
||||
return $this->parentnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first child of this object
|
||||
*
|
||||
* @return object The first child
|
||||
*/
|
||||
function &getFirstChild(){
|
||||
static $nullguard = null;
|
||||
if(count($this->child) > 0) {
|
||||
//echo "moving from " . $this->getName() . " to " . $this->child[0]->getName() . "<br/>";
|
||||
return $this->child[0];
|
||||
}
|
||||
else
|
||||
return $nullguard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print object tree in HTML for debugging purposes
|
||||
*
|
||||
* @param object $node select part of tree to print, or leave blank for full tree
|
||||
*
|
||||
* @param int $level Level of recursion (usually leave this blank)
|
||||
*
|
||||
* @return string - HTML formatted display of object tree
|
||||
*/
|
||||
function printTree(& $node=null, $level=1){
|
||||
$level += 1;
|
||||
$html = "";
|
||||
if($node == null)
|
||||
$node = $this->parentnode;
|
||||
if($level > 5)
|
||||
{
|
||||
die("levels nested too deep<br/>\n");
|
||||
//return;
|
||||
}
|
||||
for($i = 0 ; $i < $level; $i ++)
|
||||
$html .= "+";
|
||||
$html .= $node->getName() . "<br/>\n";
|
||||
foreach ($node->child as $c){
|
||||
$html .= $node->printTree($c,$level);
|
||||
}
|
||||
$level -= 1;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* export tree to icalendar format
|
||||
*
|
||||
* @param object $node Top level node to export
|
||||
*
|
||||
* @param int $level Level of recursion (usually leave this blank)
|
||||
*
|
||||
* @return string iCalendar formatted output
|
||||
*/
|
||||
function export(& $node=null, $level=0){
|
||||
$txtstr = "";
|
||||
if($node == null)
|
||||
$node = $this;
|
||||
if($level > 5)
|
||||
{
|
||||
//die("levels nested too deep<br/>\n");
|
||||
throw new Exception("levels nested too deep");
|
||||
}
|
||||
$txtstr .= "BEGIN:" . $node->getName() . "\r\n";
|
||||
if(property_exists($node,"data"))
|
||||
foreach ($node->data as $d){
|
||||
if(is_array($d))
|
||||
{
|
||||
foreach ($d as $c)
|
||||
{
|
||||
//$txtstr .= $node->export($c,$level + 1);
|
||||
$p = "";
|
||||
$params = @$c->getParameters();
|
||||
if(count($params) > 0)
|
||||
{
|
||||
foreach($params as $key => $value){
|
||||
$p .= ";" . strtoupper($key) . "=" . $value;
|
||||
}
|
||||
}
|
||||
$txtstr .= $this->printDataLine($c, $p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$p = "";
|
||||
$params = @$d->getParameters();
|
||||
if(count($params) > 0)
|
||||
{
|
||||
foreach($params as $key => $value){
|
||||
$p .= ";" . strtoupper($key) . "=" . $value;
|
||||
}
|
||||
}
|
||||
$txtstr .= $this->printDataLine($d, $p);
|
||||
/*
|
||||
$values = $d->getValues();
|
||||
// don't think we need this, Sunbird does not like it in the EXDATE field
|
||||
//$values = str_replace(",", "\\,", $values);
|
||||
|
||||
$line = $d->getName() . $p . ":" . $values;
|
||||
$line = str_replace(array("<br>","<BR>","<br/>","<BR/"),"\\n",$line);
|
||||
$line = str_replace(array("\r\n","\n\r","\n","\r"),'\n',$line);
|
||||
//$line = str_replace(array(',',';','\\'), array('\\,','\\;','\\\\'),$line);
|
||||
//$line =strip_tags($line);
|
||||
$linecount = 0;
|
||||
while (strlen($line) > 0) {
|
||||
$linewidth = ($linecount == 0? 75 : 74);
|
||||
$linesize = (strlen($line) > $linewidth? $linewidth: strlen($line));
|
||||
if($linecount > 0)
|
||||
$txtstr .= " ";
|
||||
$txtstr .= substr($line,0,$linesize) . "\r\n";
|
||||
$linecount += 1;
|
||||
$line = substr($line,$linewidth);
|
||||
}
|
||||
*/
|
||||
}
|
||||
//echo $line . "\n";
|
||||
}
|
||||
if(property_exists($node,"child"))
|
||||
foreach ($node->child as $c){
|
||||
$txtstr .= $node->export($c,$level + 1);
|
||||
}
|
||||
$txtstr .= "END:" . $node->getName() . "\r\n";
|
||||
return $txtstr;
|
||||
}
|
||||
|
||||
/**
|
||||
* print an attribute line
|
||||
|
||||
* @param object $d attributes
|
||||
* @param object $p properties
|
||||
*
|
||||
*/
|
||||
function printDataLine($d, $p)
|
||||
{
|
||||
$txtstr = "";
|
||||
|
||||
$values = $d->getValues();
|
||||
// don't think we need this, Sunbird does not like it in the EXDATE field
|
||||
//$values = str_replace(",", "\\,", $values);
|
||||
|
||||
$line = $d->getName() . $p . ":" . $values;
|
||||
$line = str_replace(array("<br>","<BR>","<br/>","<BR/"),"\\n",$line);
|
||||
$line = str_replace(array("\r\n","\n\r","\n","\r"),'\n',$line);
|
||||
//$line = str_replace(array(',',';','\\'), array('\\,','\\;','\\\\'),$line);
|
||||
//$line =strip_tags($line);
|
||||
$linecount = 0;
|
||||
while (strlen($line) > 0) {
|
||||
$linewidth = ($linecount == 0? 75 : 74);
|
||||
$linesize = (strlen($line) > $linewidth? $linewidth: strlen($line));
|
||||
if($linecount > 0)
|
||||
$txtstr .= " ";
|
||||
$txtstr .= substr($line,0,$linesize) . "\r\n";
|
||||
$linecount += 1;
|
||||
$line = substr($line,$linewidth);
|
||||
}
|
||||
return $txtstr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The main iCalendar object containing ZCiCalDataNodes and ZCiCalNodes.
|
||||
*
|
||||
*/
|
||||
class ZCiCal {
|
||||
/**
|
||||
* The root node of the object tree
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $tree=null;
|
||||
/**
|
||||
* The most recently created node in the tree
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $curnode=null;
|
||||
|
||||
/**
|
||||
* The main iCalendar object containing ZCiCalDataNodes and ZCiCalNodes.
|
||||
*
|
||||
* use maxevents and startevent to read events in multiple passes (to save memory)
|
||||
*
|
||||
* @param string $data icalendar feed string (empty if creating new feed)
|
||||
*
|
||||
* @param int $maxevents maximum # of events to read
|
||||
*
|
||||
* @param int $startevent starting event to read
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
*
|
||||
*/
|
||||
function __construct($data = "", $maxevents = 1000000, $startevent = 0) {
|
||||
|
||||
if($data != ""){
|
||||
// unfold lines
|
||||
// first change all eol chars to "\n"
|
||||
$data = str_replace(array("\r\n", "\n\r", "\n", "\r"), "\n", $data);
|
||||
// now unfold lines
|
||||
//$data = str_replace(array("\n ", "\n "),"!?", $data);
|
||||
$data = str_replace(array("\n ", "\n "),"", $data);
|
||||
// replace special iCal chars
|
||||
$data = str_replace(array("\\\\","\,"),array("\\",","), $data);
|
||||
|
||||
// parse each line
|
||||
$lines = explode("\n", $data);
|
||||
|
||||
$linecount = 0;
|
||||
$eventcount = 0;
|
||||
$eventpos = 0;
|
||||
foreach($lines as $line) {
|
||||
//$line = str_replace("!?", "\n", $line); // add nl back into descriptions
|
||||
// echo ($linecount + 1) . ": " . $line . "<br/>";
|
||||
if(substr($line,0,6) == "BEGIN:") {
|
||||
// start new object
|
||||
$name = substr($line,6);
|
||||
if($name == "VEVENT")
|
||||
{
|
||||
if($eventcount < $maxevents && $eventpos >= $startevent)
|
||||
{
|
||||
$this->curnode = new ZCiCalNode($name, $this->curnode);
|
||||
if($this->tree == null)
|
||||
$this->tree = $this->curnode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->curnode = new ZCiCalNode($name, $this->curnode);
|
||||
if($this->tree == null)
|
||||
$this->tree = $this->curnode;
|
||||
}
|
||||
//echo "new node: " . $this->curnode->name . "<br/>\n";
|
||||
/*
|
||||
if($this->curnode->getParent() != null)
|
||||
echo "parent of " . $this->curnode->getName() . " is " . $this->curnode->getParent()->getName() . "<br/>";
|
||||
else
|
||||
echo "parent of " . $this->curnode->getName() . " is null<br/>";
|
||||
*/
|
||||
}
|
||||
else if(substr($line,0,4) == "END:") {
|
||||
$name = substr($line,4);
|
||||
if($name == "VEVENT")
|
||||
{
|
||||
if($eventcount < $maxevents && $eventpos >= $startevent)
|
||||
{
|
||||
$eventcount++;
|
||||
if($this->curnode->getName() != $name) {
|
||||
//panic, mismatch in iCal structure
|
||||
//die("Can't read iCal file structure, expecting " . $this->curnode->getName() . " but reading $name instead");
|
||||
throw new Exception("Can't read iCal file structure, expecting " . $this->curnode->getName() . " but reading $name instead");
|
||||
}
|
||||
if($this->curnode->getParent() != null) {
|
||||
//echo "moving up from " . $this->curnode->getName() ;
|
||||
$this->curnode = & $this->curnode->getParent();
|
||||
//echo " to " . $this->curnode->getName() . "<br/>";
|
||||
//echo $this->curnode->getName() . " has " . count($this->curnode->child) . " children<br/>";
|
||||
}
|
||||
}
|
||||
$eventpos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($this->curnode->getName() != $name) {
|
||||
//panic, mismatch in iCal structure
|
||||
//die("Can't read iCal file structure, expecting " . $this->curnode->getName() . " but reading $name instead");
|
||||
throw new Exception("Can't read iCal file structure, expecting " . $this->curnode->getName() . " but reading $name instead");
|
||||
}
|
||||
if($this->curnode->getParent() != null) {
|
||||
//echo "moving up from " . $this->curnode->getName() ;
|
||||
$this->curnode = & $this->curnode->getParent();
|
||||
//echo " to " . $this->curnode->getName() . "<br/>";
|
||||
//echo $this->curnode->getName() . " has " . count($this->curnode->child) . " children<br/>";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$datanode = new ZCiCalDataNode($line);
|
||||
if($this->curnode->getName() == "VEVENT")
|
||||
{
|
||||
if($eventcount < $maxevents && $eventpos >= $startevent)
|
||||
{
|
||||
if($datanode->getName() == "EXDATE")
|
||||
{
|
||||
if(!array_key_exists($datanode->getName(),$this->curnode->data))
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()]->value[] = $datanode->value[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!array_key_exists($datanode->getName(),$this->curnode->data))
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tnode = $this->curnode->data[$datanode->getName()];
|
||||
$this->curnode->data[$datanode->getName()] = array();
|
||||
$this->curnode->data[$datanode->getName()][] = $tnode;
|
||||
$this->curnode->data[$datanode->getName()][] = $datanode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($datanode->getName() == "EXDATE")
|
||||
{
|
||||
if(!array_key_exists($datanode->getName(),$this->curnode->data))
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()]->value[] = $datanode->value[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!array_key_exists($datanode->getName(),$this->curnode->data))
|
||||
{
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tnode = $this->curnode->data[$datanode->getName()];
|
||||
$this->curnode->data[$datanode->getName()] = array();
|
||||
$this->curnode->data[$datanode->getName()][] = $tnode;
|
||||
$this->curnode->data[$datanode->getName()][] = $datanode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$linecount++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$name = "VCALENDAR";
|
||||
$this->curnode = new ZCiCalNode($name, $this->curnode);
|
||||
$this->tree = $this->curnode;
|
||||
$datanode = new ZCiCalDataNode("VERSION:2.0");
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
|
||||
$datanode = new ZCiCalDataNode("PRODID:-//ZContent.net//ZapCalLib 1.0//EN");
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
$datanode = new ZCiCalDataNode("CALSCALE:GREGORIAN");
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
$datanode = new ZCiCalDataNode("METHOD:PUBLISH");
|
||||
$this->curnode->data[$datanode->getName()] = $datanode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CountEvents()
|
||||
*
|
||||
* Return the # of VEVENTs in the object
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
||||
function countEvents() {
|
||||
$count = 0;
|
||||
if(isset($this->tree->child)){
|
||||
foreach($this->tree->child as $child){
|
||||
if($child->getName() == "VEVENT")
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* CountVenues()
|
||||
*
|
||||
* Return the # of VVENUEs in the object
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
||||
function countVenues() {
|
||||
$count = 0;
|
||||
if(isset($this->tree->child)){
|
||||
foreach($this->tree->child as $child){
|
||||
if($child->getName() == "VVENUE")
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export object to string
|
||||
*
|
||||
* This function exports all objects to an iCalendar string
|
||||
*
|
||||
* @return string an iCalendar formatted string
|
||||
*/
|
||||
|
||||
function export() {
|
||||
return $this->tree->export($this->tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first event in object list
|
||||
* Use getNextEvent() to navigate through list
|
||||
*
|
||||
* @return object The first event, or null
|
||||
*/
|
||||
function &getFirstEvent() {
|
||||
static $nullguard = null;
|
||||
if ($this->countEvents() > 0){
|
||||
$child = $this->tree->child[0];
|
||||
$event=false;
|
||||
while(!$event && $child != null){
|
||||
if($child->getName() == "VEVENT")
|
||||
$event = true;
|
||||
else
|
||||
$child = $child->next;
|
||||
}
|
||||
return $child;
|
||||
}
|
||||
else
|
||||
return $nullguard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next event in object list
|
||||
*
|
||||
* @param object $event The current event object
|
||||
*
|
||||
* @return object Returns the next event or null if past last event
|
||||
*/
|
||||
function &getNextEvent($event){
|
||||
do{
|
||||
$event = $event->next;
|
||||
} while($event != null && $event->getName() != "VEVENT");
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first venue in object list
|
||||
* Use getNextVenue() to navigate through list
|
||||
*
|
||||
* @return object The first venue, or null
|
||||
*/
|
||||
function &getFirstVenue() {
|
||||
static $nullguard = null;
|
||||
if ($this->countVenues() > 0){
|
||||
$child = $this->tree->child[0];
|
||||
$event=false;
|
||||
while(!$event && $child != null){
|
||||
if($child->getName() == "VVENUE")
|
||||
$event = true;
|
||||
else
|
||||
$child = $child->next;
|
||||
}
|
||||
return $child;
|
||||
}
|
||||
else
|
||||
return $nullguard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next venue in object list
|
||||
*
|
||||
* @param object $venue The current venue object
|
||||
*
|
||||
* @return object Returns the next venue or null if past last venue
|
||||
*/
|
||||
function &getNextVenue($venue){
|
||||
do{
|
||||
$venue = $venue->next;
|
||||
} while($venue != null && $venue->getName() != "VVENUE");
|
||||
return $venue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first child in object list
|
||||
* Use getNextSibling() and getPreviousSibling() to navigate through list
|
||||
*
|
||||
* @param object $thisnode The parent object
|
||||
*
|
||||
* @return object The child object
|
||||
*/
|
||||
function &getFirstChild(& $thisnode){
|
||||
$nullvalue = null;
|
||||
if(count($thisnode->child) > 0) {
|
||||
//echo "moving from " . $thisnode->getName() . " to " . $thisnode->child[0]->getName() . "<br/>";
|
||||
return $thisnode->child[0];
|
||||
}
|
||||
else
|
||||
return $nullvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next sibling in object list
|
||||
*
|
||||
* @param object $thisnode The current object
|
||||
*
|
||||
* @return object Returns the next sibling
|
||||
*/
|
||||
function &getNextSibling(& $thisnode){
|
||||
return $thisnode->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get previous sibling in object list
|
||||
*
|
||||
* @param object $thisnode The current object
|
||||
*
|
||||
* @return object Returns the previous sibling
|
||||
*/
|
||||
function &getPrevSibling(& $thisnode){
|
||||
return $thisnode->prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read date/time in iCal formatted string
|
||||
*
|
||||
* @param string iCal formated date/time string
|
||||
*
|
||||
* @return int Unix timestamp
|
||||
* @deprecated Use ZDateHelper::toUnixDateTime() instead
|
||||
*/
|
||||
|
||||
function toUnixDateTime($datetime){
|
||||
$year = substr($datetime,0,4);
|
||||
$month = substr($datetime,4,2);
|
||||
$day = substr($datetime,6,2);
|
||||
$hour = 0;
|
||||
$minute = 0;
|
||||
$second = 0;
|
||||
if(strlen($datetime) > 8 && $datetime[8] == "T") {
|
||||
$hour = substr($datetime,9,2);
|
||||
$minute = substr($datetime,11,2);
|
||||
$second = substr($datetime,13,2);
|
||||
}
|
||||
$d1 = mktime($hour, $minute, $second, $month, $day, $year);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* fromUnixDateTime()
|
||||
*
|
||||
* Take Unix timestamp and format to iCal date/time string
|
||||
*
|
||||
* @param int $datetime Unix timestamp, leave blank for current date/time
|
||||
*
|
||||
* @return string formatted iCal date/time string
|
||||
* @deprecated Use ZDateHelper::fromUnixDateTimetoiCal() instead
|
||||
*/
|
||||
|
||||
static function fromUnixDateTime($datetime = null){
|
||||
date_default_timezone_set('UTC');
|
||||
if($datetime == null)
|
||||
$datetime = time();
|
||||
return date("Ymd\THis",$datetime);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fromUnixDate()
|
||||
*
|
||||
* Take Unix timestamp and format to iCal date string
|
||||
*
|
||||
* @param int $datetime Unix timestamp, leave blank for current date/time
|
||||
*
|
||||
* @return string formatted iCal date string
|
||||
* @deprecated Use ZDateHelper::fromUnixDateTimetoiCal() instead
|
||||
*/
|
||||
|
||||
static function fromUnixDate($datetime = null){
|
||||
date_default_timezone_set('UTC');
|
||||
if($datetime == null)
|
||||
$datetime = time();
|
||||
return date("Ymd",$datetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format into iCal time format from SQL date or SQL date-time format
|
||||
*
|
||||
* @param string $datetime SQL date or SQL date-time string
|
||||
*
|
||||
* @return string iCal formatted string
|
||||
* @deprecated Use ZDateHelper::fromSqlDateTime() instead
|
||||
*/
|
||||
static function fromSqlDateTime($datetime = ""){
|
||||
if($datetime == "")
|
||||
$datetime = ZDateHelper::toSqlDateTime();
|
||||
if(strlen($datetime) > 10)
|
||||
return sprintf('%04d%02d%02dT%02d%02d%02d',substr($datetime,0,4),substr($datetime,5,2),substr($datetime,8,2),
|
||||
substr($datetime,11,2),substr($datetime,14,2),substr($datetime,17,2));
|
||||
else
|
||||
return sprintf('%04d%02d%02d',substr($datetime,0,4),substr($datetime,5,2),substr($datetime,8,2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format iCal time format to either SQL date or SQL date-time format
|
||||
*
|
||||
* @param string $datetime icalendar formatted date or date-time
|
||||
* @return string SQL date or SQL date-time string
|
||||
* @deprecated Use ZDateHelper::toSqlDateTime() instead
|
||||
*/
|
||||
static function toSqlDateTime($datetime = ""){
|
||||
if($datetime == "")
|
||||
return ZDateHelper::toSqlDateTime();
|
||||
if(strlen($datetime) > 10)
|
||||
return sprintf('%04d-%02d-%02d %02d:%02d:%02d',substr($datetime,0,4),substr($datetime,5,2),substr($datetime,8,2),
|
||||
substr($datetime,11,2),substr($datetime,14,2),substr($datetime,17,2));
|
||||
else
|
||||
return sprintf('%04d-%02d-%02d',substr($datetime,0,4),substr($datetime,5,2),substr($datetime,8,2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull timezone data from node and put in array
|
||||
*
|
||||
* Returning array contains the following array keys: tzoffsetfrom, tzoffsetto, tzname, dtstart, rrule
|
||||
*
|
||||
* @param array $node timezone object
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function getTZValues($node){
|
||||
$tzvalues = array();
|
||||
|
||||
$tnode = @$node->data['TZOFFSETFROM'];
|
||||
if($tnode != null){
|
||||
$tzvalues["tzoffsetfrom"] = $tnode->getValues();
|
||||
}
|
||||
|
||||
$tnode = @$node->data['TZOFFSETTO'];
|
||||
if($tnode != null){
|
||||
$tzvalues["tzoffsetto"] = $tnode->getValues();
|
||||
}
|
||||
|
||||
$tnode = @$node->data['TZNAME'];
|
||||
if($tnode != null){
|
||||
$tzvalues["tzname"] = $tnode->getValues();
|
||||
}
|
||||
else
|
||||
$tzvalues["tzname"] = "";
|
||||
|
||||
$tnode = @$node->data['DTSTART'];
|
||||
if($tnode != null){
|
||||
$tzvalues["dtstart"] = ZDateHelper::fromiCaltoUnixDateTime($tnode->getValues());
|
||||
}
|
||||
|
||||
$tnode = @$node->data['RRULE'];
|
||||
if($tnode != null){
|
||||
$tzvalues["rrule"] = $tnode->getValues();
|
||||
//echo "rule: " . $tzvalues["rrule"] . "<br/>\n";
|
||||
}
|
||||
else{
|
||||
// no rule specified, let's create one from based on the date
|
||||
$date = getdate($tzvalues["dtstart"]);
|
||||
$month = $date["mon"];
|
||||
$day = $date["mday"];
|
||||
$tzvalues["rrule"] = "FREQ=YEARLY;INTERVAL=1;BYMONTH=$month;BYMONTHDAY=$day";
|
||||
}
|
||||
|
||||
return $tzvalues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape slashes, commas and semicolons in strings
|
||||
*
|
||||
* @param string $content
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static function formatContent($content)
|
||||
{
|
||||
$content = str_replace(array('\\' , ',' , ';' ), array('\\\\' , '\\,' , '\\;' ),$content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,796 @@
|
|||
<?php
|
||||
/**
|
||||
* recurringdate.php - create list of dates from recurring rule
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
// No direct access
|
||||
defined('_ZAPCAL') or die( 'Restricted access' );
|
||||
|
||||
/**
|
||||
* Zap Calendar Recurring Date Helper Class
|
||||
*
|
||||
* Class to expand recurring rule to a list of dates
|
||||
*/
|
||||
class ZCRecurringDate {
|
||||
/**
|
||||
* rules string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $rules = "";
|
||||
|
||||
/**
|
||||
* start date in Unix Timestamp format (local timezone)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $startdate = null;
|
||||
|
||||
/**
|
||||
* repeating frequency type (i.e. "y" for yearly, "m" for monthly)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $freq = null;
|
||||
|
||||
/**
|
||||
* timezone of event (using PHP timezones)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $tzid = null;
|
||||
|
||||
/**
|
||||
* repeat mode ('c': count, 'u': until)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $repeatmode=null;
|
||||
|
||||
/**
|
||||
* repeat until date (in UTC Unix Timestamp format)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $until=null;
|
||||
|
||||
/**
|
||||
* repeat count when repeat mode is 'c'
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $count=0;
|
||||
|
||||
/**
|
||||
* array of repeat by seconds values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $bysecond=array();
|
||||
|
||||
/**
|
||||
* array of repeat by minutes values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $byminute=array();
|
||||
|
||||
/**
|
||||
* array of repeat by hour values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $byhour=array();
|
||||
|
||||
/**
|
||||
* array of repeat by day values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $byday=array();
|
||||
|
||||
/**
|
||||
* array of repeat by month day values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $bymonthday=array();
|
||||
|
||||
/**
|
||||
* array of repeat by month values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $bymonth=array();
|
||||
|
||||
/**
|
||||
* array of repeat by year values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $byyear=array();
|
||||
|
||||
/**
|
||||
* array of repeat by setpos values
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $bysetpos=array();
|
||||
|
||||
/**
|
||||
* inteval of repeating event (i.e. every 2 weeks, every 6 months)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $interval = 1;
|
||||
|
||||
/**
|
||||
* debug level (for testing only)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
var $debug = 0;
|
||||
|
||||
/**
|
||||
* error string (future use)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $error;
|
||||
|
||||
/**
|
||||
* array of exception dates in Unix Timestamp format (UTC dates)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $exdates=array();
|
||||
|
||||
/**
|
||||
* Expand recurring rule to a list of dates
|
||||
*
|
||||
* @param string $rules iCalendar rules string
|
||||
* @param integer $startdate start date in Unix Timestamp format
|
||||
* @param array $exdates array of exception dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*/
|
||||
function __construct($rules, $startdate, $exdates = array(),$tzid = "UTC"){
|
||||
if(strlen($rules) > 0){
|
||||
//move exdates to event timezone for comparing with event date
|
||||
for($i = 0; $i < count($exdates); $i++)
|
||||
{
|
||||
$exdates[$i] = ZDateHelper::toUnixDateTime(ZDateHelper::toLocalDateTime(ZDateHelper::toSQLDateTime($exdates[$i]),$tzid));
|
||||
}
|
||||
|
||||
$rules=str_replace("\'","",$rules);
|
||||
$this->rules = $rules;
|
||||
if($startdate == null){
|
||||
// if not specified, use start date of beginning of last year
|
||||
$tdate=getdate();
|
||||
$startdate=mktime(0,0,0,1,1,$tdate["year"] - 1);
|
||||
}
|
||||
$this->startdate = $startdate;
|
||||
$this->tzid = $tzid;
|
||||
$this->exdates = $exdates;
|
||||
|
||||
$rules=explode(";", $rules);
|
||||
$ruletype = "";
|
||||
foreach($rules as $rule){
|
||||
$item=explode("=",$rule);
|
||||
//echo $item[0] . "=" . $item[1] . "<br/>\n";
|
||||
switch($item[0]){
|
||||
case "FREQ":
|
||||
switch($item[1]){
|
||||
case "YEARLY":
|
||||
$this->freq="y";
|
||||
break;
|
||||
case "MONTHLY":
|
||||
$this->freq="m";
|
||||
break;
|
||||
case "WEEKLY":
|
||||
$this->freq="w";
|
||||
break;
|
||||
case "DAILY":
|
||||
$this->freq="d";
|
||||
break;
|
||||
case "HOURLY":
|
||||
$this->freq="h";
|
||||
break;
|
||||
case "MINUTELY":
|
||||
$this->freq="i";
|
||||
break;
|
||||
case "SECONDLY":
|
||||
$this->freq="s";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "INTERVAL":
|
||||
$this->interval = $item[1];
|
||||
break;
|
||||
case "BYSECOND":
|
||||
$this->bysecond = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYMINUTE":
|
||||
$this->byminute = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYHOUR":
|
||||
$this->byhour = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYDAY":
|
||||
$this->byday = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYMONTHDAY":
|
||||
$this->bymonthday = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYMONTH":
|
||||
$this->bymonth = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "BYYEAR":
|
||||
$this->byyear = explode(",",$item[1]);
|
||||
$ruletype = $item[0];
|
||||
break;
|
||||
case "COUNT":
|
||||
$this->count = intval($item[1]);
|
||||
$this->repeatmode = "c";
|
||||
break;
|
||||
case "BYSETPOS":
|
||||
$this->bysetpos = explode(",",$item[1]);
|
||||
break;
|
||||
case "UNTIL":
|
||||
$this->until = ZDateHelper::fromiCaltoUnixDateTime($item[1]);
|
||||
$this->repeatmode = "u";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(count($this->bysetpos) > 0){
|
||||
switch($ruletype){
|
||||
case "BYYEAR":
|
||||
$this->byyear = $this->bySetPos($this->byyear,$this->bysetpos);
|
||||
break;
|
||||
case "BYMONTH":
|
||||
$this->bymonth = $this->bySetPos($this->bymonth,$this->bysetpos);
|
||||
break;
|
||||
case "BYMONTHDAY":
|
||||
$this->bymonthday = $this->bySetPos($this->bymonthday,$this->bysetpos);
|
||||
break;
|
||||
case "BYDAY":
|
||||
$this->byday = $this->bySetPos($this->byday,$this->bysetpos);
|
||||
break;
|
||||
case "BYHOUR":
|
||||
$this->byhour = $this->bySetPos($this->byhour,$this->bysetpos);
|
||||
break;
|
||||
case "BYMINUTE":
|
||||
$this->byminute = $this->bySetPos($this->byminute,$this->bysetpos);
|
||||
break;
|
||||
case "BYSECOND":
|
||||
$this->bysecond = $this->bySetPos($this->bysecond,$this->bysetpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bysetpos rule support
|
||||
*
|
||||
* @param array $bytype
|
||||
* @param array $bysetpos
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function bySetPos($bytype, $bysetpos){
|
||||
$result = array();
|
||||
for($i=0; $i < count($bysetpos); $i++){
|
||||
for($j=0; $j < count($bytype); $j++){
|
||||
$result[] = $bysetpos[$i] . $bytype[$j];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* save error
|
||||
*
|
||||
* @param string $msg
|
||||
*/
|
||||
function setError($msg){
|
||||
$this->error = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error message
|
||||
*
|
||||
* @return string error message
|
||||
*/
|
||||
function getError(){
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* set debug level (0: none, 1: minimal, 2: more output)
|
||||
*
|
||||
* @param integer $level
|
||||
*
|
||||
*/
|
||||
function setDebug($level)
|
||||
{
|
||||
$this->debug = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* display debug message
|
||||
*
|
||||
* @param integer $level
|
||||
* @param string $msg
|
||||
*/
|
||||
function debug($level, $msg){
|
||||
if($this->debug >= $level)
|
||||
echo $msg . "<br/>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by year
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byYear($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byYear(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
if(count($this->byyear) > 0){
|
||||
foreach($this->byyear as $year){
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($t[hours],$t[minutes],$t[seconds],$t[month],$t[mday],$year);
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byMonth($wdate, $enddate, $rdates, $tzid);
|
||||
if($count == 0) {
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates))
|
||||
$count = $this->byMonth($startdate, $enddate, $rdates, $tzid);
|
||||
self::debug(1,"byYear() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by month
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byMonth($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byMonth(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
if(count($this->bymonth) > 0){
|
||||
foreach($this->bymonth as $month){
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($t["hours"],$t["minutes"],$t["seconds"],$month,$t["mday"],$t["year"]);
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byMonthDay($wdate, $enddate, $rdates, $tzid);
|
||||
if($count == 0) {
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates))
|
||||
$count = $this->byMonthDay($startdate, $enddate, $rdates, $tzid);
|
||||
self::debug(1,"byMonth() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by month day
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byMonthDay($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byMonthDay(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
self::debug(1,"start date: " . ZDateHelper::toSqlDateTime($startdate));
|
||||
if(count($this->bymonthday) > 0){
|
||||
foreach($this->bymonthday as $day){
|
||||
$day = intval($day);
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($t['hours'],$t['minutes'],$t['seconds'],$t['mon'],$day,$t['year']);
|
||||
self::debug(2,"mktime(" . $t['hours'] . ", " . $t['minutes']
|
||||
. ", " . $t['mon'] . ", " . $day . ", " . $t['year'] . ") returned $wdate");
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byDay($wdate, $enddate, $rdates, $tzid);
|
||||
if($count == 0) {
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates)) {
|
||||
self::debug(1,"start date: " . ZDateHelper::toSqlDateTime($startdate));
|
||||
$count = $this->byDay($startdate, $enddate, $rdates, $tzid);
|
||||
}
|
||||
self::debug(1,"byMonthDay() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by day
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byDay($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byDay(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$days = array(
|
||||
"SU" => 0,
|
||||
"MO" => 1,
|
||||
"TU" => 2,
|
||||
"WE" => 3,
|
||||
"TH" => 4,
|
||||
"FR" => 5,
|
||||
"SA" => 6);
|
||||
$idays = array(
|
||||
0 => "SU",
|
||||
1 => "MO",
|
||||
2 => "TU",
|
||||
3 => "WE",
|
||||
4 => "TH",
|
||||
5 => "FR",
|
||||
6 => "SA");
|
||||
|
||||
$count = 0;
|
||||
if(count($this->byday) > 0){
|
||||
if(empty($this->byday[0]))
|
||||
{
|
||||
$this->byday[0] = $idays[date("w",$startdate)];
|
||||
}
|
||||
foreach($this->byday as $tday){
|
||||
$t = getdate($startdate);
|
||||
$day = substr($tday,strlen($tday) - 2);
|
||||
if(strlen($day) < 2)
|
||||
{
|
||||
// missing start day, use current date for DOW
|
||||
$day = $idays[date("w",$startdate)];
|
||||
}
|
||||
if(strlen($tday) > 2) {
|
||||
$imin = 1;
|
||||
$imax = 5; // max # of occurances in a month
|
||||
if(strlen($tday) > 2)
|
||||
$imin = $imax = substr($tday,0,strlen($tday) - 2);
|
||||
self::debug(2,"imin: $imin, imax: $imax, tday: $tday, day: $day, daynum: {$days[$day]}");
|
||||
for($i = $imin; $i <= $imax; $i++){
|
||||
$wdate = ZDateHelper::getDateFromDay($startdate,$i-1,$days[$day],$tzid);
|
||||
self::debug(2,"getDateFromDay(" . ZDateHelper::toSqlDateTime($startdate)
|
||||
. ",$i,{$days[$day]}) returned " . ZDateHelper::toSqlDateTime($wdate));
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byHour($wdate, $enddate, $rdates);
|
||||
if($count == 0){
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// day of week version
|
||||
$startdate_dow = date("w",$startdate);
|
||||
$datedelta = $days[$day] - $startdate_dow;
|
||||
self::debug(2, "start_dow: $startdate_dow, datedelta: $datedelta");
|
||||
if($datedelta >= 0)
|
||||
{
|
||||
$wdate = ZDateHelper::addDate($startdate,0,0,0,0,$datedelta,0,$this->tzid);
|
||||
self::debug(2, "wdate: " . ZDateHelper::toSqlDateTime($wdate));
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byHour($wdate, $enddate, $rdates);
|
||||
if($count == 0){
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
self::debug(2,"adding date " . ZDateHelper::toSqlDateTime($wdate) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates))
|
||||
$count = $this->byHour($startdate, $enddate, $rdates);
|
||||
self::debug(1,"byDay() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by hour
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byHour($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byHour(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
if(count($this->byhour) > 0){
|
||||
foreach($this->byhour as $hour){
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($hour,$t["minutes"],$t["seconds"],$t["mon"],$t["mday"],$t["year"]);
|
||||
self::debug(2,"checking date/time " . ZDateHelper::toSqlDateTime($wdate));
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->byMinute($wdate, $enddate, $rdates);
|
||||
if($count == 0) {
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates))
|
||||
$count = $this->byMinute($startdate, $enddate, $rdates);
|
||||
self::debug(1,"byHour() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get repeating dates by minute
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function byMinute($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"byMinute(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
if(count($this->byminute) > 0){
|
||||
foreach($this->byminute as $minute){
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($t["hours"],$minute,$t["seconds"],$t["mon"],$t["mday"],$t["year"]);
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$count = $this->bySecond($wdate, $enddate, $rdates);
|
||||
if($count == 0) {
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!$this->maxDates($rdates))
|
||||
$count = $this->bySecond($startdate, $enddate, $rdates);
|
||||
self::debug(1,"byMinute() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
/**
|
||||
* Get repeating dates by second
|
||||
*
|
||||
* @param integer $startdate start date of repeating events, in Unix timestamp format
|
||||
* @param integer $enddate end date of repeating events, in Unix timestamp format
|
||||
* @param array $rdates array to contain expanded repeating dates
|
||||
* @param string $tzid timezone of event (using PHP timezones)
|
||||
*
|
||||
* @return integer count of dates
|
||||
*/
|
||||
private function bySecond($startdate, $enddate, &$rdates, $tzid="UTC"){
|
||||
self::debug(1,"bySecond(" . ZDateHelper::toSqlDateTime($startdate) . ","
|
||||
. ZDateHelper::toSqlDateTime($enddate) . "," . count($rdates) . " dates)");
|
||||
$count = 0;
|
||||
if(count($this->bysecond) > 0){
|
||||
foreach($this->bysecond as $second){
|
||||
$t = getdate($startdate);
|
||||
$wdate = mktime($t["hours"],$t["minutes"],$second,$t["mon"],$t["mday"],$t["year"]);
|
||||
if($startdate <= $wdate && $wdate < $enddate && !$this->maxDates($rdates)){
|
||||
$rdates[] = $wdate;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
self::debug(1,"bySecond() returned " . $count );
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the loop has reached the end date
|
||||
*
|
||||
* @param array $rdates array of repeating dates
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function maxDates($rdates){
|
||||
if($this->repeatmode == "c" && count($rdates) >= $this->count)
|
||||
return true; // exceeded count
|
||||
else if(count($rdates) > 0 && $this->repeatmode == "u" && $rdates[count($rdates) - 1] > $this->until){
|
||||
return true; //past date
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of dates from recurring rule
|
||||
*
|
||||
* @param $maxdate integer maximum date to appear in repeating dates in Unix timestamp format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDates($maxdate = null){
|
||||
//$this->debug = 2;
|
||||
self::debug(1,"getDates()");
|
||||
$nextdate = $enddate = $this->startdate;
|
||||
$rdates = array();
|
||||
$done = false;
|
||||
$eventcount = 0;
|
||||
$loopcount = 0;
|
||||
self::debug(2,"freq: " . $this->freq . ", interval: " . $this->interval);
|
||||
while(!$done){
|
||||
self::debug(1,"<b>*** Frequency ({$this->freq}) loop pass $loopcount ***</b>");
|
||||
switch($this->freq){
|
||||
case "y":
|
||||
if($eventcount > 0)
|
||||
{
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,0,0,$this->interval,$this->tzid);
|
||||
self::debug(2,"addDate() returned " . ZDateHelper::toSqlDateTime($nextdate));
|
||||
if(!empty($this->byday)){
|
||||
$t = getdate($nextdate);
|
||||
$nextdate = gmmktime($t["hours"],$t["minutes"],$t["seconds"],$t["mon"],1,$t["year"]);
|
||||
}
|
||||
self::debug(2,"nextdate set to $nextdate (". ZDateHelper::toSQLDateTime($nextdate) . ")");
|
||||
}
|
||||
$enddate=ZDateHelper::addDate($nextdate,0,0,0,0,0,1);
|
||||
break;
|
||||
case "m":
|
||||
if($eventcount > 0)
|
||||
{
|
||||
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,$this->interval,0,0,$this->tzid);
|
||||
self::debug(2,"addDate() returned " . ZDateHelper::toSqlDateTime($nextdate));
|
||||
}
|
||||
if(count($this->byday) > 0)
|
||||
{
|
||||
$t = getdate($nextdate);
|
||||
if($t["mday"] > 28)
|
||||
{
|
||||
//check for short months when using month by day, make sure we do not overshoot the counter and skip a month
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,$this->interval,0,0,$this->tzid);
|
||||
$t2 = getdate($nextdate);
|
||||
if($t2["mday"] < $t["mday"])
|
||||
{
|
||||
// oops, skipped a month, backup to previous month
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,0,$t2["mday"] - $t["mday"],0,$this->tzid);
|
||||
}
|
||||
}
|
||||
$t = getdate($nextdate);
|
||||
$nextdate = mktime($t["hours"],$t["minutes"],$t["seconds"],$t["mon"],1,$t["year"]);
|
||||
}
|
||||
self::debug(2,"nextdate set to $nextdate (". ZDateHelper::toSQLDateTime($nextdate) . ")");
|
||||
$enddate=ZDateHelper::addDate($nextdate,0,0,0,$this->interval,0,0);
|
||||
break;
|
||||
case "w":
|
||||
if($eventcount == 0)
|
||||
$nextdate=$nextdate;
|
||||
else {
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,0,$this->interval*7,0,$this->tzid);
|
||||
if(count($this->byday) > 0){
|
||||
$dow = date("w", $nextdate);
|
||||
// move to beginning of week (Sunday)
|
||||
$bow = 0;
|
||||
$diff = $bow - $dow;
|
||||
if($diff > 0)
|
||||
$diff = $diff - 7;
|
||||
$nextdate = ZDateHelper::addDate($nextdate,0,0,0,0,$diff,0);
|
||||
}
|
||||
self::debug(2,"nextdate set to $nextdate (". ZDateHelper::toSQLDateTime($nextdate) . ")");
|
||||
}
|
||||
$enddate=ZDateHelper::addDate($nextdate,0,0,0,0,$this->interval*7,0);
|
||||
break;
|
||||
case "d":
|
||||
$nextdate=($eventcount==0?$nextdate:
|
||||
ZDateHelper::addDate($nextdate,0,0,0,0,$this->interval,0,$this->tzid));
|
||||
$enddate=ZDateHelper::addDate($nextdate,0,0,0,0,1,0);
|
||||
break;
|
||||
}
|
||||
|
||||
$count = $this->byYear($nextdate,$enddate,$rdates,$this->tzid);
|
||||
$eventcount += $count;
|
||||
if($maxdate > 0 && $maxdate < $nextdate)
|
||||
{
|
||||
array_pop($rdates);
|
||||
$done = true;
|
||||
}
|
||||
else if($count == 0 && !$this->maxDates($rdates)){
|
||||
$rdates[] = $nextdate;
|
||||
$eventcount++;
|
||||
}
|
||||
if($this->maxDates($rdates))
|
||||
$done = true;
|
||||
|
||||
$year = date("Y", $nextdate);
|
||||
if($year > _ZAPCAL_MAXYEAR)
|
||||
{
|
||||
$done = true;
|
||||
}
|
||||
$loopcount++;
|
||||
if($loopcount > _ZAPCAL_MAXYEAR){
|
||||
$done = true;
|
||||
throw new Exception("Infinite loop detected in getDates()");
|
||||
}
|
||||
}
|
||||
if($this->repeatmode == "u" && $rdates[count($rdates) - 1] > $this->until){
|
||||
// erase last item
|
||||
array_pop($rdates);
|
||||
}
|
||||
$count1 = count($rdates);
|
||||
$rdates = array_unique($rdates);
|
||||
$count2 = count($rdates);
|
||||
$dups = $count1 - $count2;
|
||||
$excount = 0;
|
||||
|
||||
foreach($this->exdates as $exdate)
|
||||
{
|
||||
if($pos = array_search($exdate,$rdates))
|
||||
{
|
||||
array_splice($rdates,$pos,1);
|
||||
$excount++;
|
||||
}
|
||||
}
|
||||
self::debug(1,"getDates() returned " . count($rdates) . " dates, removing $dups duplicates, $excount exceptions");
|
||||
|
||||
|
||||
if($this->debug >= 2)
|
||||
{
|
||||
self::debug(2,"Recurring Dates:");
|
||||
foreach($rdates as $rdate)
|
||||
{
|
||||
$d = getdate($rdate);
|
||||
self::debug(2,ZDateHelper::toSQLDateTime($rdate) . " " . $d["wday"] );
|
||||
}
|
||||
self::debug(2,"Exception Dates:");
|
||||
foreach($this->exdates as $exdate)
|
||||
{
|
||||
self::debug(2, ZDateHelper::toSQLDateTime($exdate));
|
||||
}
|
||||
//exit;
|
||||
}
|
||||
|
||||
return $rdates;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
/**
|
||||
* timezone.php - create timezone data for use in icalendar file
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
// No direct access
|
||||
defined('_ZAPCAL') or die( 'Restricted access' );
|
||||
|
||||
/**
|
||||
* Zap Calendar Time Zone Helper Class
|
||||
*
|
||||
* Class to help create timezone section of iCalendar file
|
||||
*
|
||||
* @copyright Copyright (C) 2006 - 2016 by Dan Cogliano
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
class ZCTimeZoneHelper {
|
||||
|
||||
/**
|
||||
* getTZNode creates VTIMEZONE section in an iCalendar file
|
||||
*
|
||||
* @param @startyear int start year of date range
|
||||
*
|
||||
* @param @endyear int end year of date range
|
||||
*
|
||||
* @param $tzid string PHP timezone, use underscore for multiple words (i.e. "New_York" for "New York")
|
||||
*
|
||||
* @param $parentnode object iCalendar object where VTIMEZONE will be created
|
||||
*
|
||||
* @return object return VTIMEZONE object
|
||||
*/
|
||||
static function getTZNode($startyear, $endyear, $tzid, $parentnode)
|
||||
{
|
||||
$tzmins = array();
|
||||
$tzmaxs = array();
|
||||
if(!array_key_exists($tzid,$tzmins) || $tzmins[$tzid] > $startyear)
|
||||
{
|
||||
$tzmins[$tzid] = $startyear;
|
||||
}
|
||||
if(!array_key_exists($tzid,$tzmaxs) || $tzmaxs[$tzid] < $endyear)
|
||||
{
|
||||
$tzmaxs[$tzid] = $endyear;
|
||||
}
|
||||
|
||||
foreach(array_keys($tzmins) as $tzid)
|
||||
{
|
||||
$tmin = $tzmins[$tzid] - 1;
|
||||
if(array_key_exists($tzid,$tzmaxs))
|
||||
{
|
||||
$tmax = $tzmaxs[$tzid] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tmax = $tzmins[$tzid] + 1;
|
||||
}
|
||||
$tstart = gmmktime(0,0,0,1,1,$tmin);
|
||||
$tend = gmmktime(23,59,59,12,31,$tmax);
|
||||
$tz = new DateTimeZone($tzid);
|
||||
$transitions = $tz->getTransitions($tstart,$tend);
|
||||
$tzobj = new ZCiCalNode("VTIMEZONE", $parentnode, true);
|
||||
$datanode = new ZCiCalDataNode("TZID:" . str_replace("_"," ",$tzid));
|
||||
$tzobj->data[$datanode->getName()] = $datanode;
|
||||
$count = 0;
|
||||
$lasttransition = null;
|
||||
if(count($transitions) == 1)
|
||||
{
|
||||
// not enough transitions found, probably UTC
|
||||
// lets add fake transition at end for those systems that need it (i.e. Outlook)
|
||||
|
||||
$t2 = array();
|
||||
$t2["isdst"] = $transitions[0]["isdst"];
|
||||
$t2["offset"] = $transitions[0]["offset"];
|
||||
$t2["ts"] = $tstart;
|
||||
$t2["abbr"] = $transitions[0]["abbr"];
|
||||
$transitions[] = $t2;
|
||||
}
|
||||
foreach($transitions as $transition)
|
||||
{
|
||||
$count++;
|
||||
if($count == 1)
|
||||
{
|
||||
$lasttransition = $transition;
|
||||
continue; // skip first item
|
||||
}
|
||||
if($transition["isdst"] == 1)
|
||||
{
|
||||
$tobj = new ZCiCalNode("DAYLIGHT", $tzobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
$tobj = new ZCiCalNode("STANDARD", $tzobj);
|
||||
}
|
||||
//$tzobj->data[$tobj->getName()] == $tobj;
|
||||
|
||||
// convert timestamp to local time zone
|
||||
$ts = ZDateHelper::toUnixDateTime(ZDateHelper::toLocalDateTime(ZDateHelper::toSQLDateTime($transition["ts"]),$tzid));
|
||||
$datanode = new ZCiCalDataNode("DTSTART:".ZDateHelper::toICalDateTime($ts));
|
||||
$tobj->data[$datanode->getName()] = $datanode;
|
||||
//echo $ts . " => " . ZDateHelper::toICalDateTime($ts) . "<br/>\n"; exit;
|
||||
$toffset = $lasttransition["offset"];
|
||||
$thours = intval($toffset/60/60);
|
||||
$tmins = abs($toffset)/60 - intval(abs($toffset)/60/60)*60;
|
||||
if($thours < 0)
|
||||
{
|
||||
$offset = sprintf("%03d%02d",$thours,$tmins);
|
||||
}
|
||||
else
|
||||
{
|
||||
$offset = sprintf("+%02d%02d",$thours,$tmins);
|
||||
}
|
||||
$datanode = new ZCiCalDataNode("TZOFFSETFROM:".$offset);
|
||||
$tobj->data[$datanode->getName()] = $datanode;
|
||||
|
||||
$toffset = $transition["offset"];
|
||||
$thours = intval($toffset/60/60);
|
||||
$tmins = abs($toffset)/60 - intval(abs($toffset)/60/60)*60;
|
||||
if($thours < 0)
|
||||
{
|
||||
$offset = sprintf("%03d%02d",$thours,$tmins);
|
||||
}
|
||||
else
|
||||
{
|
||||
$offset = sprintf("+%02d%02d",$thours,$tmins);
|
||||
}
|
||||
$datanode = new ZCiCalDataNode("TZOFFSETTO:".$offset);
|
||||
$tobj->data[$datanode->getName()] = $datanode;
|
||||
|
||||
$datanode = new ZCiCalDataNode("TZNAME:".$transition["abbr"]);
|
||||
$tobj->data[$datanode->getName()] = $datanode;
|
||||
|
||||
$lasttransition = $transition;
|
||||
}
|
||||
}
|
||||
return $tzobj;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* zapcallib.php
|
||||
*
|
||||
* @package ZapCalLib
|
||||
* @author Dan Cogliano <http://zcontent.net>
|
||||
* @copyright Copyright (C) 2006 - 2017 by Dan Cogliano
|
||||
* @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html>
|
||||
* @link http://icalendar.org/php-library.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* used by ZapCalLib
|
||||
* @var integer
|
||||
*/
|
||||
define('_ZAPCAL',1);
|
||||
|
||||
if(!defined('_ZAPCAL_BASE'))
|
||||
{
|
||||
/**
|
||||
* the base folder of the library
|
||||
* @var string
|
||||
*/
|
||||
define('_ZAPCAL_BASE',__DIR__);
|
||||
}
|
||||
|
||||
require_once(_ZAPCAL_BASE . '/includes/framework.php');
|
||||
|
||||
455
post/ticket.php
455
post/ticket.php
File diff suppressed because it is too large
Load Diff
|
|
@ -2,7 +2,7 @@
|
|||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-calendar-check mr-2"></i>New Scheduled Ticket</h5>
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-calendar-check mr-2"></i>New Recurring Ticket</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
|
|
@ -25,26 +25,28 @@
|
|||
$contact_id = intval($row['contact_id']);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$contact_primary = intval($row['contact_primary']);
|
||||
if($contact_primary == 1) {
|
||||
if ($contact_primary == 1) {
|
||||
$contact_primary_display = " (Primary)";
|
||||
} else {
|
||||
$contact_primary_display = "";
|
||||
}
|
||||
$contact_technical = intval($row['contact_technical']);
|
||||
if($contact_technical == 1) {
|
||||
if ($contact_technical == 1) {
|
||||
$contact_technical_display = " (Technical)";
|
||||
} else {
|
||||
$contact_technical_display = "";
|
||||
}
|
||||
$contact_title = nullable_htmlentities($row['contact_title']);
|
||||
if(!empty($contact_title)) {
|
||||
if (!empty($contact_title)) {
|
||||
$contact_title_display = " - $contact_title";
|
||||
} else {
|
||||
$contact_title_display = "";
|
||||
}
|
||||
|
||||
?>
|
||||
<option value="<?php echo $contact_id; ?>" <?php if ($contact_primary == 1) { echo "selected"; } ?>><?php echo "$contact_name$contact_title_display$contact_primary_display$contact_technical_display"; ?></option>
|
||||
|
||||
?>
|
||||
<option value="<?php echo $contact_id; ?>" <?php if ($contact_primary == 1) {
|
||||
echo "selected";
|
||||
} ?>><?php echo "$contact_name$contact_title_display$contact_primary_display$contact_technical_display"; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -64,7 +66,7 @@
|
|||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$selectable_client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
?>
|
||||
?>
|
||||
<option value="<?php echo $selectable_client_id; ?>"><?php echo $client_name; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
|
@ -139,7 +141,7 @@
|
|||
while ($row = mysqli_fetch_array($sql_assets)) {
|
||||
$asset_id_select = intval($row['asset_id']);
|
||||
$asset_name_select = nullable_htmlentities($row['asset_name']);
|
||||
?>
|
||||
?>
|
||||
<option value="<?php echo $asset_id_select; ?>"><?php echo $asset_name_select; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
|
@ -161,4 +163,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -100,4 +100,4 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -23,59 +23,60 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-calendar-check mr-2"></i>Scheduled Tickets</h3>
|
||||
<div class='card-tools'>
|
||||
<div class="float-left">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addScheduledTicketModal">
|
||||
<i class="fas fa-plus mr-2"></i>New Scheduled Ticket
|
||||
</button>
|
||||
</div>
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-calendar-check mr-2"></i>Recurring Tickets</h3>
|
||||
<div class='card-tools'>
|
||||
<div class="float-left">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addScheduledTicketModal">
|
||||
<i class="fas fa-plus mr-2"></i>New Recurring Ticket
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="card-body">
|
||||
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Scheduled Tickets">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {
|
||||
echo stripslashes(nullable_htmlentities($q));
|
||||
} ?>" placeholder="Search Scheduled Tickets">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
|
||||
<div class="dropdown float-right" id="bulkActionButton" hidden>
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<button class="dropdown-item text-danger text-bold"
|
||||
type="submit" form="multi_actions" name="bulk_delete_scheduled_tickets">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="col-md-8">
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<div class="dropdown float-right" id="bulkActionButton" hidden>
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<button class="dropdown-item text-danger text-bold" type="submit" form="multi_actions" name="bulk_delete_scheduled_tickets">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="bulkActions" action="post.php" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="<?php if (!$num_rows[0]) {
|
||||
echo "d-none";
|
||||
} ?>">
|
||||
<div class="table-responsive-sm">
|
||||
|
||||
<form id="bulkActions" action="post.php" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="<?php if (!$num_rows[0]) {
|
||||
echo "d-none";
|
||||
} ?>">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
|
|
@ -89,9 +90,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
<th><a class="text-dark">Next Run Date</a></th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
|
||||
|
|
@ -103,7 +104,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
|
||||
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
|
||||
$scheduled_ticket_client_name = nullable_htmlentities($row['client_name']);
|
||||
?>
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
|
|
@ -116,8 +117,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
</th>
|
||||
|
||||
<td>
|
||||
<a href="#" data-toggle="modal" data-target="#editScheduledTicketModal"
|
||||
onclick="populateScheduledTicketEditModal(<?php echo $scheduled_ticket_client_id, ",", $scheduled_ticket_id ?>)"> <?php echo $scheduled_ticket_subject ?>
|
||||
<a href="#" data-toggle="modal" data-target="#editScheduledTicketModal" onclick="populateScheduledTicketEditModal(<?php echo $scheduled_ticket_client_id, ",", $scheduled_ticket_id ?>)"> <?php echo $scheduled_ticket_subject ?>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
|
@ -133,8 +133,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal"
|
||||
data-target="#editScheduledTicketModal" onclick="populateScheduledTicketEditModal(<?php echo $scheduled_ticket_client_id, ",", $scheduled_ticket_id ?>)">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editScheduledTicketModal" onclick="populateScheduledTicketEditModal(<?php echo $scheduled_ticket_client_id, ",", $scheduled_ticket_id ?>)">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<?php
|
||||
|
|
@ -152,22 +151,22 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<?php require_once 'pagination.php';
|
||||
?>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/scheduled_tickets_edit_modal.js"></script>
|
||||
<script src="js/bulk_actions.js"></script>
|
||||
<?php require_once 'pagination.php';
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/scheduled_tickets_edit_modal.js"></script>
|
||||
<script src="js/bulk_actions.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "scheduled_ticket_add_modal.php";
|
||||
|
|
@ -175,4 +174,3 @@ require_once "scheduled_ticket_add_modal.php";
|
|||
require_once "scheduled_ticket_edit_modal.php";
|
||||
|
||||
require_once "footer.php";
|
||||
|
||||
|
|
|
|||
104
side_nav.php
104
side_nav.php
|
|
@ -1,7 +1,7 @@
|
|||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
|
||||
|
||||
<div class="brand-link">
|
||||
<div class="brand-link">
|
||||
<h3 class="brand-text text-light mb-0"><?php echo nullable_htmlentities($session_company_name); ?></h3>
|
||||
</div>
|
||||
|
||||
|
|
@ -14,14 +14,18 @@
|
|||
<ul class="nav nav-pills nav-sidebar flex-column mt-3" data-widget="treeview" data-accordion="false">
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="dashboard.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "dashboard.php") { echo "active"; } ?>">
|
||||
<a href="dashboard.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "dashboard.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-tachometer-alt"></i>
|
||||
<p>Dashboard</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="clients.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "clients.php") { echo "active"; } ?>">
|
||||
<a href="clients.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "clients.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-user-friends"></i>
|
||||
<p>Clients</p>
|
||||
</a>
|
||||
|
|
@ -31,22 +35,20 @@
|
|||
|
||||
<li class="nav-header mt-3">SUPPORT</li>
|
||||
<li class="nav-item">
|
||||
<a href="tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php") { echo "active"; } ?>">
|
||||
<a href="tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php" || basename($_SERVER["PHP_SELF"]) == "scheduled_tickets.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-life-ring"></i>
|
||||
<p>Tickets</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="scheduled_tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "scheduled_tickets.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-calendar-check"></i>
|
||||
<p>Scheduled Tickets</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="calendar_events.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar_events.php") { echo "active"; } ?>">
|
||||
<a href="calendar_events.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar_events.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-calendar-alt"></i>
|
||||
<p>Calendar</p>
|
||||
</a>
|
||||
|
|
@ -56,31 +58,41 @@
|
|||
|
||||
<li class="nav-header mt-3">SALES</li>
|
||||
<li class="nav-item">
|
||||
<a href="quotes.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") { echo "active"; } ?>">
|
||||
<a href="quotes.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-comment-dollar"></i>
|
||||
<p>Quotes</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") { echo "active"; } ?>">
|
||||
<a href="invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-file-invoice"></i>
|
||||
<p>Invoices</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="recurring_invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php") { echo "active"; } ?>">
|
||||
<a href="recurring_invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-redo-alt"></i>
|
||||
<p>Recurring Invoices</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="revenues.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "revenues.php") { echo "active"; } ?>">
|
||||
<a href="revenues.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "revenues.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-hand-holding-usd"></i>
|
||||
<p>Revenues</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="products.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "products.php") { echo "active"; } ?>">
|
||||
<a href="products.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "products.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-box-open"></i>
|
||||
<p>Products</p>
|
||||
</a>
|
||||
|
|
@ -92,60 +104,78 @@
|
|||
|
||||
<li class="nav-header mt-3">FINANCE</li>
|
||||
<li class="nav-item">
|
||||
<a href="payments.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") { echo "active"; } ?>">
|
||||
<a href="payments.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-credit-card"></i>
|
||||
<p>Payments</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="vendors.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") { echo "active"; } ?>">
|
||||
<a href="vendors.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-building"></i>
|
||||
<p>Vendors</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expenses.php") { echo "active"; } ?>">
|
||||
<a href="expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expenses.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-shopping-cart"></i>
|
||||
<p>Expenses</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="recurring_expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_expenses.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-clock"></i>
|
||||
<a href="recurring_expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_expenses.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-redo-alt"></i>
|
||||
<p>Recurring Expenses</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="accounts.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "accounts.php") { echo "active"; } ?>">
|
||||
<a href="accounts.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "accounts.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-piggy-bank"></i>
|
||||
<p>Accounts</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="transfers.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "transfers.php") { echo "active"; } ?>">
|
||||
<a href="transfers.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "transfers.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-exchange-alt"></i>
|
||||
<p>Transfers</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="budget.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "budget.php") { echo "active"; } ?>">
|
||||
<a href="budget.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "budget.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-balance-scale"></i>
|
||||
<p>Budget</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="trips.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-route"></i>
|
||||
<p>Trips</p>
|
||||
</a>
|
||||
</li>
|
||||
<a href="trips.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="nav-icon fas fa-route"></i>
|
||||
<p>Trips</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<li class="nav-header mt-3">MORE</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="report_income_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "report_income_summary.php") { echo "active"; } ?>">
|
||||
<a href="report_income_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "report_income_summary.php") {
|
||||
echo "active";
|
||||
} ?>">
|
||||
<i class="fas fa-chart-line nav-icon"></i>
|
||||
<p>Reports</p>
|
||||
<i class="fas fa-angle-right nav-icon float-right"></i>
|
||||
|
|
@ -154,13 +184,13 @@
|
|||
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="users.php" class="nav-link">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>Administration</p>
|
||||
<i class="fas fa-angle-right nav-icon float-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="users.php" class="nav-link">
|
||||
<i class="nav-icon fas fa-cogs"></i>
|
||||
<p>Administration</p>
|
||||
<i class="fas fa-angle-right nav-icon float-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
|
|
|||
185
ticket.php
185
ticket.php
|
|
@ -34,8 +34,6 @@ if (isset($_GET['ticket_id'])) {
|
|||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='tickets.php'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
|
||||
include_once "footer.php";
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
|
|
@ -58,6 +56,8 @@ if (isset($_GET['ticket_id'])) {
|
|||
$ticket_details = $purifier->purify($row['ticket_details']);
|
||||
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
|
||||
$ticket_billable = intval($row['ticket_billable']);
|
||||
$ticket_scheduled_for = nullable_htmlentities($row['ticket_schedule']);
|
||||
$ticket_onsite = nullable_htmlentities($row['ticket_onsite']);
|
||||
|
||||
//Set Ticket Bage Color based of priority
|
||||
if ($ticket_priority == "High") {
|
||||
|
|
@ -191,13 +191,15 @@ if (isset($_GET['ticket_id'])) {
|
|||
$warranty_check = date('m/d/Y', strtotime('-8 hours'));
|
||||
|
||||
if ($dt_value <= $date) {
|
||||
$dt_value = "Expired on $asset_warranty_expire"; $warranty_status_color ='red';
|
||||
$dt_value = "Expired on $asset_warranty_expire";
|
||||
$warranty_status_color = 'red';
|
||||
} else {
|
||||
$warranty_status_color = 'green';
|
||||
}
|
||||
|
||||
if ($asset_warranty_expire == "NULL") {
|
||||
$dt_value = "None"; $warranty_status_color ='red';
|
||||
$dt_value = "None";
|
||||
$warranty_status_color = 'red';
|
||||
}
|
||||
|
||||
// Get all ticket replies
|
||||
|
|
@ -226,7 +228,7 @@ if (isset($_GET['ticket_id'])) {
|
|||
AND ticket_attachment_ticket_id = $ticket_id"
|
||||
);
|
||||
|
||||
?>
|
||||
?>
|
||||
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb d-print-none">
|
||||
|
|
@ -244,30 +246,30 @@ if (isset($_GET['ticket_id'])) {
|
|||
<h3><i class="fas fa-fw fa-life-ring text-secondary mr-2"></i>Ticket <?php echo "$ticket_prefix$ticket_number"; ?> <?php echo $ticket_status_display; ?></h3>
|
||||
</div>
|
||||
<?php if ($ticket_status != "Closed") { ?>
|
||||
<div class="col-3">
|
||||
<div class="dropdown dropleft text-center d-print-none">
|
||||
<button class="btn btn-secondary btn-sm float-right" type="button" id="dropdownMenuButton" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editTicketModal<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#mergeTicketModal<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-clone mr-2"></i>Merge
|
||||
</a>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" id="clientChangeTicketModalLoad" data-target="#clientChangeTicketModal">
|
||||
<i class="fas fa-fw fa-people-carry mr-2"></i>Change Client
|
||||
</a>
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket=<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
<div class="col-3">
|
||||
<div class="dropdown dropleft text-center d-print-none">
|
||||
<button class="btn btn-secondary btn-sm float-right" type="button" id="dropdownMenuButton" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editTicketModal<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<?php } ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#mergeTicketModal<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-clone mr-2"></i>Merge
|
||||
</a>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" id="clientChangeTicketModalLoad" data-target="#clientChangeTicketModal">
|
||||
<i class="fas fa-fw fa-people-carry mr-2"></i>Change Client
|
||||
</a>
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket=<?php echo $ticket_id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
|
|
@ -310,18 +312,29 @@ if (isset($_GET['ticket_id'])) {
|
|||
<span class="input-group-text"><i class="fa fa-fw fa-thermometer-half"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="status" required>
|
||||
<option <?php if ($ticket_status == "In-Progress") {echo "selected";}?> >In-Progress</option>
|
||||
<option <?php if ($ticket_status == "Pending-Client") {echo "selected";}?> >Pending-Client</option>
|
||||
<option <?php if ($ticket_status == "Pending-Vendor") {echo "selected";}?> >Pending-Vendor</option>
|
||||
<option <?php if ($ticket_status == "Pending-Shipment") {echo "selected";}?> >Pending-Shipment</option>
|
||||
<option <?php if ($ticket_status == "Scheduled") {echo "selected";}?> >Scheduled</option>
|
||||
<?php if($config_ticket_autoclose) { ?>
|
||||
<option <?php if ($ticket_status == 'Auto Close') { echo "selected"; } ?> >Auto Close</option>
|
||||
<option <?php if ($ticket_status == "In-Progress") {
|
||||
echo "selected";
|
||||
} ?>>In-Progress</option>
|
||||
<option <?php if ($ticket_status == "Pending-Client") {
|
||||
echo "selected";
|
||||
} ?>>Pending-Client</option>
|
||||
<option <?php if ($ticket_status == "Pending-Vendor") {
|
||||
echo "selected";
|
||||
} ?>>Pending-Vendor</option>
|
||||
<option <?php if ($ticket_status == "Pending-Shipment") {
|
||||
echo "selected";
|
||||
} ?>>Pending-Shipment</option>
|
||||
<?php if ($config_ticket_autoclose) { ?>
|
||||
<option <?php if ($ticket_status == 'Auto Close') {
|
||||
echo "selected";
|
||||
} ?>>Auto Close</option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="custom-tt-horizontal-spacing"></div> <!-- Add custom class for smaller spacing -->
|
||||
|
||||
<!-- Time Tracking -->
|
||||
|
|
@ -362,16 +375,16 @@ if (isset($_GET['ticket_id'])) {
|
|||
<div class="form-row">
|
||||
|
||||
|
||||
<?php if(!empty($contact_email && $contact_email !== $session_email)){ ?>
|
||||
<?php if (!empty($contact_email && $contact_email !== $session_email)) { ?>
|
||||
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="ticket_reply_type_checkbox" name="public_reply_type" value="1" checked>
|
||||
<label class="custom-control-label" for="ticket_reply_type_checkbox">Email contact<br><small class="text-secondary">(Public Update)</small></label>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="ticket_reply_type_checkbox" name="public_reply_type" value="1" checked>
|
||||
<label class="custom-control-label" for="ticket_reply_type_checkbox">Email contact<br><small class="text-secondary">(Public Update)</small></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
|
@ -421,9 +434,15 @@ if (isset($_GET['ticket_id'])) {
|
|||
AND ticket_attachment_ticket_id = $ticket_id"
|
||||
);
|
||||
|
||||
?>
|
||||
?>
|
||||
|
||||
<div class="card card-outline <?php if ($ticket_reply_type == 'Internal') { echo "card-dark"; } elseif ($ticket_reply_type == 'Client') {echo "card-warning"; } else { echo "card-info"; } ?> mb-3">
|
||||
<div class="card card-outline <?php if ($ticket_reply_type == 'Internal') {
|
||||
echo "card-dark";
|
||||
} elseif ($ticket_reply_type == 'Client') {
|
||||
echo "card-warning";
|
||||
} else {
|
||||
echo "card-info";
|
||||
} ?> mb-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<div class="media">
|
||||
|
|
@ -439,7 +458,9 @@ if (isset($_GET['ticket_id'])) {
|
|||
<div class="media-body">
|
||||
<?php echo $ticket_reply_by_display; ?>
|
||||
<div>
|
||||
<small class="text-muted"><?php echo $ticket_reply_created_at; ?> <?php if (!empty($ticket_reply_updated_at)) { echo "modified: $ticket_reply_updated_at"; } ?></small>
|
||||
<small class="text-muted"><?php echo $ticket_reply_created_at; ?> <?php if (!empty($ticket_reply_updated_at)) {
|
||||
echo "modified: $ticket_reply_updated_at";
|
||||
} ?></small>
|
||||
</div>
|
||||
<?php if ($ticket_reply_type !== "Client") { ?>
|
||||
<div>
|
||||
|
|
@ -487,11 +508,9 @@ if (isset($_GET['ticket_id'])) {
|
|||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<?php
|
||||
|
||||
require "ticket_reply_edit_modal.php";
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
@ -566,7 +585,7 @@ if (isset($_GET['ticket_id'])) {
|
|||
$prev_ticket_id = intval($prev_ticket_row['ticket_id']);
|
||||
$prev_ticket_subject = nullable_htmlentities($prev_ticket_row['ticket_subject']);
|
||||
$prev_ticket_status = nullable_htmlentities($prev_ticket_row['ticket_status']);
|
||||
?>
|
||||
?>
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
|
|
@ -577,7 +596,7 @@ if (isset($_GET['ticket_id'])) {
|
|||
<i class="fa fa-fw fa-hourglass-start text-secondary ml-1 mr-2"></i><strong>Status:</strong>
|
||||
<span class="text-success"><?php echo $prev_ticket_status; ?></span>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
|
||||
<?php } else { ?>
|
||||
<div class="d-print-none">
|
||||
|
|
@ -602,11 +621,10 @@ if (isset($_GET['ticket_id'])) {
|
|||
while ($ticket_watcher_row = mysqli_fetch_array($sql_ticket_watchers)) {
|
||||
$watcher_id = intval($ticket_watcher_row['watcher_id']);
|
||||
$ticket_watcher_email = nullable_htmlentities($ticket_watcher_row['watcher_email']);
|
||||
?>
|
||||
?>
|
||||
<div class='mt-1'>
|
||||
<i class="fa fa-fw fa-eye text-secondary ml-1 mr-2"></i><?php echo $ticket_watcher_email; ?>
|
||||
<a class="confirm-link"
|
||||
href="post.php?delete_ticket_watcher=<?php echo $watcher_id; ?>">
|
||||
<a class="confirm-link" href="post.php?delete_ticket_watcher=<?php echo $watcher_id; ?>">
|
||||
<i class="fas fa-fw fa-times text-secondary ml-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -642,15 +660,25 @@ if (isset($_GET['ticket_id'])) {
|
|||
<div class="mt-1">
|
||||
<i class="fa fa-fw fa-comment-dots text-secondary ml-1 mr-2"></i>Feedback: <?php echo $ticket_feedback; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php }
|
||||
|
||||
<?php if (!empty($ticket_total_reply_time)) { ?>
|
||||
if (!empty($ticket_scheduled_for)) { ?>
|
||||
<div class="mt-1">
|
||||
<i class="fa fa-fw fa-calendar-check text-secondary ml-1 mr-2"></i>Scheduled for: <a href="#" data-toggle="modal" data-target="#editTicketScheduleModal"><?php echo $ticket_scheduled_for; ?></a>
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="mt-1">
|
||||
<i class="fa fa-fw fa-calendar-check text-secondary ml-1 mr-2"></i>Scheduled for: <a href="#" data-toggle="modal" data-target="#editTicketScheduleModal">Add</a>
|
||||
</div>
|
||||
<?php }
|
||||
|
||||
if (!empty($ticket_total_reply_time)) { ?>
|
||||
<div class="mt-1">
|
||||
<i class="far fa-fw fa-clock text-secondary ml-1 mr-2"></i>Total time worked: <?php echo $ticket_total_reply_time; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php }
|
||||
|
||||
<?php if ($config_module_enable_accounting) { ?>
|
||||
if ($config_module_enable_accounting) { ?>
|
||||
<div class="mt-1">
|
||||
<i class="fa fa-fw fa-dollar-sign text-secondary ml-1 mr-2"></i>Billable:
|
||||
<a href="#" data-toggle="modal" data-target="#editTicketBillableModal<?php echo $ticket_id; ?>">
|
||||
|
|
@ -680,7 +708,7 @@ if (isset($_GET['ticket_id'])) {
|
|||
<?php } else { ?>
|
||||
|
||||
<div>
|
||||
<a href='client_asset_details.php?client_id=<?php echo $client_id?>&asset_id=<?php echo $asset_id?>' ><i class="fa fa-fw fa-desktop text-secondary ml-1 mr-2"></i><strong><?php echo $asset_name; ?></strong></a>
|
||||
<a href='client_asset_details.php?client_id=<?php echo $client_id ?>&asset_id=<?php echo $asset_id ?>'><i class="fa fa-fw fa-desktop text-secondary ml-1 mr-2"></i><strong><?php echo $asset_name; ?></strong></a>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($asset_os)) { ?>
|
||||
|
|
@ -744,12 +772,12 @@ if (isset($_GET['ticket_id'])) {
|
|||
$service_ticket_status = nullable_htmlentities($row['ticket_status']);
|
||||
$service_ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
|
||||
$service_ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
|
||||
?>
|
||||
?>
|
||||
<p>
|
||||
<i class="fas fa-fw fa-ticket-alt"></i>
|
||||
Ticket: <a href="ticket.php?ticket_id=<?php echo $service_ticket_id; ?>"><?php echo "$service_ticket_prefix$service_ticket_number" ?></a> <?php echo "on $service_ticket_created_at - <b>$service_ticket_subject</b> ($service_ticket_status)"; ?>
|
||||
</p>
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
|
@ -761,9 +789,11 @@ if (isset($_GET['ticket_id'])) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<?php } // End Ticket asset Count ?>
|
||||
<?php } // End Ticket asset Count
|
||||
?>
|
||||
|
||||
<?php } // End if asset_id == 0 else ?>
|
||||
<?php } // End if asset_id == 0 else
|
||||
?>
|
||||
|
||||
</div>
|
||||
<!-- End Asset card -->
|
||||
|
|
@ -811,7 +841,8 @@ if (isset($_GET['ticket_id'])) {
|
|||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php } //End Else ?>
|
||||
<?php } //End Else
|
||||
?>
|
||||
</div>
|
||||
<!-- End Vendor card -->
|
||||
|
||||
|
|
@ -824,18 +855,24 @@ if (isset($_GET['ticket_id'])) {
|
|||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="assigned_to" <?php if ($ticket_status == "Closed") {echo "disabled";} ?>>
|
||||
<select class="form-control select2" name="assigned_to" <?php if ($ticket_status == "Closed") {
|
||||
echo "disabled";
|
||||
} ?>>
|
||||
<option value="0">Not Assigned</option>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_assign_to_select)) {
|
||||
$user_id = intval($row['user_id']);
|
||||
$user_name = nullable_htmlentities($row['user_name']); ?>
|
||||
<option <?php if ($ticket_assigned_to == $user_id) { echo "selected"; } ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
|
||||
<option <?php if ($ticket_assigned_to == $user_id) {
|
||||
echo "selected";
|
||||
} ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<div class="input-group-append d-print-none">
|
||||
<button type="submit" class="btn btn-primary" name="assign_ticket" <?php if ($ticket_status == "Closed") {echo "disabled";} ?>><i class="fas fa-check"></i></button>
|
||||
<button type="submit" class="btn btn-primary" name="assign_ticket" <?php if ($ticket_status == "Closed") {
|
||||
echo "disabled";
|
||||
} ?>><i class="fas fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -859,7 +896,7 @@ if (isset($_GET['ticket_id'])) {
|
|||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<?php
|
||||
require_once "ticket_edit_modal.php";
|
||||
|
||||
require_once "ticket_edit_contact_modal.php";
|
||||
|
|
@ -874,22 +911,29 @@ if (isset($_GET['ticket_id'])) {
|
|||
|
||||
require_once "ticket_change_client_modal.php";
|
||||
|
||||
require_once "ticket_edit_schedule_modal.php";
|
||||
|
||||
require_once "ticket_merge_modal.php";
|
||||
|
||||
if ($config_module_enable_accounting) {
|
||||
require_once "ticket_edit_billable_modal.php";
|
||||
require_once "ticket_invoice_add_modal.php";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
require_once "footer.php";
|
||||
|
||||
?> <script src="js/show_modals.js"></script> <?php
|
||||
?>
|
||||
|
||||
if ($ticket_status !== "Closed") { ?>
|
||||
|
||||
|
||||
|
||||
<script src="js/show_modals.js"></script> <?php
|
||||
|
||||
if ($ticket_status !== "Closed") { ?>
|
||||
<!-- Ticket Time Tracking JS -->
|
||||
<script src="js/ticket_time_tracking.js"></script>
|
||||
|
||||
|
|
@ -898,5 +942,4 @@ if ($ticket_status !== "Closed") { ?>
|
|||
<script src="js/ticket_button_respond_note.js"></script>
|
||||
<?php } ?>
|
||||
|
||||
<script src="js/pretty_content.js"></script>
|
||||
|
||||
<script src="js/pretty_content.js"></script>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<div class="modal" id="editTicketScheduleModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fa fa-fw fa-user mr-2"></i>
|
||||
Edit Scheduled Time for <strong><?php echo "$ticket_prefix$ticket_number"; ?></strong>
|
||||
</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body bg-white">
|
||||
<input type="hidden" name="ticket_id" value="<?php echo $ticket_id; ?>">
|
||||
<div class="form-group">
|
||||
<label>Scheduled Date and Time</label>
|
||||
<?php if (!$ticket_scheduled_for) { ?>
|
||||
<input type="datetime-local" class="form-control" name="scheduled_date_time" placeholder="Scheduled Date & Time">
|
||||
<?php } else { ?>
|
||||
<input type="datetime-local" class="form-control" name="scheduled_date_time" value="<?php echo $ticket_scheduled_for; ?>">
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Onsite</label>
|
||||
<select class="form-control" name="onsite">
|
||||
<option value="0" <?php if ($ticket_onsite == 0) echo "selected"; ?>>No</option>
|
||||
<option value="1" <?php if ($ticket_onsite == 1) echo "selected"; ?>>Yes</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="edit_ticket_schedule" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
418
tickets.php
418
tickets.php
|
|
@ -39,7 +39,7 @@ if (isset($_GET['assigned']) & !empty($_GET['assigned'])) {
|
|||
if ($_GET['assigned'] == 'unassigned') {
|
||||
$ticket_assigned_filter = 'AND ticket_assigned_to = 0';
|
||||
} else {
|
||||
$ticket_assigned_filter = 'AND ticket_assigned_to = '.intval($_GET['assigned']);
|
||||
$ticket_assigned_filter = 'AND ticket_assigned_to = ' . intval($_GET['assigned']);
|
||||
}
|
||||
} else {
|
||||
// Default - any
|
||||
|
|
@ -77,6 +77,11 @@ $sql_total_tickets_closed = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS to
|
|||
$row = mysqli_fetch_array($sql_total_tickets_closed);
|
||||
$total_tickets_closed = intval($row['total_tickets_closed']);
|
||||
|
||||
//Get Total Scheduled tickets
|
||||
$sql_total_scheduled_tickets = mysqli_query($mysqli, "SELECT COUNT(scheduled_ticket_id) AS total_scheduled_tickets FROM scheduled_tickets");
|
||||
$row = mysqli_fetch_array($sql_total_scheduled_tickets);
|
||||
$total_scheduled_tickets = intval($row['total_scheduled_tickets']);
|
||||
|
||||
//Get Unassigned tickets
|
||||
$sql_total_tickets_unassigned = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS total_tickets_unassigned FROM tickets WHERE ticket_assigned_to = '0' AND ticket_status != 'Closed'");
|
||||
$row = mysqli_fetch_array($sql_total_tickets_unassigned);
|
||||
|
|
@ -112,10 +117,11 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Tickets">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {
|
||||
echo stripslashes(nullable_htmlentities($q));
|
||||
} ?>" placeholder="Search Tickets">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse"
|
||||
data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -134,7 +140,11 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
<a href="?assigned=unassigned" class="btn btn-outline-danger">
|
||||
<i class="fa fa-fw fa-exclamation-triangle mr-2"></i>Unassigned Tickets | <strong> <?php echo $total_tickets_unassigned; ?></strong>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="scheduled_tickets.php" class="btn btn-outline-info">
|
||||
<i class="fa fa-fw fa-redo-alt mr-2"></i>Recurring Tickets | <strong> <?php echo $total_scheduled_tickets; ?></strong>
|
||||
</a>
|
||||
|
||||
<div class="dropdown ml-2" id="bulkActionButton" hidden>
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
|
|
@ -159,51 +169,53 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="collapse <?php if (!empty($_GET['dtf']) || (isset($_GET['canned_date']) && $_GET['canned_date'] !== "custom") || (isset($_GET['status']) && is_array($_GET['status']))) { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="collapse <?php if (!empty($_GET['dtf']) || (isset($_GET['canned_date']) && $_GET['canned_date'] !== "custom") || (isset($_GET['status']) && is_array($_GET['status']))) {
|
||||
echo "show";
|
||||
} ?>" id="advancedFilter">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Canned Date</label>
|
||||
<select class="form-control select2" name="canned_date">
|
||||
<option <?php if ($_GET['canned_date'] == "custom") {
|
||||
echo "selected";
|
||||
} ?> value="custom">Custom
|
||||
echo "selected";
|
||||
} ?> value="custom">Custom
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "today") {
|
||||
echo "selected";
|
||||
} ?> value="today">Today
|
||||
echo "selected";
|
||||
} ?> value="today">Today
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "yesterday") {
|
||||
echo "selected";
|
||||
} ?> value="yesterday">Yesterday
|
||||
echo "selected";
|
||||
} ?> value="yesterday">Yesterday
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisweek") {
|
||||
echo "selected";
|
||||
} ?> value="thisweek">This Week
|
||||
echo "selected";
|
||||
} ?> value="thisweek">This Week
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastweek") {
|
||||
echo "selected";
|
||||
} ?> value="lastweek">Last Week
|
||||
echo "selected";
|
||||
} ?> value="lastweek">Last Week
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thismonth") {
|
||||
echo "selected";
|
||||
} ?> value="thismonth">This Month
|
||||
echo "selected";
|
||||
} ?> value="thismonth">This Month
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastmonth") {
|
||||
echo "selected";
|
||||
} ?> value="lastmonth">Last Month
|
||||
echo "selected";
|
||||
} ?> value="lastmonth">Last Month
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisyear") {
|
||||
echo "selected";
|
||||
} ?> value="thisyear">This Year
|
||||
echo "selected";
|
||||
} ?> value="thisyear">This Year
|
||||
</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastyear") {
|
||||
echo "selected";
|
||||
} ?> value="lastyear">Last Year
|
||||
echo "selected";
|
||||
} ?> value="lastyear">Last Year
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -223,14 +235,28 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Ticket Status</label>
|
||||
<select class="form-control select2" name="status[]" data-placeholder = "Select Status" multiple>
|
||||
<option value="In-Progress" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('In-Progress', $_GET['status'])) { echo 'selected'; } ?> >In-Progress</option>
|
||||
<option value="Client-Replied" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Client-Replied', $_GET['status'])) { echo 'selected'; } ?> >Client-Replied</option>
|
||||
<option value="Pending-Client" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Client', $_GET['status'])) { echo 'selected'; } ?> >Pending-Client</option>
|
||||
<option value="Pending-Vendor" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Vendor', $_GET['status'])) { echo 'selected'; } ?> >Pending-Vendor</option>
|
||||
<option value="Pending-Shipment" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Shipment', $_GET['status'])) { echo 'selected'; } ?> >Pending-Shipment</option>
|
||||
<option value="Scheduled" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Scheduled', $_GET['status'])) { echo 'selected'; } ?> >Scheduled</option>
|
||||
<option value="Closed" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Closed', $_GET['status'])) { echo 'selected'; } ?> >Closed</option>
|
||||
<select class="form-control select2" name="status[]" data-placeholder="Select Status" multiple>
|
||||
<option value="In-Progress" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('In-Progress', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>In-Progress</option>
|
||||
<option value="Client-Replied" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Client-Replied', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Client-Replied</option>
|
||||
<option value="Pending-Client" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Client', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Pending-Client</option>
|
||||
<option value="Pending-Vendor" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Vendor', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Pending-Vendor</option>
|
||||
<option value="Pending-Shipment" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Pending-Shipment', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Pending-Shipment</option>
|
||||
<option value="Scheduled" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Scheduled', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Scheduled</option>
|
||||
<option value="Closed" <?php if (isset($_GET['status']) && is_array($_GET['status']) && in_array('Closed', $_GET['status'])) {
|
||||
echo 'selected';
|
||||
} ?>>Closed</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -238,17 +264,23 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
<div class="form-group">
|
||||
<label>Assigned to</label>
|
||||
<select class="form-control select2" name="assigned">
|
||||
<option value="" <?php if ($ticket_assigned_filter == "") {echo "selected";}?> >Any</option>
|
||||
<option value="unassigned"<?php if ($ticket_assigned_filter == "0") {echo "selected";}?> >Unassigned</option>
|
||||
<option value="" <?php if ($ticket_assigned_filter == "") {
|
||||
echo "selected";
|
||||
} ?>>Any</option>
|
||||
<option value="unassigned" <?php if ($ticket_assigned_filter == "0") {
|
||||
echo "selected";
|
||||
} ?>>Unassigned</option>
|
||||
|
||||
<?php
|
||||
$sql_assign_to = mysqli_query($mysqli, "SELECT * FROM users WHERE user_archived_at IS NULL ORDER BY user_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql_assign_to)) {
|
||||
$user_id = intval($row['user_id']);
|
||||
$user_name = nullable_htmlentities($row['user_name']);
|
||||
?>
|
||||
<option <?php if ($ticket_assigned_filter == $user_id) { echo "selected"; } ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
|
||||
<?php
|
||||
?>
|
||||
<option <?php if ($ticket_assigned_filter == $user_id) {
|
||||
echo "selected";
|
||||
} ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
|
|
@ -263,192 +295,186 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
|
|||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
|
||||
</div>
|
||||
</td>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_number&order=<?php echo $disp; ?>">Number</a>
|
||||
</th>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_subject&order=<?php echo $disp; ?>">Subject</a>
|
||||
</th>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">Client / Contact</a>
|
||||
</th>
|
||||
<?php if ($config_module_enable_accounting) {
|
||||
?>
|
||||
<th class="text-center"><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_billable&order=<?php echo $disp; ?>">Billable</a>
|
||||
<thead class="text-dark <?php if (!$num_rows[0]) {
|
||||
echo "d-none";
|
||||
} ?>">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
|
||||
</div>
|
||||
</td>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_number&order=<?php echo $disp; ?>">Number</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_subject&order=<?php echo $disp; ?>">Subject</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">Client / Contact</a>
|
||||
</th>
|
||||
<?php if ($config_module_enable_accounting) {
|
||||
?>
|
||||
<th class="text-center"><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_billable&order=<?php echo $disp; ?>">Billable</a>
|
||||
</th>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
}
|
||||
?>
|
||||
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_priority&order=<?php echo $disp; ?>">Priority</a>
|
||||
</th>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_status&order=<?php echo $disp; ?>">Status</a>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>">Assigned</a>
|
||||
</th>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_updated_at&order=<?php echo $disp; ?>">Last Response</a>
|
||||
</th>
|
||||
<th><a class="text-dark"
|
||||
href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_created_at&order=<?php echo $disp; ?>">Created</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_priority&order=<?php echo $disp; ?>">Priority</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_status&order=<?php echo $disp; ?>">Status</a>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>">Assigned</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_updated_at&order=<?php echo $disp; ?>">Last Response</a>
|
||||
</th>
|
||||
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_created_at&order=<?php echo $disp; ?>">Created</a>
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$ticket_id = intval($row['ticket_id']);
|
||||
$ticket_prefix = nullable_htmlentities($row['ticket_prefix']);
|
||||
$ticket_number = intval($row['ticket_number']);
|
||||
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
|
||||
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
|
||||
$ticket_status = nullable_htmlentities($row['ticket_status']);
|
||||
$ticket_billable = intval($row['ticket_billable']);
|
||||
$ticket_vendor_ticket_number = nullable_htmlentities($row['ticket_vendor_ticket_number']);
|
||||
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
|
||||
$ticket_created_at_time_ago = timeAgo($row['ticket_created_at']);
|
||||
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
|
||||
$ticket_updated_at_time_ago = timeAgo($row['ticket_updated_at']);
|
||||
if (empty($ticket_updated_at)) {
|
||||
if ($ticket_status == "Closed") {
|
||||
$ticket_updated_at_display = "<p>Never</p>";
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$ticket_id = intval($row['ticket_id']);
|
||||
$ticket_prefix = nullable_htmlentities($row['ticket_prefix']);
|
||||
$ticket_number = intval($row['ticket_number']);
|
||||
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
|
||||
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
|
||||
$ticket_status = nullable_htmlentities($row['ticket_status']);
|
||||
$ticket_billable = intval($row['ticket_billable']);
|
||||
$ticket_vendor_ticket_number = nullable_htmlentities($row['ticket_vendor_ticket_number']);
|
||||
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
|
||||
$ticket_created_at_time_ago = timeAgo($row['ticket_created_at']);
|
||||
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
|
||||
$ticket_updated_at_time_ago = timeAgo($row['ticket_updated_at']);
|
||||
if (empty($ticket_updated_at)) {
|
||||
if ($ticket_status == "Closed") {
|
||||
$ticket_updated_at_display = "<p>Never</p>";
|
||||
} else {
|
||||
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
|
||||
}
|
||||
} else {
|
||||
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
|
||||
$ticket_updated_at_display = "$ticket_updated_at_time_ago<br><small class='text-secondary'>$ticket_updated_at</small>";
|
||||
}
|
||||
} else {
|
||||
$ticket_updated_at_display = "$ticket_updated_at_time_ago<br><small class='text-secondary'>$ticket_updated_at</small>";
|
||||
}
|
||||
$ticket_closed_at = nullable_htmlentities($row['ticket_closed_at']);
|
||||
$client_id = intval($row['ticket_client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$contact_id = intval($row['ticket_contact_id']);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$contact_title = nullable_htmlentities($row['contact_title']);
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_phone = formatPhoneNumber($row['contact_phone']);
|
||||
$contact_extension = nullable_htmlentities($row['contact_extension']);
|
||||
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
|
||||
if ($ticket_status == "Pending-Assignment") {
|
||||
$ticket_status_color = "danger";
|
||||
} elseif ($ticket_status == "Assigned") {
|
||||
$ticket_status_color = "primary";
|
||||
} elseif ($ticket_status == "In-Progress") {
|
||||
$ticket_status_color = "success";
|
||||
} elseif ($ticket_status == "Closed") {
|
||||
$ticket_status_color = "dark";
|
||||
} elseif ($ticket_status == "Auto Close") {
|
||||
$ticket_status_color = "dark";
|
||||
} elseif ($ticket_status == "Client-Replied") {
|
||||
$ticket_status_color = "warning";
|
||||
} else{
|
||||
$ticket_status_color = "secondary";
|
||||
}
|
||||
|
||||
if ($ticket_priority == "High") {
|
||||
$ticket_priority_color = "danger";
|
||||
} elseif ($ticket_priority == "Medium") {
|
||||
$ticket_priority_color = "warning";
|
||||
} else{
|
||||
$ticket_priority_color = "info";
|
||||
}
|
||||
$ticket_assigned_to = intval($row['ticket_assigned_to']);
|
||||
if (empty($ticket_assigned_to)) {
|
||||
if ($ticket_status == "Closed") {
|
||||
$ticket_assigned_to_display = "<p>Not Assigned</p>";
|
||||
$ticket_closed_at = nullable_htmlentities($row['ticket_closed_at']);
|
||||
$client_id = intval($row['ticket_client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$contact_id = intval($row['ticket_contact_id']);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$contact_title = nullable_htmlentities($row['contact_title']);
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_phone = formatPhoneNumber($row['contact_phone']);
|
||||
$contact_extension = nullable_htmlentities($row['contact_extension']);
|
||||
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
|
||||
if ($ticket_status == "Pending-Assignment") {
|
||||
$ticket_status_color = "danger";
|
||||
} elseif ($ticket_status == "Assigned") {
|
||||
$ticket_status_color = "primary";
|
||||
} elseif ($ticket_status == "In-Progress") {
|
||||
$ticket_status_color = "success";
|
||||
} elseif ($ticket_status == "Closed") {
|
||||
$ticket_status_color = "dark";
|
||||
} elseif ($ticket_status == "Auto Close") {
|
||||
$ticket_status_color = "dark";
|
||||
} elseif ($ticket_status == "Client-Replied") {
|
||||
$ticket_status_color = "warning";
|
||||
} else {
|
||||
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
|
||||
$ticket_status_color = "secondary";
|
||||
}
|
||||
} else {
|
||||
$ticket_assigned_to_display = nullable_htmlentities($row['user_name']);
|
||||
}
|
||||
|
||||
if (empty($contact_name)) {
|
||||
$contact_display = "-";
|
||||
} else {
|
||||
$contact_display = "$contact_name<br><small class='text-secondary'>$contact_email</small>";
|
||||
}
|
||||
if ($ticket_priority == "High") {
|
||||
$ticket_priority_color = "danger";
|
||||
} elseif ($ticket_priority == "Medium") {
|
||||
$ticket_priority_color = "warning";
|
||||
} else {
|
||||
$ticket_priority_color = "info";
|
||||
}
|
||||
$ticket_assigned_to = intval($row['ticket_assigned_to']);
|
||||
if (empty($ticket_assigned_to)) {
|
||||
if ($ticket_status == "Closed") {
|
||||
$ticket_assigned_to_display = "<p>Not Assigned</p>";
|
||||
} else {
|
||||
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
|
||||
}
|
||||
} else {
|
||||
$ticket_assigned_to_display = nullable_htmlentities($row['user_name']);
|
||||
}
|
||||
|
||||
$asset_id = intval($row['ticket_asset_id']);
|
||||
$vendor_id = intval($row['ticket_vendor_id']);
|
||||
if (empty($contact_name)) {
|
||||
$contact_display = "-";
|
||||
} else {
|
||||
$contact_display = "$contact_name<br><small class='text-secondary'>$contact_email</small>";
|
||||
}
|
||||
|
||||
$asset_id = intval($row['ticket_asset_id']);
|
||||
$vendor_id = intval($row['ticket_vendor_id']);
|
||||
|
||||
?>
|
||||
|
||||
<tr class="<?php if(empty($ticket_updated_at)) { echo "text-bold"; }?>">
|
||||
<td>
|
||||
<?php if($ticket_status !== "Closed") { ?>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="ticket_ids[]" value="<?php echo $ticket_id ?>">
|
||||
</div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="ticket.php?ticket_id=<?php echo $ticket_id; ?>">
|
||||
<span class="badge badge-pill badge-secondary p-3"><?php echo "$ticket_prefix$ticket_number"; ?></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="ticket.php?ticket_id=<?php echo $ticket_id; ?>"><?php echo $ticket_subject; ?></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="client_tickets.php?client_id=<?php echo $client_id; ?>"><strong><?php echo $client_name; ?></strong></a>
|
||||
<tr class="<?php if (empty($ticket_updated_at)) {
|
||||
echo "text-bold";
|
||||
} ?>">
|
||||
<td>
|
||||
<?php if ($ticket_status !== "Closed") { ?>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="ticket_ids[]" value="<?php echo $ticket_id ?>">
|
||||
</div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="ticket.php?ticket_id=<?php echo $ticket_id; ?>">
|
||||
<span class="badge badge-pill badge-secondary p-3"><?php echo "$ticket_prefix$ticket_number"; ?></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="ticket.php?ticket_id=<?php echo $ticket_id; ?>"><?php echo $ticket_subject; ?></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="client_tickets.php?client_id=<?php echo $client_id; ?>"><strong><?php echo $client_name; ?></strong></a>
|
||||
|
||||
<div class="mt-1"><?php echo $contact_display; ?></div>
|
||||
</td>
|
||||
<?php if ($config_module_enable_accounting) {
|
||||
?>
|
||||
<td class="text-center">
|
||||
<a href="#" data-toggle="modal" data-target="#editTicketBillableModal<?php echo $ticket_id; ?>">
|
||||
<div class="mt-1"><?php echo $contact_display; ?></div>
|
||||
</td>
|
||||
<?php if ($config_module_enable_accounting) {
|
||||
?>
|
||||
<td class="text-center">
|
||||
<a href="#" data-toggle="modal" data-target="#editTicketBillableModal<?php echo $ticket_id; ?>">
|
||||
<?php
|
||||
if ($ticket_billable == 1) {
|
||||
echo "<span class='badge badge-pill badge-success'>$</span>";
|
||||
} else {
|
||||
echo "<span class='badge badge-pill badge-secondary'>X</span>";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<?php
|
||||
if ($ticket_billable == 1) {
|
||||
echo "<span class='badge badge-pill badge-success'>$</span>";
|
||||
} else {
|
||||
echo "<span class='badge badge-pill badge-secondary'>X</span>";
|
||||
}
|
||||
?></td>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<td><a href="#" data-toggle="modal" data-target="#editTicketPriorityModal<?php echo $ticket_id; ?>"><span class='p-2 badge badge-pill badge-<?php echo $ticket_priority_color; ?>'><?php echo $ticket_priority; ?></span></a></td>
|
||||
<td><span class='p-2 badge badge-pill badge-<?php echo $ticket_status_color; ?>'><?php echo $ticket_status; ?></span></td>
|
||||
<td><a href="#" data-toggle="modal" data-target="#assignTicketModal<?php echo $ticket_id; ?>"><?php echo $ticket_assigned_to_display; ?></a></td>
|
||||
<td><?php echo $ticket_updated_at_display; ?></td>
|
||||
<td>
|
||||
<?php echo $ticket_created_at_time_ago; ?>
|
||||
<br>
|
||||
<small class="text-secondary"><?php echo $ticket_created_at; ?></small>
|
||||
</td>
|
||||
</tr>
|
||||
?>
|
||||
<td><a href="#" data-toggle="modal" data-target="#editTicketPriorityModal<?php echo $ticket_id; ?>"><span class='p-2 badge badge-pill badge-<?php echo $ticket_priority_color; ?>'><?php echo $ticket_priority; ?></span></a></td>
|
||||
<td><span class='p-2 badge badge-pill badge-<?php echo $ticket_status_color; ?>'><?php echo $ticket_status; ?></span></td>
|
||||
<td><a href="#" data-toggle="modal" data-target="#assignTicketModal<?php echo $ticket_id; ?>"><?php echo $ticket_assigned_to_display; ?></a></td>
|
||||
<td><?php echo $ticket_updated_at_display; ?></td>
|
||||
<td>
|
||||
<?php echo $ticket_created_at_time_ago; ?>
|
||||
<br>
|
||||
<small class="text-secondary"><?php echo $ticket_created_at; ?></small>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
if ($ticket_status !== "Closed") {
|
||||
// Temp performance boost for closed tickets, until we move to dynamic modals
|
||||
if ($ticket_status !== "Closed") {
|
||||
// Temp performance boost for closed tickets, until we move to dynamic modals
|
||||
|
||||
require "ticket_assign_modal.php";
|
||||
require "ticket_assign_modal.php";
|
||||
|
||||
require "ticket_edit_priority_modal.php";
|
||||
require "ticket_edit_priority_modal.php";
|
||||
|
||||
if ($config_module_enable_accounting) {
|
||||
require "ticket_edit_billable_modal.php";
|
||||
if ($config_module_enable_accounting) {
|
||||
require "ticket_edit_billable_modal.php";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
Loading…
Reference in New Issue