style: remove unused code and updated plugin
This commit is contained in:
parent
a2b2073bad
commit
68470e3dee
|
@ -28,14 +28,34 @@ class Config {
|
||||||
private $rcOptions;
|
private $rcOptions;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function __construct($taskrc='~/.taskrc', $taskData='~/.task',$rcOptions = [], $bin='task'){
|
public function __construct($taskrc='~/.taskrc', $taskData='~/.task',$rcOptions = [], $bin='task'){
|
||||||
$this->taskrc = $taskrc;
|
$this->taskrc = $taskrc;
|
||||||
$this->bin = $bin;
|
$this->bin = $bin;
|
||||||
$this->taskDat = $taskData;
|
$this->taskData = $taskData;
|
||||||
$this->rcOptions = $rcOptions;
|
$this->rcOptions = array_merge(
|
||||||
|
array(
|
||||||
|
'rc:' . $this->taskrc,
|
||||||
|
'rc.data.location=' . $this->taskData,
|
||||||
|
'rc.json.array=true',
|
||||||
|
'rc.json.depends.array=true',
|
||||||
|
'rc.confirmation=no',
|
||||||
|
),
|
||||||
|
$rcOptions
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTaskBin(){
|
||||||
|
return $this->bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOptions(){
|
||||||
|
return $this->rcOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function getTaskwarriorInstance(){
|
public function getTaskwarriorInstance(){
|
||||||
|
|
||||||
$this->taskwarrior = new Taskwarrior($this->taskrc,$this->taskdatadir, [], $this->taskbinfile);
|
$this->taskwarrior = new Taskwarrior($this->taskrc,$this->taskdatadir, [], $this->taskbinfile);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
class TaskwarriorCommandException extends Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
712
src/Plugin.php
712
src/Plugin.php
|
@ -57,24 +57,7 @@ class Plugin extends ServerPlugin {
|
||||||
function initialize(Server $server) {
|
function initialize(Server $server) {
|
||||||
|
|
||||||
$this->server = $server;
|
$this->server = $server;
|
||||||
$server->on('method:GET', [$this, 'httpGet']);
|
|
||||||
$server->on('method:OPTIONS', [$this, 'httpOptions']);
|
|
||||||
$server->on('method:HEAD', [$this, 'httpHead']);
|
|
||||||
$server->on('method:DELETE', [$this, 'httpDelete']);
|
|
||||||
$server->on('method:PROPFIND', [$this, 'httpPropFind']);
|
|
||||||
$server->on('method:PROPPATCH', [$this, 'httpPropPatch']);
|
|
||||||
$server->on('method:PUT', [$this, 'httpPut']);
|
|
||||||
$server->on('method:MKCOL', [$this, 'httpMkcol']);
|
|
||||||
$server->on('method:MOVE', [$this, 'httpMove']);
|
|
||||||
$server->on('method:COPY', [$this, 'httpCopy']);
|
|
||||||
$server->on('method:REPORT', [$this, 'httpReport']);
|
|
||||||
|
|
||||||
$server->on('propPatch', [$this, 'propPatchProtectedPropertyCheck'], 90);
|
|
||||||
$server->on('propPatch', [$this, 'propPatchNodeUpdate'], 200);
|
|
||||||
$server->on('calendarObjectChange', [$this, 'calendarObjectChange']);
|
$server->on('calendarObjectChange', [$this, 'calendarObjectChange']);
|
||||||
//$server->on('propFind', [$this, 'propFind']);
|
|
||||||
//$server->on('propFind', [$this, 'propFindNode'], 120);
|
|
||||||
//$server->on('propFind', [$this, 'propFindLate'], 200);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,12 +82,16 @@ class Plugin extends ServerPlugin {
|
||||||
*/
|
*/
|
||||||
function processCalendarEventForTaskwarrior(Document $vCal){
|
function processCalendarEventForTaskwarrior(Document $vCal){
|
||||||
try {
|
try {
|
||||||
$this->twCalManager->importTask($vCal->VTODO);
|
if(isset($vCal->VTODO)){
|
||||||
|
$response = $this->twCalManager->importTask($vCal->VTODO);
|
||||||
|
}
|
||||||
} catch(BadRequest $e){
|
} catch(BadRequest $e){
|
||||||
throw new BadRequest($e->getMessage(), null, $e);
|
throw new BadRequest($e->getMessage(), null, $e);
|
||||||
} catch(Exception $e){
|
} catch(Exception $e){
|
||||||
throw new Exception($e->getMessage(), null, $e);
|
throw new Exception($e->getMessage(), null, $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* * This method is triggered whenever there was a calendar object gets
|
* * This method is triggered whenever there was a calendar object gets
|
||||||
|
@ -120,703 +107,18 @@ class Plugin extends ServerPlugin {
|
||||||
* */
|
* */
|
||||||
function calendarObjectChange(RequestInterface $request, ResponseInterface $response, Document $vCal, $calendarPath, &$modified, $isNew) {
|
function calendarObjectChange(RequestInterface $request, ResponseInterface $response, Document $vCal, $calendarPath, &$modified, $isNew) {
|
||||||
$calendarNode = $this->server->tree->getNodeForPath($calendarPath);
|
$calendarNode = $this->server->tree->getNodeForPath($calendarPath);
|
||||||
|
$body = '';
|
||||||
if ($isNew) {
|
if ($isNew) {
|
||||||
try {
|
try {
|
||||||
$this->processCalendarEventForTaskwarrior($vCal);
|
$body = $this->processCalendarEventForTaskwarrior($vCal);
|
||||||
} catch(Exception\BadRequest $e){
|
} catch(Exception\BadRequest $e){
|
||||||
$response->setStatus(200);
|
|
||||||
$response->setBody('');
|
|
||||||
$response->setHeader('Content-Type', 'text/plain');
|
|
||||||
$response->setHeader('X-Sabre-Real-Status', $e->getHTTPCode());
|
$response->setHeader('X-Sabre-Real-Status', $e->getHTTPCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
|
||||||
* This is the default implementation for the GET method.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpGet(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
$node = $this->server->tree->getNodeForPath($path);
|
|
||||||
|
|
||||||
if (!$node instanceof IFile) return;
|
|
||||||
|
|
||||||
$body = $node->get();
|
|
||||||
|
|
||||||
echo($body);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP OPTIONS
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpOptions(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$methods = $this->server->getAllowedMethods($request->getPath());
|
|
||||||
echo('httpOptions ' . $response);
|
|
||||||
|
|
||||||
$response->setHeader('Allow', strtoupper(implode(', ', $methods)));
|
|
||||||
$features = ['1', '3', 'extended-mkcol'];
|
|
||||||
|
|
||||||
foreach ($this->server->getPlugins() as $plugin) {
|
|
||||||
$features = array_merge($features, $plugin->getFeatures());
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->setHeader('DAV', implode(', ', $features));
|
|
||||||
$response->setHeader('MS-Author-Via', 'DAV');
|
|
||||||
$response->setHeader('Accept-Ranges', 'bytes');
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
$response->setStatus(200);
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP HEAD
|
|
||||||
*
|
|
||||||
* This method is normally used to take a peak at a url, and only get the
|
|
||||||
* HTTP response headers, without the body. This is used by clients to
|
|
||||||
* determine if a remote file was changed, so they can use a local cached
|
|
||||||
* version, instead of downloading it again
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpHead(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
// This is implemented by changing the HEAD request to a GET request,
|
|
||||||
// and dropping the response body.
|
|
||||||
$subRequest = clone $request;
|
|
||||||
$subRequest->setMethod('GET');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->server->invokeMethod($subRequest, $response, false);
|
|
||||||
$response->setBody('');
|
|
||||||
} catch (Exception\NotImplemented $e) {
|
|
||||||
// Some clients may do HEAD requests on collections, however, GET
|
|
||||||
// requests and HEAD requests _may_ not be defined on a collection,
|
|
||||||
// which would trigger a 501.
|
|
||||||
// This breaks some clients though, so we're transforming these
|
|
||||||
// 501s into 200s.
|
|
||||||
$response->setStatus(200);
|
$response->setStatus(200);
|
||||||
$response->setBody('');
|
$response->setBody('');
|
||||||
$response->setHeader('Content-Type', 'text/plain');
|
$response->setHeader('Content-Type', 'text/plain');
|
||||||
$response->setHeader('X-Sabre-Real-Status', $e->getHTTPCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP Delete
|
|
||||||
*
|
|
||||||
* The HTTP delete method, deletes a given uri
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function httpDelete(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
echo('httpDelete.path ' . $path);
|
|
||||||
|
|
||||||
if (!$this->server->emit('beforeUnbind', [$path])) return false;
|
|
||||||
$this->server->tree->delete($path);
|
|
||||||
$this->server->emit('afterUnbind', [$path]);
|
|
||||||
|
|
||||||
$response->setStatus(204);
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebDAV PROPFIND
|
|
||||||
*
|
|
||||||
* This WebDAV method requests information about an uri resource, or a list of resources
|
|
||||||
* If a client wants to receive the properties for a single resource it will add an HTTP Depth: header with a 0 value
|
|
||||||
* If the value is 1, it means that it also expects a list of sub-resources (e.g.: files in a directory)
|
|
||||||
*
|
|
||||||
* The request body contains an XML data structure that has a list of properties the client understands
|
|
||||||
* The response body is also an xml document, containing information about every uri resource and the requested properties
|
|
||||||
*
|
|
||||||
* It has to return a HTTP 207 Multi-status status code
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function httpPropFind(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
$requestBody = $request->getBodyAsString();
|
|
||||||
if (strlen($requestBody)) {
|
|
||||||
try {
|
|
||||||
$propFindXml = $this->server->xml->expect('{DAV:}propfind', $requestBody);
|
|
||||||
} catch (ParseException $e) {
|
|
||||||
throw new BadRequest($e->getMessage(), null, $e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$propFindXml = new Xml\Request\PropFind();
|
|
||||||
$propFindXml->allProp = true;
|
|
||||||
$propFindXml->properties = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$depth = $this->server->getHTTPDepth(1);
|
|
||||||
// The only two options for the depth of a propfind is 0 or 1 - as long as depth infinity is not enabled
|
|
||||||
if (!$this->server->enablePropfindDepthInfinity && $depth != 0) $depth = 1;
|
|
||||||
|
|
||||||
$newProperties = $this->server->getPropertiesForPath($path, $propFindXml->properties, $depth);
|
|
||||||
|
|
||||||
// This is a multi-status response
|
|
||||||
$response->setStatus(207);
|
|
||||||
$response->setHeader('Content-Type', 'application/xml; charset=utf-8');
|
|
||||||
$response->setHeader('Vary', 'Brief,Prefer');
|
|
||||||
|
|
||||||
// Normally this header is only needed for OPTIONS responses, however..
|
|
||||||
// iCal seems to also depend on these being set for PROPFIND. Since
|
|
||||||
// this is not harmful, we'll add it.
|
|
||||||
$features = ['1', '3', 'extended-mkcol'];
|
|
||||||
foreach ($this->server->getPlugins() as $plugin) {
|
|
||||||
$features = array_merge($features, $plugin->getFeatures());
|
|
||||||
}
|
|
||||||
$response->setHeader('DAV', implode(', ', $features));
|
|
||||||
|
|
||||||
$prefer = $this->server->getHTTPPrefer();
|
|
||||||
$minimal = $prefer['return'] === 'minimal';
|
|
||||||
|
|
||||||
$data = $this->server->generateMultiStatus($newProperties, $minimal);
|
|
||||||
echo('httppropfind ' . $data);
|
|
||||||
|
|
||||||
$response->setBody($data);
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebDAV PROPPATCH
|
|
||||||
*
|
|
||||||
* This method is called to update properties on a Node. The request is an XML body with all the mutations.
|
|
||||||
* In this XML body it is specified which properties should be set/updated and/or deleted
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpPropPatch(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
try {
|
|
||||||
$propPatch = $this->server->xml->expect('{DAV:}propertyupdate', $request->getBody());
|
|
||||||
} catch (ParseException $e) {
|
|
||||||
throw new BadRequest($e->getMessage(), null, $e);
|
|
||||||
}
|
|
||||||
$newProperties = $propPatch->properties;
|
|
||||||
|
|
||||||
$result = $this->server->updateProperties($path, $newProperties);
|
|
||||||
|
|
||||||
$prefer = $this->server->getHTTPPrefer();
|
|
||||||
$response->setHeader('Vary', 'Brief,Prefer');
|
|
||||||
|
|
||||||
if ($prefer['return'] === 'minimal') {
|
|
||||||
|
|
||||||
// If return-minimal is specified, we only have to check if the
|
|
||||||
// request was succesful, and don't need to return the
|
|
||||||
// multi-status.
|
|
||||||
$ok = true;
|
|
||||||
foreach ($result as $prop => $code) {
|
|
||||||
if ((int)$code > 299) {
|
|
||||||
$ok = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ok) {
|
|
||||||
|
|
||||||
$response->setStatus(204);
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->setStatus(207);
|
|
||||||
$response->setHeader('Content-Type', 'application/xml; charset=utf-8');
|
|
||||||
|
|
||||||
|
|
||||||
// Reorganizing the result for generateMultiStatus
|
|
||||||
$multiStatus = [];
|
|
||||||
foreach ($result as $propertyName => $code) {
|
|
||||||
if (isset($multiStatus[$code])) {
|
|
||||||
$multiStatus[$code][$propertyName] = null;
|
|
||||||
} else {
|
|
||||||
$multiStatus[$code] = [$propertyName => null];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$multiStatus['href'] = $path;
|
|
||||||
|
|
||||||
$response->setBody(
|
|
||||||
$this->server->generateMultiStatus([$multiStatus])
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP PUT method
|
|
||||||
*
|
|
||||||
* This HTTP method updates a file, or creates a new one.
|
|
||||||
*
|
|
||||||
* If a new resource was created, a 201 Created status code should be returned. If an existing resource is updated, it's a 204 No Content
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpPut(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$body = $request->getBodyAsStream();
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
// Intercepting Content-Range
|
|
||||||
if ($request->getHeader('Content-Range')) {
|
|
||||||
/*
|
|
||||||
An origin server that allows PUT on a given target resource MUST send
|
|
||||||
a 400 (Bad Request) response to a PUT request that contains a
|
|
||||||
Content-Range header field.
|
|
||||||
|
|
||||||
Reference: http://tools.ietf.org/html/rfc7231#section-4.3.4
|
|
||||||
*/
|
|
||||||
throw new Exception\BadRequest('Content-Range on PUT requests are forbidden.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intercepting the Finder problem
|
|
||||||
if (($expected = $request->getHeader('X-Expected-Entity-Length')) && $expected > 0) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
Many webservers will not cooperate well with Finder PUT requests,
|
|
||||||
because it uses 'Chunked' transfer encoding for the request body.
|
|
||||||
|
|
||||||
The symptom of this problem is that Finder sends files to the
|
|
||||||
server, but they arrive as 0-length files in PHP.
|
|
||||||
|
|
||||||
If we don't do anything, the user might think they are uploading
|
|
||||||
files successfully, but they end up empty on the server. Instead,
|
|
||||||
we throw back an error if we detect this.
|
|
||||||
|
|
||||||
The reason Finder uses Chunked, is because it thinks the files
|
|
||||||
might change as it's being uploaded, and therefore the
|
|
||||||
Content-Length can vary.
|
|
||||||
|
|
||||||
Instead it sends the X-Expected-Entity-Length header with the size
|
|
||||||
of the file at the very start of the request. If this header is set,
|
|
||||||
but we don't get a request body we will fail the request to
|
|
||||||
protect the end-user.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Only reading first byte
|
|
||||||
$firstByte = fread($body, 1);
|
|
||||||
if (strlen($firstByte) !== 1) {
|
|
||||||
throw new Exception\Forbidden('This server is not compatible with OS/X finder. Consider using a different WebDAV client or webserver.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// The body needs to stay intact, so we copy everything to a
|
|
||||||
// temporary stream.
|
|
||||||
|
|
||||||
$newBody = fopen('php://temp', 'r+');
|
|
||||||
fwrite($newBody, $firstByte);
|
|
||||||
stream_copy_to_stream($body, $newBody);
|
|
||||||
rewind($newBody);
|
|
||||||
|
|
||||||
$body = $newBody;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->server->tree->nodeExists($path)) {
|
|
||||||
|
|
||||||
$node = $this->server->tree->getNodeForPath($path);
|
|
||||||
|
|
||||||
// If the node is a collection, we'll deny it
|
|
||||||
if (!($node instanceof IFile)) throw new Exception\Conflict('PUT is not allowed on non-files.');
|
|
||||||
|
|
||||||
if (!$this->server->updateFile($path, $body, $etag)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
if ($etag) $response->setHeader('ETag', $etag);
|
|
||||||
$response->setStatus(204);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$etag = null;
|
|
||||||
// If we got here, the resource didn't exist yet.
|
|
||||||
if (!$this->server->createFile($path, $body, $etag)) {
|
|
||||||
// For one reason or another the file was not created.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
if ($etag) $response->setHeader('ETag', $etag);
|
|
||||||
$response->setStatus(201);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebDAV MKCOL
|
|
||||||
*
|
|
||||||
* The MKCOL method is used to create a new collection (directory) on the server
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpMkcol(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$requestBody = $request->getBodyAsString();
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
if ($requestBody) {
|
|
||||||
|
|
||||||
$contentType = $request->getHeader('Content-Type');
|
|
||||||
if (strpos($contentType, 'application/xml') !== 0 && strpos($contentType, 'text/xml') !== 0) {
|
|
||||||
|
|
||||||
// We must throw 415 for unsupported mkcol bodies
|
|
||||||
throw new Exception\UnsupportedMediaType('The request body for the MKCOL request must have an xml Content-Type');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$mkcol = $this->server->xml->expect('{DAV:}mkcol', $requestBody);
|
|
||||||
} catch (\Sabre\Xml\ParseException $e) {
|
|
||||||
throw new Exception\BadRequest($e->getMessage(), null, $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
$properties = $mkcol->getProperties();
|
|
||||||
|
|
||||||
if (!isset($properties['{DAV:}resourcetype']))
|
|
||||||
throw new Exception\BadRequest('The mkcol request must include a {DAV:}resourcetype property');
|
|
||||||
|
|
||||||
$resourceType = $properties['{DAV:}resourcetype']->getValue();
|
|
||||||
unset($properties['{DAV:}resourcetype']);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$properties = [];
|
|
||||||
$resourceType = ['{DAV:}collection'];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$mkcol = new MkCol($resourceType, $properties);
|
|
||||||
|
|
||||||
$result = $this->server->createCollection($path, $mkcol);
|
|
||||||
|
|
||||||
if (is_array($result)) {
|
|
||||||
$response->setStatus(207);
|
|
||||||
$response->setHeader('Content-Type', 'application/xml; charset=utf-8');
|
|
||||||
|
|
||||||
$response->setBody(
|
|
||||||
$this->server->generateMultiStatus([$result])
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
$response->setStatus(201);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebDAV HTTP MOVE method
|
|
||||||
*
|
|
||||||
* This method moves one uri to a different uri. A lot of the actual request processing is done in getCopyMoveInfo
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpMove(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
$moveInfo = $this->server->getCopyAndMoveInfo($request);
|
|
||||||
|
|
||||||
if ($moveInfo['destinationExists']) {
|
|
||||||
|
|
||||||
if (!$this->server->emit('beforeUnbind', [$moveInfo['destination']])) return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (!$this->server->emit('beforeUnbind', [$path])) return false;
|
|
||||||
if (!$this->server->emit('beforeBind', [$moveInfo['destination']])) return false;
|
|
||||||
if (!$this->server->emit('beforeMove', [$path, $moveInfo['destination']])) return false;
|
|
||||||
|
|
||||||
if ($moveInfo['destinationExists']) {
|
|
||||||
|
|
||||||
$this->server->tree->delete($moveInfo['destination']);
|
|
||||||
$this->server->emit('afterUnbind', [$moveInfo['destination']]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->server->tree->move($path, $moveInfo['destination']);
|
|
||||||
|
|
||||||
// Its important afterMove is called before afterUnbind, because it
|
|
||||||
// allows systems to transfer data from one path to another.
|
|
||||||
// PropertyStorage uses this. If afterUnbind was first, it would clean
|
|
||||||
// up all the properties before it has a chance.
|
|
||||||
$this->server->emit('afterMove', [$path, $moveInfo['destination']]);
|
|
||||||
$this->server->emit('afterUnbind', [$path]);
|
|
||||||
$this->server->emit('afterBind', [$moveInfo['destination']]);
|
|
||||||
|
|
||||||
// If a resource was overwritten we should send a 204, otherwise a 201
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
$response->setStatus($moveInfo['destinationExists'] ? 204 : 201);
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebDAV HTTP COPY method
|
|
||||||
*
|
|
||||||
* This method copies one uri to a different uri, and works much like the MOVE request
|
|
||||||
* A lot of the actual request processing is done in getCopyMoveInfo
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpCopy(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
$copyInfo = $this->server->getCopyAndMoveInfo($request);
|
|
||||||
|
|
||||||
if (!$this->server->emit('beforeBind', [$copyInfo['destination']])) return false;
|
|
||||||
if ($copyInfo['destinationExists']) {
|
|
||||||
if (!$this->server->emit('beforeUnbind', [$copyInfo['destination']])) return false;
|
|
||||||
$this->server->tree->delete($copyInfo['destination']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->server->tree->copy($path, $copyInfo['destination']);
|
|
||||||
$this->server->emit('afterBind', [$copyInfo['destination']]);
|
|
||||||
|
|
||||||
// If a resource was overwritten we should send a 204, otherwise a 201
|
|
||||||
$response->setHeader('Content-Length', '0');
|
|
||||||
$response->setStatus($copyInfo['destinationExists'] ? 204 : 201);
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP REPORT method implementation
|
|
||||||
*
|
|
||||||
* Although the REPORT method is not part of the standard WebDAV spec (it's from rfc3253)
|
|
||||||
* It's used in a lot of extensions, so it made sense to implement it into the core.
|
|
||||||
*
|
|
||||||
* @param RequestInterface $request
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function httpReport(RequestInterface $request, ResponseInterface $response) {
|
|
||||||
|
|
||||||
$path = $request->getPath();
|
|
||||||
|
|
||||||
$result = $this->server->xml->parse(
|
|
||||||
$request->getBody(),
|
|
||||||
$request->getUrl(),
|
|
||||||
$rootElementName
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($this->server->emit('report', [$rootElementName, $result, $path])) {
|
|
||||||
|
|
||||||
// If emit returned true, it means the report was not supported
|
|
||||||
throw new Exception\ReportNotSupported();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sending back false will interupt the event chain and tell the server
|
|
||||||
// we've handled this method.
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called during property updates.
|
|
||||||
*
|
|
||||||
* Here we check if a user attempted to update a protected property and
|
|
||||||
* ensure that the process fails if this is the case.
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param PropPatch $propPatch
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function propPatchProtectedPropertyCheck($path, PropPatch $propPatch) {
|
|
||||||
|
|
||||||
// Comparing the mutation list to the list of propetected properties.
|
|
||||||
$mutations = $propPatch->getMutations();
|
|
||||||
|
|
||||||
$protected = array_intersect(
|
|
||||||
$this->server->protectedProperties,
|
|
||||||
array_keys($mutations)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($protected) {
|
|
||||||
$propPatch->setResultCode($protected, 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called during property updates.
|
|
||||||
*
|
|
||||||
* Here we check if a node implements IProperties and let the node handle
|
|
||||||
* updating of (some) properties.
|
|
||||||
*
|
|
||||||
* @param string $path
|
|
||||||
* @param PropPatch $propPatch
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function propPatchNodeUpdate($path, PropPatch $propPatch) {
|
|
||||||
|
|
||||||
// This should trigger a 404 if the node doesn't exist.
|
|
||||||
$node = $this->server->tree->getNodeForPath($path);
|
|
||||||
|
|
||||||
if ($node instanceof IProperties) {
|
|
||||||
$node->propPatch($propPatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when properties are retrieved.
|
|
||||||
*
|
|
||||||
* Here we add all the default properties.
|
|
||||||
*
|
|
||||||
* @param PropFind $propFind
|
|
||||||
* @param INode $node
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function propFind(PropFind $propFind, INode $node) {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches properties for a node.
|
|
||||||
*
|
|
||||||
* This event is called a bit later, so plugins have a chance first to
|
|
||||||
* populate the result.
|
|
||||||
*
|
|
||||||
* @param PropFind $propFind
|
|
||||||
* @param INode $node
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function propFindNode(PropFind $propFind, INode $node) {
|
|
||||||
|
|
||||||
if ($node instanceof IProperties && $propertyNames = $propFind->get404Properties()) {
|
|
||||||
|
|
||||||
$nodeProperties = $node->getProperties($propertyNames);
|
|
||||||
foreach ($propertyNames as $propertyName) {
|
|
||||||
if (array_key_exists($propertyName, $nodeProperties)) {
|
|
||||||
$propFind->set($propertyName, $nodeProperties[$propertyName], 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when properties are retrieved.
|
|
||||||
*
|
|
||||||
* This specific handler is called very late in the process, because we
|
|
||||||
* want other systems to first have a chance to handle the properties.
|
|
||||||
*
|
|
||||||
* @param PropFind $propFind
|
|
||||||
* @param INode $node
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function propFindLate(PropFind $propFind, INode $node) {
|
|
||||||
|
|
||||||
$propFind->handle('{http://calendarserver.org/ns/}getctag', function() use ($propFind) {
|
|
||||||
|
|
||||||
// If we already have a sync-token from the current propFind
|
|
||||||
// request, we can re-use that.
|
|
||||||
$val = $propFind->get('{http://sabredav.org/ns}sync-token');
|
|
||||||
if ($val) return $val;
|
|
||||||
|
|
||||||
$val = $propFind->get('{DAV:}sync-token');
|
|
||||||
if ($val && is_scalar($val)) {
|
|
||||||
return $val;
|
|
||||||
}
|
|
||||||
if ($val && $val instanceof Xml\Property\Href) {
|
|
||||||
return substr($val->getHref(), strlen(Sync\Plugin::SYNCTOKEN_PREFIX));
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we got here, the earlier two properties may simply not have
|
|
||||||
// been part of the earlier request. We're going to fetch them.
|
|
||||||
$result = $this->server->getProperties($propFind->getPath(), [
|
|
||||||
'{http://sabredav.org/ns}sync-token',
|
|
||||||
'{DAV:}sync-token',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (isset($result['{http://sabredav.org/ns}sync-token'])) {
|
|
||||||
return $result['{http://sabredav.org/ns}sync-token'];
|
|
||||||
}
|
|
||||||
if (isset($result['{DAV:}sync-token'])) {
|
|
||||||
$val = $result['{DAV:}sync-token'];
|
|
||||||
if (is_scalar($val)) {
|
|
||||||
return $val;
|
|
||||||
} elseif ($val instanceof Xml\Property\Href) {
|
|
||||||
return substr($val->getHref(), strlen(Sync\Plugin::SYNCTOKEN_PREFIX));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,8 +3,9 @@ namespace Aerex\TaskwarriorPlugin\Taskwarrior\Commands;
|
||||||
|
|
||||||
use Aerex\TaskwarriorPlugin\Taskwarrior\Task;
|
use Aerex\TaskwarriorPlugin\Taskwarrior\Task;
|
||||||
|
|
||||||
interface Strategy {
|
interface IStrategy {
|
||||||
public function add(Task $task);
|
public function add(Task $task);
|
||||||
|
public function count(Task $task);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,60 +1,78 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
namespace Aerex\TaskwarriorPlugin\Taskwarrior\Commands;
|
||||||
|
use Aerex\TaskwarriorPlugin\Taskwarrior\Task;
|
||||||
|
use Aerex\TaskwarriorPlugin\Config;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
class TodoStrategy implements IStrategy {
|
class TodoStrategy implements IStrategy {
|
||||||
|
|
||||||
public function __construct(TaskwarriorConfig $config){
|
public function __construct(TaskwarriorConfig $config){
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->cmd[] = $this->config->taskBin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add(Task $task){
|
public function add(Task $task){
|
||||||
$this->cmd[] = 'add';
|
$cmd[] = $this->config->getTaskBin();
|
||||||
|
$cmd[] = 'add';
|
||||||
|
|
||||||
if($task->getDescription() != null){
|
if($task->getDescription() != null){
|
||||||
$this->cmd[] = sprintf('"%s"', $task->getDescription());
|
$cmd[] = sprintf('"%s"', (string)$task->getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
if($task->getCategories() != null){
|
if($task->getCategories() != null){
|
||||||
$categories = implode(' +', $task->getCategories());
|
$categories = implode(' +', (string)$task->getCategories());
|
||||||
$this->cmd[] = $categories;
|
$cmd[] = $categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($task->getDue() != null){
|
if($task->getDue() != null){
|
||||||
$this->cmd[] = $task->getDue('Y-m-dTH:i:s');
|
$cmd[] = sprintf("due:%s",$task->getDue('Y-m-dTH:i:s'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($task->getRecurrence() != null){
|
if($task->getRecurrence() != null){
|
||||||
$rrule = $task->getRecurrence()->getParts();
|
$rrule = $task->getRecurrence()->getParts();
|
||||||
$this->cmd[] = sprintf('recur:%s', $rrule['FREQ']);
|
$cmd[] = sprintf('recur:%s', $rrule['FREQ']);
|
||||||
if(isset($rrule['UNTIL'])){
|
if(isset($rrule['UNTIL'])){
|
||||||
$this->cmd[] = sprintf('until:%s', $rrule['UNTIL']);
|
$cmd[] = sprintf('until:%s', $rrule['UNTIL']);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($task->getStatus() != null){
|
if($task->getStatus() != null){
|
||||||
$this->cmd[] = sprintf('status:%s', $task->getStatus());
|
$cmd[] = sprintf('status:%s', (string)$task->getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->executeCommand($cmd);
|
return $this->executeCommand($cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function count($uuid){
|
||||||
|
$cmd[] = $this->config->getTaskBin();
|
||||||
|
$cmd[] = sprintf('%s count', $uuid);
|
||||||
|
return $this->executeCommand($cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private function executeCommand($command){
|
private function executeCommand($command){
|
||||||
|
$rcOptions = $this->config->getOptions();
|
||||||
|
|
||||||
|
foreach ($rcOptions as $rcOption) {
|
||||||
|
$command[] = $rcOption;
|
||||||
|
}
|
||||||
|
|
||||||
$cmdString = implode(' ', $command);
|
$cmdString = implode(' ', $command);
|
||||||
|
echo $cmdString;
|
||||||
$process = new Process($cmdString);
|
$process = new Process($cmdString);
|
||||||
|
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
if(!$process->isSuccessful()){
|
if(!$process->isSuccessful()){
|
||||||
|
echo $process;
|
||||||
throw new TaskwarriorCommandLineException($process);
|
throw new TaskwarriorCommandLineException($process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear cmd queue
|
||||||
|
$this->cmd = [];
|
||||||
return $process->getOutput();
|
return $process->getOutput();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,118 +13,100 @@ class Task {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
|
||||||
* @JMS\Type("string")
|
|
||||||
*/
|
*/
|
||||||
private $uuid;
|
private $uuid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @JMS\Type("string")
|
|
||||||
*/
|
*/
|
||||||
private $description;
|
private $description;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @JMS\Type("string")
|
|
||||||
*/
|
*/
|
||||||
private $priority;
|
private $priority;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @JMS\Type("string")
|
|
||||||
*/
|
*/
|
||||||
private $project;
|
private $project;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $due;
|
private $due;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $wait;
|
private $wait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*
|
*
|
||||||
* @JMS\Type("array<string>")
|
|
||||||
*/
|
*/
|
||||||
private $tags;
|
private $tags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var float
|
* @var float
|
||||||
*
|
*
|
||||||
* @JMS\Type("float")
|
|
||||||
*/
|
*/
|
||||||
private $urgency;
|
private $urgency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $entry;
|
private $entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $start;
|
private $start;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @JMS\Type("Recurring")
|
|
||||||
*/
|
*/
|
||||||
private $recur;
|
private $recur;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $until;
|
private $until;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Annotation[]
|
* @var Annotation[]
|
||||||
*
|
*
|
||||||
* @JMS\Type("array<Aerex\Taskwarrior\Annotation>")
|
|
||||||
*/
|
*/
|
||||||
private $annotations = [];
|
private $annotations = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $modified;
|
private $modified;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Carbon
|
* @var Carbon
|
||||||
*
|
*
|
||||||
* @JMS\Type("Carbon")
|
|
||||||
*/
|
*/
|
||||||
private $end;
|
private $end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*
|
*
|
||||||
* @JMS\Type("string")
|
|
||||||
*/
|
*/
|
||||||
private $status;
|
private $status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Task[]|ArrayCollection
|
|
||||||
*
|
*
|
||||||
* @JMS\Type("Depends")
|
* @JMS\Type("Depends")
|
||||||
*/
|
*/
|
||||||
|
@ -144,10 +126,13 @@ class Task {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUuid(){
|
||||||
|
return $this->uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
*
|
||||||
* If description is not available attempt to summary, otherwise throw Exception
|
* If description is not available attempt to summary, otherwise throw Exception
|
||||||
*/
|
*/
|
||||||
|
@ -155,7 +140,7 @@ public function setDescription(VTodo $component){
|
||||||
if(!isset($component->DESCRIPTION) && isset($component->SUMMARY)){
|
if(!isset($component->DESCRIPTION) && isset($component->SUMMARY)){
|
||||||
$this->description = $component->SUMMARY;
|
$this->description = $component->SUMMARY;
|
||||||
} else if(!isset($component->DESCRIPTION) && !isset($component->SUMMARY)){
|
} else if(!isset($component->DESCRIPTION) && !isset($component->SUMMARY)){
|
||||||
throw new Exception("Task must have a description or summary");
|
throw new Exception('Task must have a description or summary');
|
||||||
} else {
|
} else {
|
||||||
$this->description = $component->DESCRIPTION;
|
$this->description = $component->DESCRIPTION;
|
||||||
}
|
}
|
||||||
|
@ -247,6 +232,11 @@ public function setStatus(VTodo $document){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRecurrence(){
|
||||||
|
return $this->recur;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function setRecurrence(VTodo $document){
|
public function setRecurrence(VTodo $document){
|
||||||
if(isset($document->RRULE)){
|
if(isset($document->RRULE)){
|
||||||
$this->recur = $document->RRULE;
|
$this->recur = $document->RRULE;
|
||||||
|
|
|
@ -7,9 +7,6 @@ use Aerex\TaskwarriorPlugin\Config;
|
||||||
|
|
||||||
class Taskwarrior {
|
class Taskwarrior {
|
||||||
|
|
||||||
const EXPORT = 'export';
|
|
||||||
const IMPORT = 'import';
|
|
||||||
const ADD = 'add';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TaskwarriorConfig
|
* @var TaskwarriorConfig
|
||||||
|
@ -26,6 +23,7 @@ class Taskwarrior {
|
||||||
*/
|
*/
|
||||||
private $taskrc;
|
private $taskrc;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +34,11 @@ class Taskwarrior {
|
||||||
*/
|
*/
|
||||||
private $rcOptions;
|
private $rcOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var IStrategy
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $strategy;
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
@ -58,9 +61,14 @@ class Taskwarrior {
|
||||||
|
|
||||||
|
|
||||||
public function add($task){
|
public function add($task){
|
||||||
$this->strategy($task);
|
$this->strategy->add($task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function count($uuid){
|
||||||
|
return $this->strategy->cound($uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,11 @@ use Sabre\VObject\Component\VTodo;
|
||||||
|
|
||||||
class TaskwarriorManager {
|
class TaskwarriorManager {
|
||||||
|
|
||||||
const DESCRIPTION = 'description';
|
|
||||||
const CATEGORIES = 'categories';
|
|
||||||
const TASK_UUID = 'uuid';
|
|
||||||
const ICAL_UID = 'uid';
|
|
||||||
|
|
||||||
private $tasks;
|
/**
|
||||||
|
* @var TodoStrategy
|
||||||
const ENTRY = 'entry';
|
*/
|
||||||
const START = 'start';
|
private $todoStrategy;
|
||||||
const MODIFIED = 'modified';
|
|
||||||
const END = 'end';
|
|
||||||
|
|
||||||
public function __construct($taskwarrior){
|
public function __construct($taskwarrior){
|
||||||
if(!isset($taskwarrior)){
|
if(!isset($taskwarrior)){
|
||||||
|
@ -26,29 +20,19 @@ class TaskwarriorManager {
|
||||||
} else {
|
} else {
|
||||||
$this->taskwarrior = $taskwarrior;
|
$this->taskwarrior = $taskwarrior;
|
||||||
}
|
}
|
||||||
|
// Initialize strategies
|
||||||
|
$this->todoStrategy = new TodoStrategy($this->taskwarrior->getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createTask($UUID){
|
|
||||||
$task = new Task();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function export(VTodo $document){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addTask(VTodo $document){
|
public function addTask(VTodo $document){
|
||||||
|
$this->taskwarrior->setStrategy($this->todoStrategy);
|
||||||
|
|
||||||
$task = $this->taskwarrior->createTask((string)$document->UID);
|
$task = $this->taskwarrior->createTask((string)$document->UID);
|
||||||
|
|
||||||
$task->setDescription($document);
|
$task->setDescription($document);
|
||||||
|
|
||||||
$task->setEntry($document);
|
$task->setEntryTime($document);
|
||||||
|
|
||||||
$task->setStartTime($document);
|
|
||||||
|
|
||||||
$task->setModifiedTime($document);
|
|
||||||
|
|
||||||
$task->setStopTime($document);
|
|
||||||
|
|
||||||
$task->setDue($document);
|
$task->setDue($document);
|
||||||
|
|
||||||
|
@ -89,73 +73,11 @@ class TaskwarriorManager {
|
||||||
return $upatedTask;
|
return $upatedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setEntryTime($entry){
|
|
||||||
}
|
|
||||||
|
|
||||||
function exists($UUID){}
|
|
||||||
|
|
||||||
function setEndTime($end){}
|
|
||||||
function setModifiedTime($modifiedTime){}
|
|
||||||
function setSummary($description){
|
|
||||||
if(!isset($description)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->taskWarriorJSON[self::DESCRIPTION] = $description;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStartTime($startTime){}
|
|
||||||
function setCategories($categories){
|
|
||||||
if(!isset($categories)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!is_array($catergories)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->taskWarriorJSON[self::CATEGORIES] = $categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function taskExists($taskUuid){
|
public function taskExists($taskUuid){
|
||||||
$taskIsInCache = isset($this->cachedTasks[$taskUuid]);
|
$this->taskwarrior->setStrategy($this->$todoStrategy);
|
||||||
|
return $this->taskwarrior->count((string)$taskUuid);
|
||||||
if($taskIsInCache){
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$jsonArray = $this->taskwarrior->export($taskUuid);
|
|
||||||
$taskWithUuidExists = count($jsonArray) > 0;
|
|
||||||
|
|
||||||
return $taskWithUuidExists;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save(){
|
|
||||||
|
|
||||||
}
|
|
||||||
public function build(){
|
|
||||||
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param Task $task
|
|
||||||
* @param string $attr
|
|
||||||
* @param mixed $value
|
|
||||||
*/
|
|
||||||
public function setValue(Task $task, $attr, $value)
|
|
||||||
{
|
|
||||||
$refClass = new \ReflectionClass(Task::class);
|
|
||||||
$refProp = $refClass->getProperty($attr);
|
|
||||||
$refProp->setAccessible(true);
|
|
||||||
$refProp->setValue($task, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function setDescription($description){}
|
|
||||||
function parseiCalDateTime($iCalDateTime){}
|
|
||||||
function convertToStringArray($categories){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Reference in New Issue