config->vision != 'lite') { $templateButton = html::a(helper::createLink('doc', 'create', "objectType=$objectType&objectID=$objectID&libID=$libID&moduleID=0&type=html&fromGlobal=&from=template"), '' . $this->lang->doc->createByTemplate, '', "class='btn btn-secondary' data-app={$this->app->tab}"); return $templateButton . $button; } return $button; } /** * Assign a doc. * * @param int $docID * @access public * @return array|bool */ public function assign($docID) { $oldDoc = $this->getByID($docID); $now = helper::now(); $doc = fixer::input('post') ->add('editedBy', $this->app->user->account) ->add('editedDate', $now) ->add('assignedDate', $now) ->stripTags($this->config->doc->editor->assignto['id'], $this->config->allowedTags) ->remove('uid,comment,files,label') ->get(); $this->dao->update(TABLE_DOC)->data($doc)->autoCheck()->where('id')->eq((int)$docID)->exec(); if(!dao::isError()) return common::createChanges($oldDoc, $doc); return false; } /** * Get doc list. * * @param int|array|string $docList * @access public * @return array */ public function getByList($docList = 0) { return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq(0) ->beginIF($docList)->andWhere('id')->in($docList)->fi() ->fetchAll('id'); } /** * Get node list. * * @param int $bookID * @access public * @return array */ public function getNodeList($bookID) { $stmt = $this->dbh->query($this->dao->select('id, lib, type, chapterType, template, path, `order`, parent, grade, title')->from(TABLE_DOC)->where('template')->eq($bookID)->andWhere('deleted')->eq(0)->orderBy('grade_desc,`order`, id')->get()); $parent = array(); while($node = $stmt->fetch()) { if(!isset($parent)) $parent = array(); if(isset($parent[$node->id])) { $node->children = $parent[$node->id]->children; unset($parent[$node->id]); } if(!isset($parent[$node->parent])) $parent[$node->parent] = new stdclass(); $parent[$node->parent]->children[] = $node; } $nodeList = array(); foreach($parent as $node) { foreach($node->children as $children) { if($children->parent != 0 && !empty($nodeList)) { foreach($nodeList as $firstChildren) { if($firstChildren->id == $children->parent) $firstChildren->children[] = $children; } } $nodeList[] = $children; } } return $nodeList; } /** * Sync book. * * @param int $templateID * @param int $docID * @param string $templateType * @access public * @return void */ public function syncBook($templateID, $docID, $templateType) { $doc = $this->getByID($docID); $catalogs = $this->dao->select('*')->from(TABLE_DOC)->where('template')->eq($templateID)->andWhere('deleted')->eq(0)->fetchAll(); $pairs = array(); $pairs[$templateID] = $docID; foreach($catalogs as $catalog) { $oldID = $catalog->id; $catalog->template = $docID; unset($catalog->id); $this->dao->insert(TABLE_DOC)->data($catalog)->exec(); $newID = $this->dao->lastInsertID(); $this->dao->update(TABLE_DOC)->set('path')->eq(",$newID,")->where('id')->eq($newID)->exec(); $pairs[$oldID] = $newID; $content = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($oldID)->fetch(); unset($content->id); $content->doc = $newID; $this->dao->insert(TABLE_DOCCONTENT)->data($content)->exec(); } foreach($pairs as $oldID => $newID) $this->dao->update(TABLE_DOC)->set('parent')->eq($newID)->where('parent')->eq($oldID)->andWhere('template')->eq($docID)->exec(); /* Compute path and parent. */ $newCatalog = $this->dao->select('*')->from(TABLE_DOC) ->where('template')->eq($docID) ->andWhere('grade')->ge(1) ->fetchAll(); foreach($newCatalog as $catalog) $this->computePath($catalog->id, $catalog->parent, $catalog->path, TABLE_DOC, $catalog->grade); } /** * Sync doc module. * * @param int $docLibID * @access public * @return void */ public function syncDocModule($docLibID) { $catalog = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq(0) ->andWhere('type')->eq('doc') ->orderBy('grade_asc') ->fetchAll(); /* Cpoy module and mark new id. */ $pairs = array(); foreach($catalog as $module) { $oldID = $module->id; $module->root = $docLibID; unset($module->id); unset($module->path); $this->dao->insert(TABLE_MODULE)->data($module)->exec(); $newID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",$newID,")->where('id')->eq($newID)->exec(); $pairs[$oldID] = $newID; } foreach($pairs as $oldID => $newID) $this->dao->update(TABLE_MODULE)->set('parent')->eq($newID)->where('parent')->eq($oldID)->andWhere('id')->in(array_values($pairs))->exec(); /* Compute path and parent. */ $newCatalog = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq($docLibID) ->andWhere('type')->eq('doc') ->andWhere('parent')->ne(0) ->fetchAll(); foreach($newCatalog as $module) $this->computePath($module->id, $module->parent, $module->path, TABLE_MODULE, $module->grade); } /** * Compute path. * * @param int $moduleID * @param int $parentID * @param string $path * @param string $table * @param int $grade * @access public * @return void */ public function computePath($moduleID, $parentID, $path = '', $table = TABLE_MODULE, $grade = 1) { if($grade == 1) { $this->dao->update($table)->set('path')->eq($path)->where('id')->eq($moduleID)->exec(); return true; } $parent = $this->dao->select('*')->from($table)->where('id')->eq($parentID)->fetch(); $path = ',' . $parent->id . $path; $this->computePath($moduleID, $parent->parent, $path, $table, $parent->grade); } /** * Get doc structure. * * @param int $bookID * @param string $serial * @param object $object * @access public * @return string */ public function getCmStructure($bookID, $serial, $object) { $structure = ''; $data = json_decode($object->data); if($object->category == 'SRS') { $stories = (array)$data->story; if(empty($stories)) return ''; foreach($stories as $id => $story) $story->id = $id; $storyIDList = array_column($stories, 'module'); $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq($object->product) ->andWhere('id')->in($storyIDList) ->andWhere('type')->eq('story') ->andWhere('deleted')->eq(0) ->andWhere('grade')->eq(1) ->orderBy('`order` asc') ->fetchAll(); $moduleIDList = $this->dao->select('module')->from(TABLE_STORY) ->where('product')->eq($object->product) ->andWhere('deleted')->eq(0) ->orderBy('id_desc') ->fetchPairs(); $serials = $this->computeModuleSN($object->product, $serial); $structure .= ''; $structure .= $this->getStoryStructure((array)$stories, $modules, $object, $serials, $moduleIDList); } elseif(in_array($object->category, array('HLDS', 'DDS', 'DBDS', 'ADS'))) { $designs = (array)$data->design; if(empty($designs)) return; $structure .= ''; } elseif(in_array($object->category, array('ITTC', 'STTC'))) { $stage = $object->category == 'STTC' ? 'system' : 'intergrate'; $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq($object->product) ->andWhere('grade')->eq(1) ->andWhere('type')->in('story,case') ->andWhere('deleted')->eq(0) ->orderBy('`order` asc') ->fetchAll(); $cases = (array)$data->case; if(empty($cases)) return; $structure .= ''; $structure .= $this->getCaseStructure($modules, $cases, $moduleIDList); } return $structure; } /** * Get story structure. * * @param array $stories * @param object $modules * @param object $book * @param string $serials * @param array $moduleIDList * @access public * @return string */ public function getStoryStructure($stories, $modules, $book, $serials, $moduleIDList) { $html = ''; $html .= ''; return $html; } /** * Get design structure. * * @param object $book * @param string $serial * @access public * @return string */ public function getDesignStructure($book, $serial) { $designs = $this->dao->select('*')->from(TABLE_DESIGN) ->where('deleted')->eq(0) ->andWhere('product')->eq($book->product) ->andWhere('type')->eq($book->templateType) ->fetchAll('id'); $i = 1; $structure = ''; $structure .= ''; return $structure; } /** * Get case structure. * * @param object $modules * @param object $cases * @param array $moduleIDList * @access public * @return string */ public function getCaseStructure($modules, $cases, $moduleIDList) { $tree = ''; $tree .= ''; return $tree; } /** * Compute module SN. * * @param int $productID * @param string $parentSerial * @access public * @return array */ public function computeModuleSN($productID, $parentSerial) { /* Get all children of the startNode. */ $modules = $this->dao->select('id, parent, `order`, path')->from(TABLE_MODULE) ->where('root')->eq($productID) ->andWhere('deleted')->eq(0) ->andWhere('type')->eq('story') ->orderBy('grade, `order`, id') ->fetchAll('id'); $stories = $this->dao->select('id, module')->from(TABLE_STORY) ->where('product')->eq($productID) ->andWhere('type')->eq('story') ->fetchAll('id'); /* Push story to module array. */ foreach($modules as $moduleID => $module) { foreach($stories as $storyID => $story) { $array = array(); $data = new stdclass(); $key = 's' . $storyID; $data->id = $key; if($story->module == 0) { $data->parent = 0; $data->path = ',' . $key . ','; $array[$key] = $data; $modules = $array + $modules; continue; } if($story->module == $moduleID) { $data->parent = $moduleID; $data->path = $module->path . $key . ','; $array[$key] = $data; $modules = $array + $modules; } } } /* Group them by their parent. */ $groupedModules = array(); foreach($modules as $module) $groupedModules[$module->parent][$module->id] = $module; $serials = array(); foreach($modules as $module) { $path = explode(',', $module->path); $serial = ''; foreach($path as $moduleID) { if(!$moduleID) continue; /* Compute the serial. */ if(isset($modules[$moduleID])) { $parentID = $modules[$moduleID]->parent; $brothers = $groupedModules[$parentID]; $serial .= array_search($moduleID, array_keys($brothers)) + 1 . '.'; } } $serials[$module->id] = $parentSerial . '.' . rtrim($serial, '.'); } return $serials; } /** * Import doc to asset lib. * * @param int|array $docIdList * @param string $assetType * @access public * @return bool */ public function importToLib($docIdList = 0, $assetType = 'practice') { $data = fixer::input('post')->get(); if(empty($data->lib)) { $libName = $assetType == 'practice' ? $this->lang->doc->practiceLib : $this->lang->doc->componentLib; dao::$errors[] = sprintf($this->lang->error->notempty, $libName); return false; } $docs = $this->getByIdList($docIdList); $importedDocs = $this->dao->select('`from`,`fromVersion`')->from(TABLE_DOC) ->where('assetlib')->eq($data->lib) ->andWhere('`from`')->in($docIdList) ->fetchGroup('from'); if(is_numeric($docIdList) and isset($importedDocs[$docIdList])) { dao::$errors[] = $assetType == 'practice' ? $this->lang->doc->isExistPracticeLib : $this->lang->doc->isExistComponentLib; return false; } /* Remove duplicate doc and save file id list. */ $fileIDList = array(); foreach($docs as $doc) { $fileIDList = array_merge($fileIDList, explode(',', $doc->files)); if(isset($importedDocs[$doc->docID])) { foreach($importedDocs[$doc->docID] as $improtedDoc) { if($improtedDoc->fromVersion == $doc->version) unset($docs[$doc->docID]); } } } $fileIDList = array_unique($fileIDList); $files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($fileIDList)->andWhere('deleted')->eq(0)->fetchAll('id'); $now = helper::now(); $today = helper::today(); $hasApprovePiv = false; if($assetType == 'practice' and (common::hasPriv('assetlib', 'approvePractice') or common::hasPriv('assetlib', 'batchApprovePractice'))) $hasApprovePiv = true; if($assetType == 'component' and (common::hasPriv('assetlib', 'approveComponent') or common::hasPriv('assetlib', 'batchApproveComponent'))) $hasApprovePiv = true; $this->loadModel('action'); /* Create doc to asset lib. */ $now = helper::now(); $this->loadModel('action'); foreach($docs as $doc) { $assetDoc = new stdclass(); $assetDoc->title = $doc->title; $assetDoc->keywords = $doc->keywords; $assetDoc->type = $doc->docType; $assetDoc->version = 1; $assetDoc->acl = 'open'; $assetDoc->status = $hasApprovePiv ? 'active' : 'draft'; $assetDoc->assetLib = $data->lib; $assetDoc->assetLibType = $assetType; $assetDoc->from = $doc->docID; $assetDoc->fromVersion = $doc->version; $assetDoc->addedBy = $this->app->user->account; $assetDoc->addedDate = $now; if(!empty($data->assignedTo)) $assetDoc->assignedTo = $data->assignedTo; if($hasApprovePiv) { $assetDoc->assignedTo = $this->app->user->account; $assetDoc->approvedDate = $today; } $this->dao->insert(TABLE_DOC)->data($assetDoc)->exec(); $assetDocID = $this->dao->lastInsertID(); if(!dao::isError()) { /* Copy file info. */ $docFiles = explode(',', $doc->files); $newFiles = ''; foreach($docFiles as $fileID) { if(isset($files[$fileID])) { $file = $files[$fileID]; unset($file->id); $file->objectID = $assetDocID; $file->addedBy = $this->app->user->account; $file->addedDate = helper::now(); $file->downloads = 0; $this->dao->insert(TABLE_FILE)->data($file)->exec(); $copyFileID = $this->dao->lastInsertID(); $newFiles = empty($newFiles) ? $copyFileID : "$newFiles,$copyFileID"; } } $content = new stdclass(); $content->doc = $assetDocID; $content->title = $doc->title; $content->digest = $doc->digest; $content->content = $doc->content; $content->files = $newFiles; $content->type = $doc->contentType; $content->version = 1; $this->dao->insert(TABLE_DOCCONTENT)->data($content)->exec(); $action = $assetType == 'practice' ? 'import2PracticeLib' : 'import2ComponentLib'; $this->action->create('doc', $assetDocID, $action); } } return true; }