コード例 #1
0
 public function serviceDocument()
 {
     $service = new KT_cmis_atom_serviceDoc(KT_APP_BASE_URI);
     foreach ($this->services as $workspace => $collection) {
         //Creating the Default Workspace for use with standard atomPub Clients
         $ws = $service->newWorkspace();
         $hadDetail = false;
         if (isset($this->workspaceDetail[$workspace])) {
             if (is_array($this->workspaceDetail[$workspace])) {
                 foreach ($this->workspaceDetail[$workspace] as $wsTag => $wsValue) {
                     $ws->appendChild($service->newElement($wsTag, $wsValue));
                     $hadDetail = true;
                 }
             }
         }
         if (!$hadDetail) {
             $ws->appendChild($service->newElement('atom:title', $workspace));
         }
         $ws->appendChild($service->newAttr('cmis:repositoryRelationship', $this->repositoryInfo['repositoryRelationship']));
         // repository information
         $element = $service->newElement('cmis:repositoryInfo');
         foreach ($this->repositoryInfo as $key => $repoData) {
             if ($key == 'rootFolderId') {
                 $repoData = CMIS_APP_BASE_URI . $workspace . '/folder/' . rawurlencode($repoData);
             }
             if (!is_array($repoData)) {
                 $element->appendChild($service->newElement('cmis:' . $key, $repoData));
             } else {
                 $elementSub = $service->newElement('cmis:' . $key);
                 foreach ($repoData as $key2 => $data) {
                     $elementSub->appendChild($service->newElement('cmis:' . $key2, CMISUtil::boolToString($data)));
                 }
                 $element->appendChild($elementSub);
             }
         }
         $ws->appendChild($element);
         foreach ($collection as $serviceName => $serviceInstance) {
             foreach ($serviceInstance as $instance) {
                 $collectionStr = CMIS_APP_BASE_URI . $workspace . '/' . $serviceName . '/' . (is_array($instance['parameters']) ? implode('/', $instance['parameters']) . '/' : '');
                 $col = $service->newCollection($collectionStr, $instance['title'], $instance['collectionType'], $instance['accept'], $ws);
             }
         }
     }
     $this->output = $service->getAPPdoc();
 }
コード例 #2
0
 function getObjectParents($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $filter = '')
 {
     $ancestry = array();
     $objectId = CMISUtil::decodeObjectId($objectId, $typeId);
     // TODO - what about other types?  only implementing folders and documents at the moment so ignore for now
     switch ($typeId) {
         case 'Document':
             $document = $this->ktapi->get_document_by_id($objectId);
             $parent = $document->ktapi_folder;
             $ancestry[] = $parent;
             break;
         case 'Folder':
             $folder = $this->ktapi->get_folder_by_id($objectId);
             $parent = $this->ktapi->get_folder_by_id($folder->get_parent_folder_id());
             $ancestry[] = $parent;
             break;
     }
     $ancestry = CMISUtil::createParentObjectHierarchy($ancestry, $repository->getRepositoryURI, $this->ktapi);
     return $ancestry;
 }
コード例 #3
0
ファイル: ktcmis.inc.php プロジェクト: jpbauer/knowledgetree
 /**
  * Gets the properties for the selected object
  *
  * @param string $repositoryId
  * @param string $objectId
  * @param boolean $includeAllowableActions
  * @param boolean $includeRelationships
  * @param string $returnVersion
  * @param string $filter
  * @return properties[]
  */
 public function getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships, $returnVersion = false, $filter = '')
 {
     try {
         $propertyCollection = $this->ObjectService->getProperties($repositoryId, $objectId, $includeAllowableActions, $includeRelationships);
     } catch (Exception $e) {
         return array("status_code" => 1, "message" => $e->getMessage());
     }
     $properties = CMISUtil::createObjectPropertiesEntry($propertyCollection);
     return array("status_code" => 0, "results" => $properties);
 }
コード例 #4
0
 public function setContentStream($repositoryId, $documentId, $overwriteFlag, $contentStream, $changeToken = null)
 {
     // if no document id was supplied, we are going to create the underlying physical document
     // NOTE while it might have been nice to keep this out of here, KTAPI has no method for creating a document without
     //      a physical upload, so we cannot create the document first and then add the upload as a content stream, the
     //      entire creation step needs to happen here.
     // Attempt to decode $documentId, use as is if not detected as encoded
     $tmpObjectId = $documentId;
     $tmpObjectId = CMISUtil::decodeObjectId($tmpObjectId, $tmpTypeId);
     if ($tmpTypeId != 'Unknown') {
         $documentId = $tmpObjectId;
     }
     // TODO deal with other types except documents
     // fetch type definition of supplied document
     $CMISDocument = new CMISDocumentObject($documentId, $this->ktapi);
     // if content stream is not allowed for this object type definition, throw a ConstraintViolationException
     if ($CMISDocument->getAttribute('contentStreamAllowed') == 'notAllowed') {
         // NOTE spec version 0.61c specifies both a ConstraintViolationException and a StreamNotSupportedException
         //      for this case.  Choosing to throw StreamNotSupportedException until the specification is clarified
         //      as it is a more specific exception
         throw new StreamNotSupportedException('Content Streams are not allowed for this object type');
     }
     $csFileName = $CMISDocument->getProperty('ContentStreamFilename');
     if (!empty($csFileName) && !$overwriteFlag) {
         throw new ContentAlreadyExistsException('Unable to overwrite existing content stream');
     }
     $tempfilename = CMISUtil::createTemporaryFile($contentStream);
     // update the document content from this temporary file as per usual
     // TODO Use checkin_document_with_metadata instead if metadata content submitted || update metadata separately?
     $response = $this->ktapi->checkin_document($documentId, $csFileName, 'CMIS setContentStream action', $tempfilename, false);
     if ($response['status_code'] != 0) {
         throw new StorageException('Unable to update the content stream.  ' . $response['message']);
     }
     //        else
     //        {
     //            $objectId = CMISUtil::encodeObjectId('Document', $response['results']['id']);
     //        }
     @unlink($csFile);
     // update the CMIS document object with the content stream information
     //        $CMISDocument->reload($document['result']['document_id']);
     return $CMISDocument->getProperty('ObjectId');
 }
コード例 #5
0
 /**
  * Parses a hierarchy of CMIS objects to return an array format of a subset of information
  * required for a webservice response
  *
  * Essentially a reversal of createChildObjectHierarchy and createParentObjectHierarchy,
  * though the output may well be different to what went into that function
  *
  * @param array $input // input hierarchy to decode
  * @param string $linkText // 'child' or 'parent' - indicates direction of hierarchy => descending or ascending
  * @return array $hierarchy
  */
 public static function decodeObjectHierarchy($input, $linkText)
 {
     $hierarchy = array();
     // first, run through the base array to get the initial children
     foreach ($input as $key => $entry) {
         $object = $entry['object'];
         $properties = $object->getProperties();
         $hierarchy[$key] = CMISUtil::createObjectPropertiesEntry($properties);
     }
     return $hierarchy;
 }
コード例 #6
0
 private function get($folderId)
 {
     $object = $this->ktapi->get_folder_by_id((int) $folderId);
     // error?
     if (PEAR::isError($object)) {
         // throw an exception?
         return $object;
     }
     //          static $allowedChildObjectTypeIds;
     $objectProperties = $object->get_detail();
     $this->_setPropertyInternal('ObjectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['id']));
     // prevent doubled '/' chars
     $uri = preg_replace_callback('/([^:]\\/)\\//', create_function('$matches', 'return $matches[1];'), $this->uri . '/browse.php?fFolderId=' . $objectProperties['id']);
     // TODO this url is probably incorrect...needs to be checked
     //        $this->_setPropertyInternal('Uri', $uri);
     $this->_setPropertyInternal('Uri', '');
     // TODO what is this?  Assuming it is the object type id, and not OUR document type?
     $this->_setPropertyInternal('ObjectTypeId', $this->getAttribute('typeId'));
     // Needed to distinguish type
     $this->_setPropertyInternal('BaseType', strtolower($this->getAttribute('typeId')));
     $this->_setPropertyInternal('CreatedBy', $objectProperties['created_by']);
     // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by
     $this->_setPropertyInternal('CreationDate', $objectProperties['created_date']);
     // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by
     $this->_setPropertyInternal('LastModifiedBy', $objectProperties['modified_by']);
     // TODO cannot currently retrieve via ktapi or regular folder code - add as with created by
     $this->_setPropertyInternal('LastModificationDate', $objectProperties['modified_date']);
     $this->_setPropertyInternal('ChangeToken', null);
     $this->_setPropertyInternal('Name', $objectProperties['folder_name']);
     $this->_setPropertyInternal('ParentId', $objectProperties['parent_id']);
     $this->_setPropertyInternal('AllowedChildObjectTypeIds', array('Document', 'Folder'));
     $this->_setPropertyInternal('Author', $objectProperties['created_by']);
 }
コード例 #7
0
 /**
  * Deals with folder service POST actions.
  * This includes creation/moving of both folders and documents.
  */
 public function POST_action()
 {
     $RepositoryService = new RepositoryService();
     $repositories = $RepositoryService->getRepositories();
     $repositoryId = $repositories[0]['repositoryId'];
     // set default action, objectId and typeId
     $action = 'create';
     $objectId = null;
     $typeId = null;
     $folderId = $this->params[0];
     $title = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'title');
     $summary = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'summary');
     $properties = array('name' => $title, 'summary' => $summary);
     // determine whether this is a folder or a document action
     // document action create will have a content tag <atom:content> or <content> containing base64 encoding of the document
     // move action will have an existing id supplied as a parameter - not sure how this works yet as the CMIS clients we are
     // testing don't support move functionality at this time (2009/07/23) and so we are presuming the following format:
     // /folder/<folderId>/children/<objectId>
     // also possible that there will be an existing ObjectId property, try to cater for both until we know how it really works
     // check for existing object id as parameter in url
     if (isset($this->params[2])) {
         $action = 'move';
         $objectId = $this->params[2];
     }
     $cmisObjectProperties = KT_cmis_atom_service_helper::getCmisProperties($this->parsedXMLContent['@children']['cmis:object']);
     // check for existing object id as property of submitted object data
     if (!empty($cmisObjectProperties['ObjectId'])) {
         $action = 'move';
         $objectId = $cmisObjectProperties['ObjectId'];
     }
     // TODO there may be more to do for the checking of an existing object.
     //      e.g. verifying that it does indeed exist, and throwing an exception if it does not:
     //      "If the objected property is present but not valid an exception will be thrown" (from CMIS specification)
     // NOTE this exception should be thrown in the service API code and not here.
     // determine type if object is being moved
     if (!is_null($objectId)) {
         CMISUtil::decodeObjectId($objectId, $typeId);
     }
     // now check for content stream
     $content = KT_cmis_atom_service_helper::getAtomValues($this->parsedXMLContent['@children'], 'content');
     // TODO this will possibly need to change somewhat once Relationship Objects come into play.
     if ($action == 'create' && is_null($content) || $typeId == 'Folder') {
         $type = 'folder';
     } else {
         $type = 'document';
     }
     $ObjectService = new ObjectService(KT_cmis_atom_service_helper::getKt());
     $success = false;
     $error = null;
     if ($action == 'create') {
         if ($type == 'folder') {
             $newObjectId = $ObjectService->createFolder($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId);
         } else {
             $newObjectId = $ObjectService->createDocument($repositoryId, ucwords($cmisObjectProperties['ObjectTypeId']), $properties, $folderId, $content);
         }
         // check if returned Object Id is a valid CMIS Object Id
         CMISUtil::decodeObjectId($newObjectId, $typeId);
         if ($typeId != 'Unknown') {
             $success = true;
         } else {
             $error = $newObjectId['message'];
         }
     } else {
         if ($action == 'move') {
             $response = $ObjectService->moveObject($repositoryId, $objectId, '', $folderId);
             if (!PEAR::isError($response)) {
                 $success = true;
             } else {
                 $error = $response->getMessage();
             }
             // same object as before
             $newObjectId = $objectId;
             $typeId = ucwords($type);
         }
     }
     if ($success) {
         $this->setStatus($action == 'create' ? self::STATUS_CREATED : self::STATUS_UPDATED);
         $feed = KT_cmis_atom_service_helper::getObjectFeed($this, $ObjectService, $repositoryId, $newObjectId, 'POST');
     } else {
         $feed = KT_cmis_atom_service_helper::getErrorFeed($this, self::STATUS_SERVER_ERROR, $error);
     }
     //Expose the responseFeed
     $this->responseFeed = $feed;
 }
コード例 #8
0
ファイル: testCmisApi.php プロジェクト: 5haman/knowledgetree
 function testVersioningService()
 {
     $VersioningService = new KTVersioningService($this->ktapi);
     $NavigationService = new KTNavigationService($this->ktapi);
     // set up the folder/doc tree structure with which we will be testing
     $this->createFolderDocStructure();
     $RepositoryService = new KTRepositoryService();
     $response = $RepositoryService->getRepositories();
     $this->assertEqual($response['status_code'], 0);
     $this->assertNotNull($response['results'][0]);
     //
     // we only expect one repository
     $repository = $response['results'][0];
     $repositoryId = $repository['repositoryId'];
     // test deletion of document via deleteAllVersions
     $versionSeriesId = 'D' . $this->docs[0]->get_documentid();
     $response = $VersioningService->deleteAllVersions($repositoryId, $versionSeriesId);
     $this->assertEqual($response['status_code'], 0);
     $this->assertNotNull($response['results']);
     // TODO test checkout of document
     $documentId = CMISUtil::encodeObjectId('Document', $this->docs[1]->get_documentid());
     $response = $VersioningService->checkOut($repositoryId, $documentId);
     $this->assertEqual($response['status_code'], 0);
     $this->assertNotNull($response['results']);
     ////        // use this id for cancel checkout and checkin, not the original document id
     ////        $pwcId = $response['results'];
     $pwcId = CMISUtil::encodeObjectId(DOCUMENT, $this->docs[1]->get_documentid());
     // try again, this time it should fail - not working at the moment as ktapi registers the same user for download
     // even if already checked out, so no error is generated unless a different user attempts to do a checkout
     /*
     $response = $VersioningService->checkOut($repositoryId, $documentId);
     $this->assertEqual($response['status_code'], 1);
     $this->assertNotNull($response['message']);
     */
     // test cancel checkout
     //        echo "WITH: $pwcId<BR>";
     $response = $VersioningService->cancelCheckOut($repositoryId, $pwcId);
     $this->assertEqual($response['status_code'], 0);
     $this->assertNotNull($response['results']);
     // test cancel checkout of document no longer checked out
     $response = $VersioningService->cancelCheckOut($repositoryId, $pwcId);
     $this->assertEqual($response['status_code'], 1);
     $this->assertNotNull($response['message']);
     // test listing of checked out documents
     // first check out the document again :)
     $response = $VersioningService->checkOut($repositoryId, $documentId);
     // now check that it appears in the listing
     $response = $NavigationService->getCheckedOutDocs($repositoryId, false, false);
     $this->assertEqual($response['status_code'], 0);
     $this->assertNotNull($response['results']);
     $this->assertTrue($this->findInPropertiesArray('ObjectId', $documentId, $response['results']));
     // now let's cancel the checkout so that we can delete later during cleanup :)
     $response = $VersioningService->cancelCheckOut($repositoryId, $pwcId);
     // TODO test checkin
     // TODO add testing of failure conditions - e.g. checked out/immutable document (for all appropriate functions)
     // tear down the folder/doc tree structure with which we were testing
     $this->cleanupFolderDocStructure();
 }
コード例 #9
0
 private function get($documentId)
 {
     $object = $this->ktapi->get_document_by_id((int) $documentId);
     // document does not exist?
     if (PEAR::isError($object)) {
         throw new ObjectNotFoundException('The document you are trying to access does not exist or is inaccessible');
     }
     $objectProperties = $object->get_detail();
     $this->_setPropertyInternal('ObjectId', CMISUtil::encodeObjectId($this->typeId, $objectProperties['document_id']));
     // prevent doubled '/' chars
     $uri = preg_replace_callback('/([^:]\\/)\\//', create_function('$matches', 'return $matches[1];'), $this->uri . 'action.php?kt_path_info=ktnetwork.inlineview.actions.view&fDocumentId=' . $objectProperties['document_id']);
     // NOTE what about instead creating a downloadable version with appropriate link?  see ktapi::download_document
     //      also ktapidocument::get_download_url
     //        $this->_setPropertyInternal('Uri', $uri);
     $this->_setPropertyInternal('Uri', '');
     // TODO what is this?  Assuming it is the object type id, and not OUR document type?
     $this->_setPropertyInternal('ObjectTypeId', $this->getAttribute('typeId'));
     // Needed to distinguish type
     $this->_setPropertyInternal('BaseType', strtolower($this->getAttribute('typeId')));
     $this->_setPropertyInternal('CreatedBy', $objectProperties['created_by']);
     $this->_setPropertyInternal('CreationDate', $objectProperties['created_date']);
     $this->_setPropertyInternal('LastModifiedBy', $objectProperties['modified_by']);
     $this->_setPropertyInternal('LastModificationDate', $objectProperties['modified_date']);
     $this->_setPropertyInternal('ChangeToken', null);
     $this->_setPropertyInternal('Name', $objectProperties['title']);
     $this->_setPropertyInternal('ParentId', $objectProperties['folder_id']);
     $this->_setPropertyInternal('IsImmutable', $objectProperties['is_immutable']);
     // NOTE if access to older versions is allowed, this will need to be checked, else just set to yes
     //      see ktapi::get_document_version_history
     // NOTE see ktapi::is_latest_version
     $this->_setPropertyInternal('IsLatestVersion', true);
     $this->_setPropertyInternal('IsMajorVersion', strstr($objectProperties['version'], '.') ? false : true);
     // NOTE if access to older versions is allowed, this will need to be checked, else just set to yes
     //      see ktapi::get_document_version_history
     // NOTE see ktapi::is_latest_version
     $this->_setPropertyInternal('IsLatestMajorVersion', true);
     $this->_setPropertyInternal('VersionLabel', $objectProperties['version']);
     // VersionSeriesId should be the id of the latest version
     // NOTE this may change in the future but is easiest for the current implementation
     $this->_setPropertyInternal('VersionSeriesId', $objectProperties['version']);
     if ($objectProperties['checked_out_by'] != 'n/a') {
         $checkedOut = true;
         $checkedOutBy = $objectProperties['checked_out_by'];
         // TODO this is not what it will actually be, just a convenient placeholder
         $checkedOutId = $objectProperties['version'];
     } else {
         $checkedOut = false;
         $checkedOutBy = null;
         $checkedOutId = null;
     }
     $this->_setPropertyInternal('IsVersionSeriesCheckedOut', $checkedOut);
     $this->_setPropertyInternal('VersionSeriesCheckedOutBy', $checkedOutBy);
     // TODO presumably this is the ID of the Private Working Copy created on checkout?
     //      will find out more when we do checkout/checkin
     $this->_setPropertyInternal('VersionSeriesCheckedOutId', $checkedOutId);
     // TODO currently not returned by KnowledgeTree?
     $this->_setPropertyInternal('CheckinComment', null);
     $this->_setPropertyInternal('ContentStreamLength', $objectProperties['filesize']);
     $this->_setPropertyInternal('ContentStreamMimeType', $objectProperties['mime_type']);
     $this->_setPropertyInternal('ContentStreamFilename', $objectProperties['filename']);
     $this->_setPropertyInternal('ContentStreamUri', $this->getProperty('ObjectId') . '/' . $objectProperties['filename']);
     $this->_setPropertyInternal('Author', $objectProperties['created_by']);
 }
コード例 #10
0
 public function checkIn($repositoryId, $documentId, $major, $contentStream = null, $changeToken = '', $properties = array(), $checkinComment = '')
 {
     $documentId = CMISUtil::decodeObjectId($documentId, $typeId);
     // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
     try {
         $pwc = new CMISDocumentObject($documentId, $this->ktapi);
     } catch (exception $e) {
         throw new UpdateConflictException($e->getMessage());
     }
     // throw exception if the object is not versionable
     if (!$pwc->getAttribute('versionable')) {
         throw new ConstraintViolationException('This document is not versionable and may not be checked in');
     }
     $RepositoryService = new CMISRepositoryService();
     try {
         $typeDefinition = $RepositoryService->getTypeDefinition($repositoryId, $typeId);
     } catch (exception $e) {
         // if we can't get the type definition, then we can't store the content
         throw new StorageException($e->getMessage());
     }
     if ($typeDefinition['attributes']['contentStreamAllowed'] == 'notAllowed' && !empty($contentStream)) {
         throw new StreamNotSupportedException('Content Streams are not supported');
     }
     // check that this is the latest version
     if ($pwc->getProperty('IsLatestVersion') != true) {
         throw new VersioningException('The document is not the latest version and cannot be checked in');
     }
     // now do the checkin
     $tempfilename = CMISUtil::createTemporaryFile($contentStream);
     $response = $this->ktapi->checkin_document($documentId, $pwc->getProperty('ContentStreamFilename'), $reason, $tempfilename, $major, $sig_username, $sig_password);
     // if there was any error in cancelling the checkout
     if ($response['status_code'] == 1) {
         throw new RuntimeException('There was an error checking in the document: ' . $response['message']);
     }
     return CMISUtil::encodeObjectId(DOCUMENT, $documentId);
 }
コード例 #11
0
 /**
  * Returns a list of checked out documents from the selected repository
  *
  * @param string $repositoryId
  * @param string $folderId The folder for which checked out docs are requested
  * @param string $filter
  * @param boolean $includeAllowableActions
  * @param boolean $includeRelationships
  * @param int $maxItems
  * @param int $skipCount
  * @return array $checkedout The collection of checked out documents
  */
 function getCheckedOutDocs($repositoryId, $includeAllowableActions, $includeRelationships, $folderId = null, $filter = '', $maxItems = 0, $skipCount = 0)
 {
     $checkedout = $this->NavigationService->getCheckedOutDocs($repositoryId, $includeAllowableActions, $includeRelationships, $folderId, $filter, $maxItems, $skipCount);
     if (PEAR::isError($checkedout)) {
         return array("status_code" => 1, "message" => "Failed getting list of checked out documents");
     }
     // convert to array format for external code
     $co = array();
     foreach ($checkedout as $documentProperties) {
         $co[] = CMISUtil::createObjectPropertiesEntry($documentProperties);
     }
     return array("status_code" => 0, "results" => $co);
 }
コード例 #12
0
 public static function getFolderId($path, &$ktapi)
 {
     // lose first item
     array_shift($path);
     $numQ = count($path);
     $numFolders = $numQ;
     $folderId = 1;
     $start = 0;
     while ($start < $numFolders) {
         $name = $path[$numQ - $numFolders + $start];
         // fix for possible url encoding issue
         $name = str_replace('%2520', '%20', $name);
         $folderName = urldecode($name);
         $folder = $ktapi->get_folder_by_name($folderName, $folderId);
         $folderId = $folder->get_folderid();
         ++$start;
     }
     return CMISUtil::encodeObjectId('Folder', $folderId);
 }
コード例 #13
0
 /**
  * Fetches information about the selected repository
  *
  * @param string $repositoryId
  */
 public function getRepositoryInfo($repositoryId)
 {
     $repositoryInfo = $this->RepositoryService->getRepositoryInfo($repositoryId);
     if (PEAR::isError($repositoryInfo)) {
         return array("status_code" => 1, "message" => "Failed getting repository information");
     }
     // TODO output this manually, the function works but only for some objects so rather avoid it completely?
     // NOTE the problems appear to be due to recursive objects
     return array("status_code" => 0, "results" => CMISUtil::objectToArray($repositoryInfo));
 }
コード例 #14
0
 public function checkIn($repositoryId, $documentId, $major, $changeToken = '', $properties = array(), $contentStream = null, $checkinComment = '')
 {
     $documentId = CMISUtil::decodeObjectId($documentId, $typeId);
     // throw updateConflictException if the operation is attempting to update an object that is no longer current (as determined by the repository).
     try {
         $pwc = new CMISDocumentObject($documentId, $this->ktapi);
     } catch (exception $e) {
         throw new UpdateConflictException($e->getMessage());
     }
     // throw exception if the object is not versionable
     if (!$pwc->getAttribute('versionable')) {
         throw new ConstraintViolationException('This document is not versionable and may not be checked in');
     }
     return $documentId;
 }