/** * Set GET param to property array * @param int|string $page_id * @return array */ protected function setUrlPage($page_id) { $url = $this->url; switch (count($url)) { // check nulls if not set case 1: // only controller/action is defined $url[1] = null; $url[2] = null; break; case 2: $url[2] = null; break; } // add page param if > 0 if ((int) $page_id > 0) { // merge with ?page if query is not empty if (Obj::isArray($url[3])) { $url[3] = Arr::merge($url[3], ['page' => $page_id]); } else { // just set ?page=$page_id $url[3] = ['page' => $page_id]; } } return $url; }
/** * Prepare category data to display * @throws ForbiddenException */ private function buildCategory() { $catConfigs = $this->_currentCategory->configs; // prepare rss url link for current category if enabled $rssUrl = false; if ((int) $this->_configs['rss'] === 1 && (int) $catConfigs['showRss'] === 1) { $rssUrl = App::$Alias->baseUrl . '/content/rss/' . $this->_currentCategory->path; $rssUrl = rtrim($rssUrl, '/'); } // prepare sorting urls $catSortParams = []; if (App::$Request->query->get('page') !== null) { $catSortParams['page'] = (int) App::$Request->query->get('page'); } $catSortUrls = ['views' => Url::to('content/list', $this->_currentCategory->path, null, Arr::merge($catSortParams, ['sort' => 'views']), false), 'rating' => Url::to('content/list', $this->_currentCategory->path, null, Arr::merge($catSortParams, ['sort' => 'rating']), false), 'newest' => Url::to('content/list', $this->_currentCategory->path, null, $catSortParams, false)]; // prepare current category data to output (unserialize locales and strip tags) $this->category = ['title' => $this->_currentCategory->getLocaled('title'), 'description' => $this->_currentCategory->getLocaled('description'), 'configs' => $catConfigs, 'path' => $this->_currentCategory->path, 'rss' => $rssUrl, 'sort' => $catSortUrls]; // check if this category is hidden if ((int) $this->category['configs']['showCategory'] !== 1) { throw new ForbiddenException(__('This category is not available to view')); } // make sorted tree of categories to display in breadcrumbs foreach ($this->_allCategories as $cat) { $this->categories[$cat->id] = $cat; } }
/** * Prepare model attributes from passed objects * @throws ForbiddenException */ public function before() { $this->id = $this->_content->id; $this->title = $this->_content->getLocaled('title'); $this->text = $this->_content->getLocaled('text'); // check if title and text are exists if (Str::length($this->title) < 1 || Str::length($this->text) < 1) { throw new ForbiddenException(); } // get meta data $this->metaTitle = $this->_content->getLocaled('meta_title'); if (Str::likeEmpty($this->metaTitle)) { $this->metaTitle = $this->title; } $this->metaDescription = $this->_content->getLocaled('meta_description'); $tmpKeywords = $this->_content->getLocaled('meta_keywords'); $this->metaKeywords = explode(',', $tmpKeywords); // set content date, category data $this->createDate = Date::humanize($this->_content->created_at); $this->catName = $this->_category->getLocaled('title'); $this->catPath = $this->_category->path; // set user data if (App::$User->isExist($this->_content->author_id)) { $this->authorId = $this->_content->author_id; $profile = App::$User->identity($this->authorId)->getProfile(); $this->authorName = $profile->getNickname(); } $this->source = $this->_content->source; $this->views = $this->_content->views + 1; // check for dependence, add '' for general cat, ex: general/depend1/depend2/.../depend-n $catNestingArray = Arr::merge([0 => ''], explode('/', $this->catPath)); if ($catNestingArray > 1) { // latest element its a current nesting level, lets cleanup it array_pop($catNestingArray); $catNestingPath = null; foreach ($catNestingArray as $cPath) { $catNestingPath .= $cPath; // try to find category by path in db $record = ContentCategory::getByPath($catNestingPath); if ($record !== null && $record->count() > 0) { // if founded - add to nesting data $this->catNesting[] = ['name' => $record->getLocaled('title'), 'path' => $record->path]; } if (!Str::likeEmpty($catNestingPath)) { $catNestingPath .= '/'; } } } // build array of category nesting level $this->catNesting[] = ['name' => $this->catName, 'path' => $this->catPath]; // get gallery images and poster data $galleryPath = '/upload/gallery/' . $this->_content->id; // check if gallery folder is exist if (Directory::exist($galleryPath)) { $originImages = File::listFiles($galleryPath . '/orig/', ['.jpg', '.png', '.gif', '.jpeg', '.bmp', '.webp'], true); // generate poster data if (Arr::in($this->_content->poster, $originImages)) { // original poster $posterName = $this->_content->poster; $this->posterFull = $galleryPath . '/orig/' . $posterName; if (!File::exist($this->posterFull)) { $this->posterFull = null; } // thumb poster $posterSplit = explode('.', $posterName); array_pop($posterSplit); $posterCleanName = implode('.', $posterSplit); $this->posterThumb = $galleryPath . '/thumb/' . $posterCleanName . '.jpg'; if (!File::exist($this->posterThumb)) { $this->posterThumb = null; } } // generate full gallery foreach ($originImages as $image) { $imageSplit = explode('.', $image); array_pop($imageSplit); $imageClearName = implode('.', $imageSplit); // skip image used in poster if (Str::startsWith($imageClearName, $this->_content->poster)) { continue; } $thumbPath = $galleryPath . '/thumb/' . $imageClearName . '.jpg'; if (File::exist($thumbPath)) { $this->galleryItems[$thumbPath] = $galleryPath . '/orig/' . $image; } } } // set rating data $this->rating = $this->_content->rating; $ignoredRate = App::$Session->get('content.rate.ignore'); $this->canRate = true; if (Obj::isArray($ignoredRate) && Arr::in((string) $this->id, $ignoredRate)) { $this->canRate = false; } if (!App::$User->isAuth()) { $this->canRate = false; } elseif ($this->authorId === App::$User->identity()->getId()) { $this->canRate = false; } // update views count $this->_content->views += 1; $this->_content->save(); }
/** * Append translation data from exist full path * @param string $path * @return bool */ public function append($path) { $path = Normalize::diskFullPath($path); // check if file exist if (!File::exist($path)) { return false; } // load file translations $addTranslation = (require $path); if (!Obj::isArray($addTranslation)) { return false; } // merge data $this->cached = Arr::merge($this->cached, $addTranslation); return true; }
/** * Console installation * @return string * @throws NativeException */ public function actionInstall() { if (File::exist('/Private/Install/install.lock')) { throw new NativeException('Installation is locked! Please delete /Private/Install/install.lock'); } echo Console::$Output->writeHeader('License start'); echo File::read('/LICENSE') . PHP_EOL; echo Console::$Output->writeHeader('License end'); $config = Console::$Properties->get('database'); $newConfig = []; // creating default directory's foreach (self::$installDirs as $obj) { // looks like a directory if (!Str::contains('.', $obj)) { Directory::create($obj, 0777); } } echo Console::$Output->write('Upload and private directories are successful created!'); // set chmods echo $this->actionChmod(); // database config from input echo Console::$Output->writeHeader('Database connection configuration'); echo 'Driver(default:' . $config['driver'] . '):'; $dbDriver = Console::$Input->read(); if (Arr::in($dbDriver, ['mysql', 'pgsql', 'sqlite'])) { $newConfig['driver'] = $dbDriver; } // for sqlite its would be a path echo 'Host(default:' . $config['host'] . '):'; $dbHost = Console::$Input->read(); if (!Str::likeEmpty($dbHost)) { $newConfig['host'] = $dbHost; } echo 'Database name(default:' . $config['database'] . '):'; $dbName = Console::$Input->read(); if (!Str::likeEmpty($dbName)) { $newConfig['database'] = $dbName; } echo 'User(default:' . $config['username'] . '):'; $dbUser = Console::$Input->read(); if (!Str::likeEmpty($dbUser)) { $newConfig['username'] = $dbUser; } echo 'Password(default:' . $config['password'] . '):'; $dbPwd = Console::$Input->read(); if (!Str::likeEmpty($dbPwd)) { $newConfig['password'] = $dbPwd; } echo 'Table prefix(default:' . $config['prefix'] . '):'; $dbPrefix = Console::$Input->read(); if (!Str::likeEmpty($dbPrefix)) { $newConfig['prefix'] = $dbPrefix; } // merge configs and add new connection to db pull $dbConfigs = Arr::merge($config, $newConfig); Console::$Database->addConnection($dbConfigs, 'install'); try { Console::$Database->connection('install')->getDatabaseName(); } catch (\Exception $e) { return 'Testing database connection is failed! Run installer again and pass tested connection data! Log: ' . $e->getMessage(); } // autoload isn't work here include root . '/Apps/Controller/Console/Db.php'; // import db data $dbController = new DbController(); echo $dbController->actionImportAll('install'); // add system info about current install version $system = new System(); $system->setConnection('install'); $system->var = 'version'; $system->data = Version::VERSION; $system->save(); // set website send from email from input $emailConfig = Console::$Properties->get('adminEmail'); echo 'Website sendFrom email(default: ' . $emailConfig . '):'; $email = Console::$Input->read(); if (!Str::isEmail($email)) { $email = $emailConfig; } // set base domain echo 'Website base domain name(ex. ffcms.org):'; $baseDomain = Console::$Input->read(); if (Str::likeEmpty($baseDomain)) { $baseDomain = Console::$Properties->get('baseDomain'); } // generate other configuration data and security salt, key's and other echo Console::$Output->writeHeader('Writing configurations'); /** @var array $allCfg */ $allCfg = Console::$Properties->getAll('default'); $allCfg['database'] = $dbConfigs; $allCfg['adminEmail'] = $email; $allCfg['baseDomain'] = $baseDomain; echo Console::$Output->write('Generate password salt for BLOWFISH crypt'); $allCfg['passwordSalt'] = '$2a$07$' . Str::randomLatinNumeric(mt_rand(21, 30)) . '$'; echo Console::$Output->write('Generate security cookies for debug panel'); $allCfg['debug']['cookie']['key'] = 'fdebug_' . Str::randomLatinNumeric(mt_rand(8, 32)); $allCfg['debug']['cookie']['value'] = Str::randomLatinNumeric(mt_rand(32, 128)); // write config data $writeCfg = Console::$Properties->writeConfig('default', $allCfg); if ($writeCfg !== true) { return 'File /Private/Config/Default.php is unavailable to write data!'; } File::write('/Private/Install/install.lock', 'Install is locked'); return 'Configuration done! FFCMS 3 is successful installed! Visit your website. You can add administrator using command php console.php db/adduser'; }
/** * Construct table based on passed elements as array: properties, thead, tbody, rows, items etc * @param array $elements * @return null */ public static function display($elements) { // check passed data if (!Obj::isArray($elements) || count($elements) < 1) { return null; } if (!isset($elements['tbody']) || !Obj::isArray($elements['tbody']['items']) || count($elements['tbody']['items']) < 1) { return null; } $selectOptions = false; if (isset($elements['selectableBox'])) { $selectOptions = $elements['selectableBox']; unset($elements['selectableBox']); } // init dom model $dom = new Dom(); // draw response $table = $dom->table(function () use($dom, $elements, $selectOptions) { $res = null; // check if thead is defined if (isset($elements['thead']) && Obj::isArray($elements['thead']) && count($elements['thead']) > 0 && Obj::isArray($elements['thead']['titles'])) { // add thead container $res .= $dom->thead(function () use($dom, $elements, $selectOptions) { return $dom->tr(function () use($dom, $elements, $selectOptions) { $tr = null; foreach ($elements['thead']['titles'] as $order => $title) { $th = null; if ($title['html'] === true) { if ($title['!secure'] === true) { $th = $title['text']; } else { $th = self::safe($title['text'], true); } } else { $th = htmlentities($title['text']); } // make global checkbox for selectable columns if ($selectOptions !== false && $order + 1 === $selectOptions['attachOrder']) { $th = $dom->input(function () { return null; }, ['type' => 'checkbox', 'name' => 'selectAll']) . ' ' . $th; } // build tr row collecting all th's $tr .= $dom->th(function () use($th) { return $th; }, $title['property']); } // return tr row in thead return $tr; }); }, $elements['thead']['property']); } // parse tbody array elements if (isset($elements['tbody']) && Obj::isArray($elements['tbody']) && isset($elements['tbody']['items']) && Obj::isArray($elements['tbody']['items'])) { // add tbody container $res .= $dom->tbody(function () use($dom, $elements, $selectOptions) { $tr = null; // each all items by row (tr) foreach ($elements['tbody']['items'] as $row) { // sort td items inside row by key increment ksort($row); // add data in tr container $tr .= $dom->tr(function () use($dom, $row, $selectOptions) { $td = null; foreach ($row as $order => $item) { if (!Obj::isInt($order)) { continue; } // collect td item $td .= $dom->td(function () use($dom, $order, $item, $selectOptions) { $text = null; // make text secure based on passed options if ($item['html'] === true) { if ($item['!secure'] === true) { $text = $item['text']; } else { $text = self::safe($item['text'], true); } } else { $text = htmlentities($item['text']); } // check if selectable box is enabled and equal current order id if ($selectOptions !== false && $order === $selectOptions['attachOrder']) { $text = $dom->input(function () { return null; }, Arr::merge($selectOptions['selector'], ['value' => htmlentities($text)])) . ' ' . $text; } return $text; }, $item['property']); } return $td; }, $row['property']); } return $tr; }, $elements['tbody']['property']); } // return all computed code return $res; }, $elements['table']); // check if select box is defined and used if ($selectOptions !== false || Obj::isArray($selectOptions)) { // build js code for "selectAll" checkbox self::buildSelectorHtml($selectOptions); // return response inside "form" tag return $dom->form(function () use($dom, $selectOptions, $table) { foreach ($selectOptions['buttons'] as $btn) { if (!Obj::isArray($btn)) { continue; } $table .= $dom->input(function () { return null; }, $btn) . ' '; } return $table; }, $selectOptions['form']); } return $table; }