/** * Use this method to create a new collection * * @param string $uri The new uri * @param MkCol $mkCol * @return array|null */ function createCollection($uri, MkCol $mkCol) { list($parentUri, $newName) = URLUtil::splitPath($uri); // Making sure the parent exists try { $parent = $this->tree->getNodeForPath($parentUri); } catch (Exception\NotFound $e) { throw new Exception\Conflict('Parent node does not exist'); } // Making sure the parent is a collection if (!$parent instanceof ICollection) { throw new Exception\Conflict('Parent node is not a collection'); } // Making sure the child does not already exist try { $parent->getChild($newName); // If we got here.. it means there's already a node on that url, and we need to throw a 405 throw new Exception\MethodNotAllowed('The resource you tried to create already exists'); } catch (Exception\NotFound $e) { // NotFound is the expected behavior. } if (!$this->emit('beforeBind', [$uri])) { return; } if ($parent instanceof IExtendedCollection) { /** * If the parent is an instance of IExtendedCollection, it means that * we can pass the MkCol object directly as it may be able to store * properties immediately. */ $parent->createExtendedCollection($newName, $mkCol); } else { /** * If the parent is a standard ICollection, it means only * 'standard' collections can be created, so we should fail any * MKCOL operation that carries extra resourcetypes. */ if (count($mkCol->getResourceType()) > 1) { throw new Exception\InvalidResourceType('The {DAV:}resourcetype you specified is not supported here.'); } $parent->createDirectory($newName); } // If there are any properties that have not been handled/stored, // we ask the 'propPatch' event to handle them. This will allow for // example the propertyStorage system to store properties upon MKCOL. if ($mkCol->getRemainingMutations()) { $this->emit('propPatch', [$uri, $mkCol]); } $success = $mkCol->commit(); if (!$success) { $result = $mkCol->getResult(); // generateMkCol needs the href key to exist. $result['href'] = $uri; return $result; } $this->tree->markDirty($parentUri); $this->emit('afterBind', [$uri]); }
/** * Use this method to create a new collection * * The {DAV:}resourcetype is specified using the resourceType array. * At the very least it must contain {DAV:}collection. * * The properties array can contain a list of additional properties. * * @param string $uri The new uri * @param array $resourceType The resourceType(s) * @param array $properties A list of properties * @return array|null */ function createCollection($uri, array $resourceType, array $properties) { list($parentUri, $newName) = URLUtil::splitPath($uri); // Making sure {DAV:}collection was specified as resourceType if (!in_array('{DAV:}collection', $resourceType)) { throw new Exception\InvalidResourceType('The resourceType for this collection must at least include {DAV:}collection'); } // Making sure the parent exists try { $parent = $this->tree->getNodeForPath($parentUri); } catch (Exception\NotFound $e) { throw new Exception\Conflict('Parent node does not exist'); } // Making sure the parent is a collection if (!$parent instanceof ICollection) { throw new Exception\Conflict('Parent node is not a collection'); } // Making sure the child does not already exist try { $parent->getChild($newName); // If we got here.. it means there's already a node on that url, and we need to throw a 405 throw new Exception\MethodNotAllowed('The resource you tried to create already exists'); } catch (Exception\NotFound $e) { // This is correct } if (!$this->emit('beforeBind', [$uri])) { return; } // There are 2 modes of operation. The standard collection // creates the directory, and then updates properties // the extended collection can create it directly. if ($parent instanceof IExtendedCollection) { $parent->createExtendedCollection($newName, $resourceType, $properties); } else { // No special resourcetypes are supported if (count($resourceType) > 1) { throw new Exception\InvalidResourceType('The {DAV:}resourcetype you specified is not supported here.'); } $parent->createDirectory($newName); $rollBack = false; $exception = null; $errorResult = null; if (count($properties) > 0) { try { $errorResult = $this->updateProperties($uri, $properties); if (!isset($errorResult[200])) { $rollBack = true; } } catch (Exception $e) { $rollBack = true; $exception = $e; } } if ($rollBack) { if (!$this->emit('beforeUnbind', [$uri])) { return; } $this->tree->delete($uri); // Re-throwing exception if ($exception) { throw $exception; } // Re-arranging the result so it makes sense for // generateMultiStatus. $newResult = ['href' => $uri]; foreach ($errorResult as $property => $code) { if (!isset($newResult[$code])) { $newResult[$code] = [$property => null]; } else { $newResult[$code][$property] = null; } } return $newResult; } } $this->tree->markDirty($parentUri); $this->emit('afterBind', [$uri]); }