2020-05-03 16:41:59 -05:00
< ? php
namespace Aerex\BaikalStorage\Storages ;
use Sabre\VObject\Component\VCalendar as Calendar ;
class Taskwarrior implements IStorage {
public const NAME = 'taskwarrior' ;
private $tasks = [];
2020-05-12 23:56:22 -05:00
private $configs ;
2020-05-28 11:54:21 -05:00
private $logger ;
2020-06-11 11:43:56 -05:00
public function __construct ( $console , $configs , $logger ) {
2020-05-03 16:41:59 -05:00
$this -> console = $console ;
2020-06-11 11:10:45 -05:00
$this -> configs = $configs [ 'storages' ][ 'taskwarrior' ];
2021-07-05 16:41:38 -05:00
$this -> logger = $logger ;
2020-05-03 16:41:59 -05:00
}
2020-06-14 23:55:05 -05:00
public function getConfigBrowser () {
$html = '<tr>' ;
$html .= '<th>taskrc</th>' ;
$html .= '<td>The enivronment variable overrides the default and the command line specification of the .taskrc file</td>' ;
$html .= '<td><input name="tw_taskrc" type="text" value="' . $this -> configs [ 'taskrc' ] . '"></td>' ;
$html .= '</tr>' ;
$html .= '<tr>' ;
$html .= '<th>taskdata</th>' ;
$html .= '<td>The environment variable overrides the default and the command line, and the "data.location" configuration setting of the task data directory</td>' ;
$html .= '<td><input name="tw_taskdata" type="text" value="' . $this -> configs [ 'taskdata' ] . '"></td>' ;
$html .= '</tr>' ;
2020-09-18 22:15:12 -05:00
$html .= '<tr>' ;
$html .= '<th>default_calendar</th>' ;
$html .= '<td>The default calendar to send tasks if no task project is set. The value is the calendar\'s displayname</td>' ;
$html .= '<td><input name="tw_default_calendar" type="text" value="' . $this -> configs [ 'default_calendar' ] . '"></td>' ;
$html .= '</tr>' ;
2020-06-14 23:55:05 -05:00
return $html ;
}
public function updateConfigs ( $postData ) {
if ( isset ( $postData [ 'tw_taskrc' ])) {
$this -> configs [ 'taskrc' ] = $postData [ 'tw_taskrc' ];
}
if ( isset ( $postData [ 'tw_taskdata' ])){
$this -> configs [ 'taskdata' ] = $postData [ 'tw_taskdata' ];
}
2020-09-18 22:15:12 -05:00
if ( isset ( $postData [ 'tw_default_calendar' ])){
$this -> configs [ 'default_calendar' ] = $postData [ 'tw_default_calendar' ];
}
2020-06-14 23:55:05 -05:00
return $this -> configs ;
2020-05-03 16:41:59 -05:00
}
public function refresh () {
2020-09-18 22:15:12 -05:00
$this -> logger -> info ( 'Syncing taskwarrior tasks...' );
2021-07-05 16:41:38 -05:00
$this -> console -> execute ( 'task' , [ 'sync' ], null ,
2020-05-28 11:54:21 -05:00
[ 'TASKRC' => $this -> configs [ 'taskrc' ], 'TASKDATA' => $this -> configs [ 'taskdata' ]]);
2020-06-03 00:04:43 -05:00
$this -> tasks = json_decode ( $this -> console -> execute ( 'task' , [ 'export' ], null ,
2020-06-02 21:16:18 -05:00
[ 'TASKRC' => $this -> configs [ 'taskrc' ], 'TASKDATA' => $this -> configs [ 'taskdata' ]]), true );
2020-06-03 00:04:43 -05:00
foreach ( $this -> tasks as $task ) {
2020-06-02 21:16:18 -05:00
if ( isset ( $task [ 'uid' ])) {
$this -> tasks [ $task [ 'uid' ]] = $task ;
}
}
2020-05-03 16:41:59 -05:00
}
2020-09-18 22:15:12 -05:00
public function vObjectToTask ( $vtodo , string $displayname ) {
2020-05-28 11:54:21 -05:00
if ( isset ( $this -> tasks [( string ) $vtodo -> UID ])) {
$task = $this -> tasks [( string ) $vtodo -> UID ];
2020-05-03 16:41:59 -05:00
} else {
$task = [];
2020-05-12 23:56:22 -05:00
$task [ 'uid' ] = ( string ) $vtodo -> UID ;
2020-05-03 16:41:59 -05:00
}
2020-06-02 21:16:18 -05:00
if ( isset ( $vtodo -> SUMMARY )){
2020-05-12 23:56:22 -05:00
$task [ 'description' ] = ( string ) $vtodo -> SUMMARY ;
2021-07-05 16:41:38 -05:00
}
2020-06-14 23:55:05 -05:00
if ( isset ( $vtodo -> DESCRIPTION )) {
$annotations = [];
if ( isset ( $task [ 'annotations' ])) {
$annotations = $task [ 'annotations' ];
}
$task [ 'annotations' ] = [];
$descriptionLines = explode ( '\n' , $vtodo -> DESCRIPTION );
foreach ( $descriptionLines as $key => $descriptionLine ) {
$annotationEntry = $vtodo -> DTSTAMP -> getDateTime () -> modify ( " + $key second " ) -> format ( \DateTime :: ISO8601 );
foreach ( $annotations as $annotation ) {
if ( $annotation [ 'description' ] == $descriptionLine ) {
$annotationEntry = $annotation [ 'entry' ];
break ;
}
}
2020-06-27 00:56:44 -05:00
array_push ( $annotations , [ 'description' => $descriptionLine , 'entry' => $annotationEntry ]);
$task [ 'annotations' ] = $annotations ;
2020-06-14 23:55:05 -05:00
}
2020-05-03 16:41:59 -05:00
}
2020-06-14 23:55:05 -05:00
if ( ! isset ( $task [ 'entry' ])){
$task [ 'entry' ] = $vtodo -> DTSTAMP -> getDateTime () -> format ( \DateTime :: ISO8601 );
2021-07-05 16:41:38 -05:00
}
2020-05-03 16:41:59 -05:00
2020-05-12 23:56:22 -05:00
if ( isset ( $vtodo -> DTSTART )) {
2020-06-14 23:55:05 -05:00
$task [ 'start' ] = $vtodo -> DTSTART -> getDateTime () -> format ( \DateTime :: ISO8601 );
2020-05-12 23:56:22 -05:00
}
2020-09-18 22:15:12 -05:00
if ( isset ( $vtodo -> DTEND )){
$task [ 'end' ] = $vtodo -> DTEND -> getDateTime () -> format ( \DateTime :: ISO8601 );
2020-05-12 23:56:22 -05:00
}
if ( isset ( $vtodo -> { 'LAST-MODIFIED' })) {
2020-06-14 23:55:05 -05:00
$task [ 'modified' ] = $vtodo -> { 'LAST-MODIFIED' } -> getDateTime () -> format ( \DateTime :: ISO8601 );
2020-05-12 23:56:22 -05:00
}
if ( isset ( $vtodo -> PRIORITY )) {
$priority = $vtodo -> PRIORITY -> getJsonValue ();
if ( $priority < 5 ) {
$task [ 'priority' ] = 'H' ;
} else if ( $priority === 5 ) {
$task [ 'priority' ] = 'M' ;
} else if ( $priority > 5 && $priority < 10 ) {
$task [ 'priority' ] = 'L' ;
}
}
2021-01-07 23:52:00 -06:00
if ( isset ( $vtodo -> DUE )) {
2020-06-14 23:55:05 -05:00
$task [ 'due' ] = $vtodo -> DUE -> getDateTime () -> format ( \DateTime :: ISO8601 );
2021-01-07 23:52:00 -06:00
} else if ( isset ( $task [ 'due' ])) {
$task [ 'due' ] = '' ;
2020-05-03 16:41:59 -05:00
}
2020-05-12 23:56:22 -05:00
if ( isset ( $vtodo -> RRULE )) {
$rules = $vtodo -> RRULE -> getParts ();
if ( isset ( $rules [ 'FREQ' ])) {
$task [ 'recu' ] = $rules [ 'FREQ' ];
}
if ( isset ( $rules [ 'UNTIL' ])) {
$task [ 'until' ] = $rules [ 'UNTIL' ];
}
}
if ( isset ( $vtodo -> STATUS )) {
switch (( string ) $vtodo -> STATUS ) {
2020-05-28 11:54:21 -05:00
case 'NEEDS-ACTION' :
$task [ 'status' ] = 'pending' ;
break ;
case 'COMPLETED' :
$task [ 'status' ] = 'completed' ;
if ( ! isset ( $task [ 'end' ])) {
2020-06-14 23:55:05 -05:00
$task [ 'end' ] = $vtodo -> DTSTAMP -> getDateTime () -> format ( \DateTime :: ISO8601 );
2020-05-28 11:54:21 -05:00
}
break ;
case 'CANCELED' :
$task [ 'status' ] = 'deleted' ;
if ( ! isset ( $task [ 'end' ])) {
2020-06-14 23:55:05 -05:00
$task [ 'end' ] = $vtodo -> DTSTAMP -> getDateTime () -> format ( \DateTime :: ISO8601 );
2020-05-28 11:54:21 -05:00
}
break ;
2020-05-12 23:56:22 -05:00
}
}
if ( isset ( $vtodo -> CATEGORIES )) {
2020-09-13 01:26:22 -05:00
$task [ 'tags' ] = $vtodo -> CATEGORIES -> getJsonValue ();
2020-09-18 22:15:12 -05:00
}
2020-05-12 23:56:22 -05:00
2020-06-14 23:55:05 -05:00
if ( isset ( $vtodo -> GEO )){
$task [ 'geo' ] = $vtodo -> GEO -> getRawMimeDirValue ();
}
2020-09-18 22:15:12 -05:00
if ( $this -> configs [ 'default_calendar' ] != $displayname ) {
$task [ 'project' ] = $displayname ;
}
2020-05-28 11:54:21 -05:00
return $task ;
}
2020-05-03 16:41:59 -05:00
2020-09-18 22:15:12 -05:00
public function save ( Calendar $c , string $displayname ) {
2020-06-02 21:16:18 -05:00
try {
if ( ! isset ( $c -> VTODO )){
throw new \Exception ( 'Calendar event does not contain VTODO' );
}
2021-07-05 16:41:38 -05:00
$this -> logger -> info ( sprintf ( 'Executing on calendar %s' , $displayname ));
2020-06-02 21:16:18 -05:00
$this -> logger -> info ( json_encode ( $c -> jsonSerialize ()));
$this -> refresh ();
2020-09-18 22:15:12 -05:00
$task = $this -> vObjectToTask ( $c -> VTODO , $displayname );
2020-06-02 21:16:18 -05:00
$this -> logger -> info ( json_encode ( $task ));
$this -> logger -> info (
sprintf ( 'Executing TASKRC = %s TASKDATA = %s task import %s' , $this -> configs [ 'taskrc' ], $this -> configs [ 'taskdata' ], json_encode ( $task ))
);
2021-07-05 16:41:38 -05:00
$output = $this -> console -> execute ( 'task' , [ 'import' ], $task ,
2020-06-02 21:16:18 -05:00
[ 'TASKRC' => $this -> configs [ 'taskrc' ], 'TASKDATA' => $this -> configs [ 'taskdata' ]]);
2020-09-18 22:15:12 -05:00
$this -> refresh ();
2020-06-02 21:16:18 -05:00
$this -> logger -> info ( $output );
} catch ( \Exception $e ) {
$this -> logger -> error ( $e -> getTraceAsString ());
throw $e ;
2020-05-03 16:41:59 -05:00
}
2020-05-28 11:54:21 -05:00
}
2020-06-27 00:56:44 -05:00
public function remove ( $uid ) {
try {
$this -> logger -> info ( sprintf ( 'Deleting iCal %s from taskwarrior' , $uid ));
$this -> refresh ();
2020-08-23 17:39:56 -05:00
if ( ! array_key_exists (( string ) $uid , $this -> tasks )) {
2021-07-05 16:41:38 -05:00
$this -> logger -> warn ( sprintf ( 'Could not find task %s to be remove. Skipping' , ( string ) $uid ));
2020-08-23 17:39:56 -05:00
return ;
}
2020-06-27 00:56:44 -05:00
$task = $this -> tasks [( string ) $uid ];
if ( isset ( $task ) && $task [ 'status' ] !== 'deleted' ) {
2021-07-05 16:41:38 -05:00
$this -> logger -> info ( sprintf ( 'Deleting iCal %s from taskwarrior' , $uid ));
2020-06-27 00:56:44 -05:00
$uuid = $task [ 'uuid' ];
$this -> logger -> info (
2021-07-05 16:41:38 -05:00
sprintf ( 'Executing TASKRC = %s TASKDATA = %s task delete %s' , $this -> configs [ 'taskrc' ], $this -> configs [ 'taskdata' ], $uuid )
2020-06-27 00:56:44 -05:00
);
2021-07-05 16:41:38 -05:00
$output = $this -> console -> execute ( 'task' , [ 'delete' , ( string ) $uuid ], null ,
2020-06-27 00:56:44 -05:00
[ 'TASKRC' => $this -> configs [ 'taskrc' ], 'TASKDATA' => $this -> configs [ 'taskdata' ]]);
$this -> logger -> info ( $output );
2020-09-18 22:15:12 -05:00
$this -> refresh ();
2020-06-27 00:56:44 -05:00
} else if ( isset ( $task ) && $task [ 'status' ] === 'deleted' ) {
$this -> logger -> warn ( sprintf ( 'Task %s has already been deleted' , $task [ 'uuid' ]));
} else {
$this -> logger -> error ( sprintf ( 'Could not find task for iCal %s to be deleted' , $uid ));
}
} catch ( \Exception $e ) {
$this -> logger -> error ( $e -> getMessage ());
$this -> logger -> error ( $e -> getTraceAsString ());
throw $e ;
}
}
2020-05-28 11:54:21 -05:00
}