* @link https://TheTempusProject.com * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ namespace TheTempusProject\Models; use TheTempusProject\Bedrock\Functions\Check; use TheTempusProject\Bedrock\Classes\Config; use TheTempusProject\Canary\Canary as Debug; use TheTempusProject\Bedrock\Classes\CustomException; use TheTempusProject\Classes\DatabaseModel; use TheTempusProject\Plugins\Bugreport as Plugin; use TheTempusProject\TheTempusProject as App; use TheTempusProject\Bedrock\Functions\Date; use TheTempusProject\Houdini\Classes\Template; class Tasks extends DatabaseModel { public $tableName = 'tasks'; public $databaseMatrix = [ [ 'task', 'varchar', '128' ], [ 'completed', 'varchar', '5' ], [ 'completedAt', 'int', '10' ], [ 'completedBy', 'int', '10' ], [ 'dueDate', 'int', '10' ], [ 'createdAt', 'int', '10' ], [ 'createdBy', 'int', '11' ], [ 'listID', 'int', '11' ], [ 'color', 'varchar', '48' ], [ 'parentID', 'int', '11' ], [ 'repeats', 'varchar', '48' ], ]; public $plugin; public $repeatOptions = [ 'Does Not Repeat' => 'none', 'Every Day' => 'daily', 'Every Week' => 'weekly', 'Every Month' => 'monthly', 'Every Year' => 'yearly', ]; public function __construct() { parent::__construct(); $this->plugin = new Plugin; } public function filter( $data, $params = [] ) { foreach ( $data as $instance ) { if ( !is_object( $instance ) ) { $instance = $data; $end = true; } if ( 'true' == $instance->completed ) { $url = Template::parse( '' ); $instance->completedUrl = $url; } else { $url = Template::parse( '' ); $instance->completedUrl = $url; } $out[] = $instance; if ( !empty( $end ) ) { $out = $out[0]; break; } } return $out; } public function create( $task, $completed = 'false', $dueDate = null, $list = 0, $repeats = 'none') { if ( !$this->plugin->checkEnabled() ) { Debug::info( 'ToDo Plugin is disabled in the config.' ); return false; } $fields = [ 'task' => $task, 'completed' => $completed, 'listID' => intval($list), 'repeats' => $repeats, 'createdBy' => App::$activeUser->ID, 'createdAt' => time(), ]; if ( !empty( $dueDate ) ) { $fields['dueDate'] = strtotime($dueDate); } if ( 'false' !== $completed ) { $fields['completedBy'] = App::$activeUser->ID; $fields['completedAt'] = time(); } else { $fields['completedAt'] = '0'; } if ( !self::$db->insert( $this->tableName, $fields ) ) { new CustomException( $this->tableName ); return false; } return self::$db->lastId(); } public function update( $ID, $task, $completed = "false", $dueDate = null, $list = 0, $repeats = 'none' ) { if ( !Check::id( $ID ) ) { Debug::info( 'ToDo Task: illegal ID.' ); return false; } $data = $this->findById( $ID ); if ( $data == false ) { Debug::info( 'ToDo Task: not found.' ); return false; } $fields = [ 'task' => $task, 'completed' => $completed, 'listID' => intval($list), 'repeats' => $repeats, ]; if ( !empty( $dueDate ) ) { $fields['dueDate'] = strtotime($dueDate); } if ( 'false' !== $completed && 'false' === $data->completed ) { $fields['completedBy'] = App::$activeUser->ID; $fields['completedAt'] = time(); } if ( !self::$db->update( $this->tableName, $ID, $fields ) ) { new CustomException( $this->tableName ); Debug::error( "ToDo: $ID not updated: $fields" ); return false; } return true; } public function setActive( $ID ) { if ( !Check::id( $ID ) ) { Debug::info( 'ToDo Task: illegal ID.' ); return false; } $fields = [ 'completed' => 'false', 'completedAt' => '0', 'completedBy' => null, ]; if ( !self::$db->update( $this->tableName, $ID, $fields ) ) { new CustomException( $this->tableName ); Debug::error( "Task: $ID not Activated: $fields" ); return false; } return true; } public function recent( $limit = null, $include_completed = false ) { $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'ID', '>', '0']; if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ 'AND', 'completed', '!=', 'true' ] ); } if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function recentlyCompleted( $limit = null ) { $whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND', 'completed', '=', 'true']; if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'completedAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'completedAt', 'DESC', [0, $limit] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function dailyTasks( $limit = null, $include_completed = false ) { $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'daily' ]; if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ // 'AND', 'completedAt', '<', Date::getDayStartTimestamp( '1735736400000', true ), 'AND', 'completedAt', '<', Date::getDayStartTimestamp( time(), true ), ] ); } if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function weeklyTasks( $limit = null, $include_completed = false ) { $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'weekly' ]; if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ 'AND', 'completedAt', '<', Date::getWeekStartTimestamp( time(), true ), ] ); } if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function monthlyTasks( $limit = null, $include_completed = false ) { $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'monthly' ]; if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ 'AND', 'completedAt', '<', Date::getMonthStartTimestamp( time(), true ), ] ); } if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [0, $limit] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function yearlyTasks( $limit = null, $include_completed = false ) { $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND', 'repeats', '=', 'yearly' ]; if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ 'AND', 'completedAt', '<', Date::getYearStartTimestamp( time(), true ), ] ); } if ( empty( $limit ) ) { $data = self::$db->getPaginated( $this->tableName, $whereClause, 'createdAt', 'DESC' ); } else { $data = self::$db->get( $this->tableName, $whereClause, 'createdAt', 'DESC', [ 0, $limit ] ); } if ( !$data->count() ) { Debug::info( 'No tasks found.' ); return false; } return $this->filter( $data->results() ); } public function findByListId( $id, $include_completed = false ) { $data = []; if ( !Check::id( $id ) ) { Debug::warn( "$this->tableName findByListId: illegal ID: $id" ); return $data; } $whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ]; $whereClause = array_merge( $whereClause, [ 'listID', '=', $id, ] ); if ( false == $include_completed ) { $whereClause = array_merge( $whereClause, [ 'AND', 'completed', '!=', 'true' ] ); } $tasks = self::$db->get( $this->tableName, $whereClause ); if ( ! $tasks->count() ) { Debug::info( 'No ' . $this->tableName . ' data found.' ); return []; } return $this->filter( $tasks->results() ); } public function duplicate( $ID, $completed = 'false' ) { if ( ! Check::id( $ID ) ) { Debug::info( 'ToDo Task: illegal ID.' ); return false; } $task = $this->findById( $ID ); if ( $task == false ) { Debug::info( 'ToDo Task: not found.' ); return false; } return $this->create( $task->task, $completed, $task->dueDate, $task->listID ); } public function complete( $ID ) { if ( !Check::id( $ID ) ) { Debug::info( 'ToDo Task: illegal ID.' ); return false; } $data = $this->findById( $ID ); if ( $data == false ) { Debug::info( 'ToDo Task: not found.' ); return false; } if ( 'none' == $data->repeats ) { $completed = 'true'; $completedBy = App::$activeUser->ID; } else { $completed = 'false'; $completedBy = $data->completedBy; $this->duplicate( $data->ID, 'true' ); } $fields = [ 'completed' => $completed, 'completedAt' => time(), 'completedBy' => $completedBy, ]; if ( !self::$db->update( $this->tableName, $ID, $fields ) ) { new CustomException( $this->tableName ); Debug::error( "Task: $ID not Completed: $fields" ); return false; } return true; } public function incomplete( $ID ) { if ( !Check::id( $ID ) ) { Debug::info( 'ToDo Task: illegal ID.' ); return false; } $data = $this->findById( $ID ); if ( $data == false ) { Debug::info( 'ToDo Task: not found.' ); return false; } if ( 'none' != $data->repeats ) { // this should not be possible as completing a repeating task duplicates it as a completed normal task Debug::info( 'There was an error with your request' ); return false; } $fields = [ 'completed' => 'false', 'completedAt' => '0', 'completedBy' => null, ]; if ( !self::$db->update( $this->tableName, $ID, $fields ) ) { new CustomException( $this->tableName ); Debug::error( "Task: $ID not Completed: $fields" ); return false; } return true; } private function isTaskCompleted( $repeats, $completedAt ) { if ( ! intval( $completedAt ) > 0 ) { return false; } switch ($repeats) { case 'none': return true; case 'daily': $start = Date::getDayStartTimestamp( time(), true ); if ( $completedAt > $start ) { return true; } return false; case 'weekly': $start = Date::getWeekStartTimestamp( time(), true ); if ( $completedAt > $start ) { return true; } return false; case 'monthly': $start = Date::getMonthStartTimestamp( time(), true ); if ( $completedAt > $start ) { return true; } return false; case 'yearly': $start = Date::getYearStartTimestamp( time(), true ); if ( $completedAt > $start ) { return true; } return false; default: return true; } return false; } }