public function createDocument($repositoryId, $typeId, $properties, $folderId = null, $contentStream = null, $versioningState = null) { $objectId = null; // fetch type definition of supplied type and check for base type "document", if not true throw exception $RepositoryService = new CMISRepositoryService(); try { $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId); } catch (Exception $e) { throw new ConstraintViolationException('Object is not of base type document. ' . $e->getMessage()); } if ($typeDefinition['attributes']['baseType'] != 'document') { throw new ConstraintViolationException('Object is not of base type document'); } // if no $folderId submitted and repository does not support "unfiling" throw exception if (empty($folderId)) { $repositoryInfo = $RepositoryService->getRepositoryInfo($repositoryId); $capabilities = $repositoryInfo->getCapabilities(); if (!$capabilities->hasCapabilityUnfiling()) { throw new ConstraintViolationException('Repository does not support the Unfiling capability and no folder id was supplied'); } } // Attempt to decode $folderId, use as is if not detected as encoded $tmpObjectId = $folderId; $tmpObjectId = CMISUtil::decodeObjectId($tmpObjectId, $tmpTypeId); if ($tmpTypeId != 'Unknown') { $folderId = $tmpObjectId; } // if parent folder is not allowed to hold this type, throw exception $CMISFolder = new CMISFolderObject($folderId, $this->ktapi); $allowed = $CMISFolder->getProperty('AllowedChildObjectTypeIds'); $typeAllowed = false; if (is_array($allowed)) { foreach ($allowed as $type) { if (strtolower($type) == strtolower($typeId)) { $typeAllowed = true; break; } } } if (!$typeAllowed) { throw new ConstraintViolationException('Parent folder may not hold objects of this type (' . $typeId . ')'); } // if content stream is required and no content stream is supplied, throw a ConstraintViolationException if ($typeDefinition['attributes']['contentStreamAllowed'] == 'required' && is_null($contentStream)) { throw new ConstraintViolationException('This repository requires a content stream for document creation. ' . 'Refusing to create an empty document'); } else { if ($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed' && !empty($contentStream)) { throw new StreamNotSupportedException('Content Streams are not supported'); } } // if versionable attribute is set to false and versioningState is supplied, throw a ConstraintViolationException if (!$typeDefinition['attributes']['versionable'] && !empty($versioningState)) { throw new ConstraintViolationException('This repository does not support versioning'); } // TODO deal with $versioningState when supplied // set title and name identical if only one submitted if ($properties['title'] == '') { $properties['title'] = $properties['name']; } else { if ($properties['name'] == '') { $properties['name'] = $properties['title']; } } // if name is blank throw exception (check type) - using invalidArgument Exception for now if (trim($properties['name']) == '') { throw new InvalidArgumentException('Refusing to create an un-named document'); } // TODO also set to Default if a non-supported type is submitted if ($properties['type'] == '') { $properties['type'] = 'Default'; } // create the content stream from the supplied data // NOTE since the repository is set to require a content stream and we don't currently have another way to get the document data // this check isn't strictly necessary; however it is needed for a repository which does not support content streams if (!is_null($contentStream)) { // TODO consider checking whether content is encoded (currently we expect encoded) // TODO choose between this and the alternative decode function (see CMISUtil class) // this will require some basic benchmarking $contentStream = CMISUtil::decodeChunkedContentStream($contentStream); // NOTE There is a function in CMISUtil to do this, written for the unit tests but since KTUploadManager exists // and has more functionality which could come in useful at some point I decided to go with that instead // (did not know this existed when I wrote the CMISUtil function) $uploadManager = new KTUploadManager(); // assumes already decoded from base64, should use store_base64_file if not $tempfilename = $uploadManager->store_file($contentStream, 'cmis_'); // metadata $metadata = array(); $metaFields = array(); $sysdata = array(); if (!empty($properties['summary'])) { $metadata[] = array('fieldset' => 'Tag Cloud', 'fields' => array(array('name' => 'Tag', 'value' => $properties['summary']))); } $user = $this->ktapi->get_user(); if (!PEAR::isError($user)) { $metaFields['General Information'][] = array('name' => 'Document Author', 'value' => $user->getName()); } if (!empty($properties['category'])) { $category = $properties['category']; } else { $category = 'Miscellaneous'; } $metaFields['General Information'][] = array('name' => 'Category', 'value' => $category); /** * Try to determine mime type which maps to one of the following KnowledgetTree document types: * * Audio * Image * Text * Video * * example mime types: * * text/plain * image/gif * application/x-dosexec * application/pdf * application/msword * audio/mpeg * application/octet-stream * application/zip */ // TODO check extension for types which are not obvious? e.g. wmv video returns application/octet-stream $mediatype = null; include_once KT_LIB_DIR . '/mime.inc.php'; $KTMime = new KTMime(); $mimetype = $KTMime->getMimeTypeFromFile($tempfilename); preg_match('/^([^\\/]*)\\/([^\\/]*)/', $mimetype, $matches); if ($matches[1] == 'text' || $matches[1] == 'image' || $matches[1] == 'audio') { $mediatype = ucwords($matches[1]); } else { if ($matches[2] == 'pdf' || $matches[2] == 'msword') { $mediatype = 'Text'; } } if (!is_null($mediatype)) { $metaFields['General Information'][] = array('name' => 'Media Type', 'value' => $mediatype); } if (count($metaFields['General Information']) > 0) { foreach ($metaFields['General Information'] as $field) { $fields[] = $field; } $metadata[] = array('fieldset' => 'General Information', 'fields' => $fields); } $response = $this->ktapi->add_document_with_metadata((int) $folderId, $properties['title'], $properties['name'], $properties['type'], $tempfilename, $metadata, $sysdata); if ($response['status_code'] != 0) { throw new StorageException('The repository was unable to create the document. ' . $response['message']); } else { $objectId = CMISUtil::encodeObjectId('Document', $response['results']['document_id']); } // remove temporary file @unlink($tempfilename); } else { // TODO creation of document without content. leaving this for now as we require content streams and any code // here will therefore never be executed; if we implement some form of template based document creation // then we may have something else to do here; // for now we just throw a general RuntimeException, since we should not // actually reach this code unless something is wrong; this may be removed or replaced later throw new RuntimeException('Cannot create document without a content stream'); } return $objectId; }