/** * Constructor * * @param object $connect * @return void */ public function __construct($connect = NULL) { if (empty($connect)) { return false; } $this->_db = \App::get('db'); $this->_connect = $connect; $this->model = $connect->model; $this->_uid = User::get('id'); $this->params = Plugin::params('projects', 'files'); $this->_logPath = \Components\Projects\Helpers\Html::getProjectRepoPath($this->model->get('alias'), 'logs', false); if (!is_dir($this->_logPath)) { Filesystem::makeDirectory($this->_logPath, 0755, true, true); } $this->_path = $this->model->repo()->get('path'); }
/** * Unlock sync and view sync log for project * * @return void */ public function fixsyncTask() { $id = Request::getVar('id', 0); $service = 'google'; // Initiate extended database class $obj = new Tables\Project($this->database); if (!$id or !$obj->loadProject($id)) { App::redirect(Route::url('index.php?option=' . $this->_option, false), Lang::txt('COM_PROJECTS_NOTICE_ID_NOT_FOUND'), 'error'); return; } // Unlock sync $obj->saveParam($id, $service . '_sync_lock', ''); // Get log file $repodir = Helpers\Html::getProjectRepoPath($obj->alias, 'logs'); $sfile = $repodir . DS . 'sync.' . Date::format('Y-m') . '.log'; if (file_exists($sfile)) { // Serve up file $server = new \Hubzero\Content\Server(); $server->filename($sfile); $server->disposition('attachment'); $server->acceptranges(false); $server->saveas('sync.' . Date::format('Y-m') . '.txt'); $result = $server->serve_attachment($sfile, 'sync.' . Date::format('Y-m') . '.txt', false); exit; } // Redirect App::redirect(Route::url('index.php?option=' . $this->_option . '&task=edit&id=' . $id, false), Lang::txt('Sync log unavailable')); }
/** * Get File Previews * * @param string $ref Reference to files * @return mixed */ protected function _getFilesPreview($ref = '') { if (!$ref) { return false; } if (!$this->_path) { // Get project file path $this->_path = \Components\Projects\Helpers\Html::getProjectRepoPath($this->model->get('alias')); } // We do need project file path if (!$this->_path || !is_dir($this->_path)) { return false; } $files = explode(',', $ref); $selected = array(); $maxHeight = 0; $minHeight = 0; $minWidth = 0; $maxWidth = 0; $imagepath = trim($this->_config->get('imagepath', '/site/projects'), DS); $to_path = DS . $imagepath . DS . strtolower($this->model->get('alias')) . DS . 'preview'; foreach ($files as $item) { $parts = explode(':', $item); $file = count($parts) > 1 ? $parts[1] : $parts[0]; $hash = count($parts) > 1 ? $parts[0] : NULL; if ($hash) { // Only preview mid-size images from now on $hashed = md5(basename($file) . '-' . $hash) . '.png'; if (is_file(PATH_APP . $to_path . DS . $hashed)) { $preview['image'] = $hashed; $preview['url'] = NULL; $preview['title'] = basename($file); // Get image properties list($width, $height, $type, $attr) = getimagesize(PATH_APP . $to_path . DS . $hashed); $preview['width'] = $width; $preview['height'] = $height; $preview['orientation'] = $width > $height ? 'horizontal' : 'vertical'; // Record min and max width and height to build image grid if ($height >= $maxHeight) { $maxHeight = $height; } if ($height && $height <= $minHeight) { $minHeight = $height; } else { $minHeight = $height; } if ($width > $maxWidth) { $maxWidth = $width; } $selected[] = $preview; } } } // No files for preview if (empty($selected)) { return false; } // Output HTML $view = new \Hubzero\Plugin\View(array('folder' => 'projects', 'element' => $this->_name, 'name' => 'preview', 'layout' => 'files')); $view->maxHeight = $maxHeight; $view->maxWidth = $maxWidth; $view->minHeight = $minHeight > 400 ? 400 : $minHeight; $view->selected = $selected; $view->option = $this->_option; $view->model = $this->model; return $view->loadTemplate(); }
/** * Save updated CSV file with headers * * @param integer $id Database ID * @return void */ public function _save_csv($id) { $db = $this->get_ds_db($this->model->get('id')); // Get project database object $objPD = new \Components\Projects\Tables\Database($this->_database); // Get project path $path = \Components\Projects\Helpers\Html::getProjectRepoPath($this->model->get('alias')); $path .= DS; if ($objPD->loadRecord($id)) { $db = $this->get_ds_db($objPD->project); $table = $objPD->database_name; $title = $objPD->title; $file = $objPD->source_file; $dir = $objPD->source_dir != '' ? $objPD->source_dir . DS : ''; $dd = json_decode($objPD->data_definition, true); $header = array(); $field_list = array(); foreach ($dd['cols'] as $field => $prop) { $field_list[] = $field; $header[0][] = $prop['label']; unset($prop['label']); unset($prop['idx']); unset($prop['styles']); $header[1][] = rtrim(ltrim(str_replace('","', "\",\r\n\"", json_encode($prop)), '{'), '}'); } $header[2] = array('DATASTART'); $path .= $dir; $fp = fopen($path . $file, 'w+'); foreach ($header as $h) { fputcsv($fp, $h); } $sql = "SELECT " . implode(', ', $field_list) . " FROM {$table}"; $db->setQuery($sql); $res = $db->query(); while ($row = $res->fetch_array(MYSQLI_NUM)) { fputcsv($fp, $row); } fclose($fp); // Commit update file $commit_message = Lang::txt('PLG_PROJECTS_DATABASES_UPDATED_FILE') . ' ' . escapeshellarg($file); $author = escapeshellarg(User::get('name') . ' <' . User::get('email') . '> '); chdir($path); exec($this->gitpath . ' add ' . escapeshellarg($file)); exec($this->gitpath . ' commit ' . escapeshellarg($file) . ' -m "' . $commit_message . '"' . ' --author="' . $author . '" 2>&1'); // Update source_revision with the current commit hash chdir($path); exec($this->gitpath . ' log --pretty=format:%H ' . escapeshellarg($file) . '|head -1', $hash); $hash = isset($hash[0]) ? $hash[0] : 0; $objPD->source_revision = $hash; $objPD->store(); $msg = Lang::txt('PLG_PROJECTS_DATABASES_UPDATED_FILE') . ' "' . $file . '"' . Lang::txt('PLG_PROJECTS_DATABASES_IN_PROJECT'); $this->model->recordActivity(str_replace("'", "\\'", $msg), $file, 'files', Route::url('index.php?option=' . $this->_option . '&alias=' . $this->model->get('alias') . '&active=files'), 'files', 1); ob_clean(); } }
/** * Optimize project repos * * @param object $job \Components\Cron\Models\Job * @return boolean */ public function gitGc(\Components\Cron\Models\Job $job) { $database = App::get('db'); $pconfig = Component::params('com_projects'); require_once PATH_CORE . DS . 'components' . DS . 'com_projects' . DS . 'tables' . DS . 'project.php'; require_once PATH_CORE . DS . 'components' . DS . 'com_projects' . DS . 'helpers' . DS . 'githelper.php'; require_once PATH_CORE . DS . 'components' . DS . 'com_projects' . DS . 'helpers' . DS . 'html.php'; // Get all projects $obj = new \Components\Projects\Tables\Project($database); $projects = $obj->getValidProjects(array(), array(), $pconfig, false, 'alias'); if (!$projects) { return true; } foreach ($projects as $project) { $path = \Components\Projects\Helpers\Html::getProjectRepoPath(strtolower($project), 'files'); // Make sure there is .git directory if (!$path || !is_dir($path . DS . '.git')) { continue; } $git = new \Components\Projects\Helpers\Git($path); $git->callGit('gc --aggressive'); } return true; }
/** * Get files stats for all projects * * @param array $aliases Project aliases for which to compute stats * @param string $get * * @return mixed */ public function getStats($aliases = array(), $get = 'total') { if (empty($aliases)) { return false; } $files = 0; $diskSpace = 0; $commits = 0; $usage = 0; // Publication space if ($get == 'pubspace') { // Load publications component configs $pubconfig = Component::params('com_publications'); $base_path = DS . trim($pubconfig->get('webpath'), DS); chdir(PATH_APP . $base_path); exec('du -sk ', $out); $used = 0; if ($out && isset($out[0])) { $kb = str_replace('.', '', trim($out[0])); $used = $kb * 1024; } return $used; } // Compute size of local project repos foreach ($aliases as $alias) { $path = Helpers\Html::getProjectRepoPath($alias, 'files', false); // Make sure there is .git directory if (!is_dir($path) || !is_dir($path . DS . '.git')) { continue; } if ($get == 'diskspace') { $diskSpace = $diskSpace + $this->call('getDiskUsage', $params = array('path' => $path, 'working' => true, 'git' => true)); } else { $git = new Helpers\Git($path); if ($get == 'commitCount') { $nf = $git->callGit('ls-files --full-name '); if ($nf && substr($nf[0], 0, 5) != 'fatal') { $out = $git->callGit('log | grep "^commit" | wc -l'); if (is_array($out)) { $c = end($out); $commits = $commits + $c; } } } else { $count = count($git->getFiles()); $files = $files + $count; if ($count > 1) { $usage++; } } } } // Output switch ($get) { case 'total': return $files; break; case 'usage': return $usage; break; case 'diskspace': return $diskSpace; break; case 'commitCount': return $commits; break; } }
/** * Activate provisioned project * * @return void */ public function activateTask() { // Cannot proceed without project id/alias if (!$this->model->exists()) { throw new Exception(Lang::txt('COM_PROJECTS_PROJECT_NOT_FOUND'), 404); return; } // Must be project creator if (!$this->model->access('owner')) { throw new Exception(Lang::txt('ALERTNOTAUTH'), 403); return; } // Must be a provisioned project to be activated if (!$this->model->isProvisioned()) { // Redirect to project page App::redirect(Route::url($this->model->link())); return; } // Redirect to setup if activation not complete if ($this->model->inSetup()) { App::redirect(Route::url($this->model->link('setup'))); return; } // Get publication of a provisioned project $pub = $this->model->getPublication(); if (empty($pub)) { throw new Exception(Lang::txt('COM_PROJECTS_PROJECT_NOT_FOUND'), 404); return; } // Incoming $name = trim(Request::getVar('new-alias', '', 'post')); $title = trim(Request::getVar('title', '', 'post')); $confirm = trim(Request::getInt('confirm', 0, 'post')); $name = preg_replace('/ /', '', $name); $name = strtolower($name); // Check incoming data $verified = $this->model->check($name, $this->model->get('id')); if ($confirm && !$verified) { $error = $this->model->getError() ? $this->model->getError() : Lang::txt('COM_PROJECTS_ERROR_NAME_INVALID_OR_EMPTY'); $this->setError($error); } elseif ($confirm && ($title == '' || strlen($title) < 3)) { $this->setError(Lang::txt('COM_PROJECTS_ERROR_TITLE_SHORT_OR_EMPTY')); } // Set the pathway $this->_buildPathway(); // Set the page title $this->_buildTitle(); // Display page if (!$confirm || $this->getError()) { $this->view->setLayout('provisioned'); $this->view->model = $this->model; $this->view->team = $this->model->_tblOwner->getOwnerNames($this->model->get('alias')); // Output HTML $this->view->pub = isset($pub) ? $pub : ''; $this->view->suggested = $name; $this->view->verified = $verified; $this->view->suggested = $verified ? $this->view->suggested : ''; $this->view->title = $this->title; $this->view->active = $this->active; $this->view->task = $this->_task; $this->view->authorized = 1; $this->view->option = $this->_option; $this->view->msg = $this->_getNotifications('success'); if ($this->getError()) { $this->view->setError($this->getError()); } $this->view->display(); return; } // Save new alias & title if (!$this->getError()) { $this->model->set('title', \Hubzero\Utility\String::truncate($title, 250)); $this->model->set('alias', $name); $state = $this->_setupComplete == 3 ? 0 : 1; $this->model->set('state', $state); $this->model->set('setup_stage', 2); $this->model->set('provisioned', 0); $this->model->set('modified', Date::toSql()); $this->model->set('modified_by', User::get('id')); // Save changes if (!$this->model->store()) { $this->setError($this->model->getError()); } } // Get project parent directory $path = Helpers\Html::getProjectRepoPath($this->model->get('alias')); $newpath = Helpers\Html::getProjectRepoPath($name, 'files', true); // Rename project parent directory if ($path && is_dir($path)) { if (!Filesystem::copyDirectory($path, $newpath)) { $this->setError(Lang::txt('COM_PROJECTS_FAILED_TO_COPY_FILES')); } else { // Correct permissions to 0755 Filesystem::setPermissions($newpath); // Delete original repo Filesystem::deleteDirectory($path); } } // Log activity $this->_logActivity($this->model->get('id'), 'provisioned', 'activate', 'save', 1); // Send to continue setup App::redirect(Route::url($this->model->link('setup'))); return; }