/** * Upload files from ckeditor * @param string $type * @return string * @throws NativeException * @throws \Ffcms\Core\Exception\SyntaxException */ public function actionUpload($type) { /** @var $loadFile \Symfony\Component\HttpFoundation\File\UploadedFile */ $loadFile = App::$Request->files->get('upload'); if ($loadFile === null || $loadFile->getError() !== 0) { return $this->errorResponse(__('File upload failed')); } // get file extension $fileExt = '.' . $loadFile->guessExtension(); // check if this request type is allowed if ($this->allowedExt[$type] === null || !Obj::isArray($this->allowedExt[$type])) { throw new NativeException('Hack attempt'); } // check if this file extension is allowed to upload if (!Arr::in($fileExt, $this->allowedExt[$type])) { return $this->errorResponse(__('This file type is not allowed to upload')); } $date = Date::convertToDatetime(time(), 'd-m-Y'); // create file hash based on name-size $fileNewName = App::$Security->simpleHash($loadFile->getFilename() . $loadFile->getSize()) . $fileExt; $savePath = Normalize::diskFullPath('/upload/' . $type . '/' . $date); // save file from tmp to regular $loadFile->move($savePath, $fileNewName); // generate URI of uploaded file $url = '/upload/' . $type . '/' . $date . '/' . $fileNewName; return App::$View->render('editor/load_success', ['callbackId' => (int) App::$Request->query->get('CKEditorFuncNum'), 'url' => $url], __DIR__); }
/** * Build <input type="checkbox" checked {$properties} /> response * {@inheritDoc} * @see \Ffcms\Core\Helper\HTML\Form\iField::make() * @throws \Ffcms\Core\Exception\NativeException * @throws \Ffcms\Core\Exception\SyntaxException */ public function make() { // check if options is defined $options = $this->properties['options']; if (!Obj::isIterable($options)) { throw new SyntaxException('Options for field ' . self::nohtml($this->name) . ' is not iterable'); } unset($this->properties['options']); // set field type $this->properties['type'] = 'checkbox'; // set this field as array html dom object $this->properties['name'] .= '[]'; unset($this->properties['value'], $this->properties['id']); $build = null; foreach ($options as $opt) { // check if this is active element if (Obj::isArray($this->value) && Arr::in($opt, $this->value)) { $this->properties['checked'] = null; } else { unset($this->properties['checked']); // remove checked if it setted before } $this->properties['value'] = $opt; // apply structured checkboxes style for each item $build .= App::$View->render('native/form/multi_checkboxes_list', ['item' => self::buildSingleTag('input', $this->properties) . self::nohtml($opt)]); } return $build; }
/** * Construct listing elements,property's and future's * @param array $elements * @return string */ public static function display($elements) { // check input elements if (!Arr::in($elements['type'], ['ul', 'ol']) || count($elements['items']) < 1) { return null; } // initialize new DOM model $dom = new Dom(); // return DOM-HTML, build based on closures! return $dom->{$elements['type']}(function () use($dom, $elements) { // prepare output avg variable $itemHTML = null; // get active order level $orderActiveLink = false; if (isset($elements['activeOrder'])) { $orderActiveLink = $elements['activeOrder']; unset($elements['activeOrder']); } foreach ($elements['items'] as $item) { // sounds like dropdown array if (isset($item['dropdown']) && isset($item['items'])) { $itemHTML .= self::buildDropdown($dom, $item); } elseif (isset($item['link'])) { // looks like link item $itemHTML .= self::buildLink($dom, $item, $orderActiveLink); } else { // just text item $itemHTML .= self::buildText($dom, $item); } } return $itemHTML; }, $elements['property']); }
/** * FormInstall constructor. Pass applications object from controller * @param $apps * @param string $type * @throws SyntaxException */ public function __construct(array $apps = null, $type) { $this->_apps = $apps; // check if passed type is allowed to use if (!Arr::in($type, ['app', 'widget'])) { throw new SyntaxException('The type of extension is not defined!'); } $this->_type = $type; parent::__construct(); }
/** * Build output content by tag name, tag content and properties * @param string $name * @param string|null $content * @param array|null $properties * @return null|string */ private function buildTag($name, $content = null, array $properties = null) { // looks like a single tag, <img src="" class="" />, <hr class="" /> if (Arr::in($name, self::$singleTags)) { return '<' . $name . self::applyProperties($properties) . ' />'; } elseif (Arr::in($name, self::$containerTags)) { // looks like a container tag, <div class=""></div> return '<' . $name . self::applyProperties($properties) . '>' . $content . '</' . $name . '>'; } // empty response return null; }
/** * Get user avatar full url for current object * @param string $type * @return string */ public function getAvatarUrl($type = 'small') { $default = '/upload/user/avatar/' . $type . '/default.jpg'; if (!Arr::in($type, ['small', 'big', 'medium'])) { return MainApp::$Alias->scriptUrl . $default; } $route = '/upload/user/avatar/' . $type . '/' . $this->user_id . '.jpg'; if (File::exist($route)) { return MainApp::$Alias->scriptUrl . $route . '?mtime=' . File::mTime($route); } return MainApp::$Alias->scriptUrl . $default; }
/** * Pass init params */ public function init() { if ($this->language === null) { $this->language = App::$Request->getLanguage(); } if ($this->targetClass === null) { $this->targetClass = 'wysiwyg'; } if ($this->config === null || !Arr::in($this->config, ['config-small', 'config-full', 'config-medium'])) { $this->config = 'config-default'; } $this->baseUrl = App::$Alias->scriptUrl . '/vendor/phpffcms/ffcms-ckeditor/assets'; }
/** * Get single row by defined type and sys_name with query caching * @param string $type * @param string|array $sys_name * @return mixed|null * @throws SyntaxException */ public static function getItem($type, $sys_name) { foreach (self::all() as $object) { if ($object->type === $type) { //&& $object->sys_name === $sys_name) { if (Obj::isArray($sys_name) && Arr::in($object->sys_name, $sys_name)) { // many different app name - maybe alias or something else return $object; } elseif (Obj::isString($sys_name) && $object->sys_name === $sys_name) { return $object; } } } return null; }
/** * Get internalization of current text from i18n * @param string $index * @param string $text * @param array|null $params * @return string */ public function get($index, $text, array $params = null) { if (App::$Request->getLanguage() !== App::$Properties->get('baseLanguage')) { if ($index !== null && !Arr::in($index, $this->indexes)) { $this->cached = Arr::merge($this->cached, $this->load($index)); $this->indexes[] = $index; } if ($this->cached !== null && Obj::isString($text) && isset($this->cached[$text])) { $text = $this->cached[$text]; } } if (Obj::isArray($params) && count($params) > 0) { foreach ($params as $var => $value) { $text = Str::replace('%' . $var . '%', $value, $text); } } return $text; }
/** * Check passed params from constructor * @throws \Ffcms\Core\Exception\SyntaxException */ public function before() { // check rule type if (!Arr::in($this->type, ['Alias', 'Callback'])) { throw new SyntaxException(); } // check loader env type if (!Arr::in($this->loader, ['Front', 'Admin', 'Api'])) { throw new SyntaxException(); } // prepare source path if ($this->type === 'Alias') { $this->source = '/' . trim($this->source, '/'); } else { $this->source = ucfirst($this->source); } if (!isset($this->_cfg[$this->type][$this->loader][$this->source])) { throw new SyntaxException(); } }
/** * List category content * @throws NotFoundException * @throws \Ffcms\Core\Exception\SyntaxException * @throws \Ffcms\Core\Exception\NativeException * @return string */ public function actionList() { $path = $this->request->getPathWithoutControllerAction(); $configs = $this->getConfigs(); $page = (int) $this->request->query->get('page', 0); $sort = (string) $this->request->query->get('sort', 'newest'); $itemCount = (int) $configs['itemPerCategory']; // build special model with content list and category list information $model = new EntityCategoryList($path, $configs, $page, $sort); // prepare query string (?a=b) for pagination if sort is defined $sortQuery = null; if (Arr::in($sort, ['rating', 'views'])) { $sortQuery = ['sort' => $sort]; } // build pagination $pagination = new SimplePagination(['url' => ['content/list', $path, null, $sortQuery], 'page' => $page, 'step' => $itemCount, 'total' => $model->getContentCount()]); // define list event App::$Event->run(static::EVENT_CONTENT_LIST, ['model' => $model]); // draw response view return $this->view->render('list', ['model' => $model, 'pagination' => $pagination, 'configs' => $configs]); }
/** * Add user in database * @return string * @throws NativeException */ public function actionAdduser() { echo "Login:"******"Email:"; $email = Console::$Input->read(); if (!Str::isEmail($email)) { throw new NativeException('Email is bad'); } echo "Password:"******"RoleId (1 = onlyread, 2 = user, 3 = moderator, 4 = admin):"; $role = (int) Console::$Input->read(); if (!Arr::in($role, [1, 2, 3, 4])) { $role = 2; } if (User::isMailExist($email) || User::isLoginExist($login)) { throw new NativeException('User with this email or login is always exist'); } $salt = Console::$Properties->get('passwordSalt'); $user = new User(); $user->login = $login; $user->email = $email; $user->password = Security::password_hash($pass, $salt); $user->role_id = $role; $user->save(); $profile = new Profile(); $profile->user_id = $user->id; $profile->save(); return 'User was successful added to database!'; }
/** * Build <select @properties>@optionsDOM</select> container * {@inheritDoc} * @see \Ffcms\Core\Helper\HTML\Form\iField::make() */ public function make() { // check if options is defined $options = $this->properties['options']; $optionsKey = (bool) $this->properties['optionsKey']; if (!Obj::isIterable($options)) { throw new SyntaxException('Options for field ' . self::nohtml($this->name) . ' is not iterable'); } unset($this->properties['options']); // set global field type $this->properties['type'] = 'select'; // add multiple element $this->properties['multiple'] = null; $this->properties['name'] .= '[]'; unset($this->properties['value'], $this->properties['options'], $this->properties['optionsKey']); // build options as HTML DOM element: <option @value>@text</option> $optionsDOM = null; foreach ($options as $val => $text) { // check if options key is value $optionProperty = null; if ($optionsKey === true) { $optionProperty['value'] = $val; // check if current element is active if (Obj::isArray($this->value) && Arr::in((string) $val, $this->value)) { $optionProperty['selected'] = 'selected'; } } else { if (Obj::isArray($this->value) && Arr::in((string) $text, $this->value)) { $optionProperty['selected'] = 'selected'; } } $optionsDOM .= self::buildContainerTag('option', $optionProperty, $text); } // build <select @properties>@optionsDOM</select> return self::buildContainerTag('select', $this->properties, $optionsDOM, true); }
/** * Prepare static pathway aliasing for routing * @param array|null $map * @param string|null $pathway * @return string */ private function findStaticAliases(array $map = null, $pathway = null) { if ($map === null) { return $pathway; } // current pathway is found as "old path" (or alias target). Make redirect to new pathway. if (Arr::in($pathway, $map)) { // find "new path" as binding uri slug $binding = array_search($pathway, $map, true); // build url to redirection $url = $this->getSchemeAndHttpHost() . $this->getBasePath() . '/'; if (App::$Properties->get('multiLanguage')) { $url .= $this->language . '/'; } $url .= ltrim($binding, '/'); $redirect = new Redirect($url); $redirect->send(); exit; } // current pathway request is equal to path alias. Set alias to property. if (array_key_exists($pathway, $map)) { $pathway = $map[$pathway]; $this->aliasPathTarget = $pathway; } return $pathway; }
/** * 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'; }
$widgetControllers[] = 'Widget'; ?> <li<?php echo Arr::in(\App::$Request->getController(), $appControllers) ? ' class="active"' : null; ?> > <a href="#"><i class="fa fa-plug fa-fw"></i> <?php echo __('Applications'); ?> <span class="fa arrow"></span></a> <?php echo Listing::display(['type' => 'ul', 'property' => ['class' => 'nav nav-second-level'], 'activeOrder' => 'controller', 'items' => $appMenuItems]); ?> </li> <li<?php echo Arr::in(\App::$Request->getController(), $widgetControllers) ? ' class="active"' : null; ?> > <a href="#"><i class="fa fa-puzzle-piece fa-fw"></i> <?php echo __('Widgets'); ?> <span class="fa arrow"></span></a> <?php echo Listing::display(['type' => 'ul', 'property' => ['class' => 'nav nav-second-level'], 'activeOrder' => 'controller', 'items' => $widgetMenuItems]); ?> </li> </ul> </div> <!-- /.sidebar-collapse --> </div> <!-- /.navbar-static-side -->
} foreach ($model->items as $item) { ?> <article class="article-item" itemscope="itemscope" itemtype="https://schema.org/NewsArticle"> <h2 itemprop="name"> <a href="<?php echo \App::$Alias->baseUrl . $item['uri']; ?> "> <?php echo $item['title']; ?> </a> </h2> <?php if (Arr::in(true, $catMeta)) { ?> <div class="meta"> <?php if ($catConfigs['showCategory'] === true) { ?> <span class="spaced"><i class="fa fa-list"></i> <?php echo Url::link(['content/list', $item['category']->path], \App::$Translate->getLocaleText($item['category']->title), ['itemprop' => 'genre']); ?> </span> <?php } ?> <?php if ($catConfigs['showDate'] === true) {
/** * Recursive scan directory, based on $path and allowed extensions $ext or without it * @param string $path * @param array $ext * @param bool $returnRelative * @param $files * @return array */ public static function listFiles($path, array $ext = null, $returnRelative = false, &$files = []) { $path = Normalize::diskFullPath($path); if (!Directory::exist($path)) { return []; } $dir = opendir($path . '/.'); while ($item = readdir($dir)) { if (is_file($sub = $path . '/' . $item)) { $item_ext = Str::lastIn($item, '.'); if ($ext === null || Arr::in($item_ext, $ext)) { if ($returnRelative) { $files[] = $item; } else { $files[] = $path . DIRECTORY_SEPARATOR . $item; } } } else { if ($item !== '.' && $item !== '..') { self::listFiles($sub, $ext, $returnRelative, $files); } } } return $files; }
/** * Try to download and parse remote avatar * @param string $url * @param int $userId */ protected function parseAvatar($url, $userId) { // check if user is defined if ((int) $userId < 1) { return; } // check remote image extension $imageExtension = Str::lastIn($url, '.', true); if (!Arr::in($imageExtension, ['png', 'gif', 'jpg', 'jpeg'])) { return; } // try to get image binary data $imageContent = Url::download($url); if ($imageContent === null || Str::likeEmpty($imageContent)) { return; } // write image to filesystem $imagePath = '/upload/user/avatar/original/' . $userId . '.' . $imageExtension; $write = File::write($imagePath, $imageContent); if ($write === false) { return; } // try to write and resize file try { $fileObject = new FileObject(root . $imagePath); $avatarUpload = new FormAvatarUpload(); $avatarUpload->resizeAndSave($fileObject, $userId, 'small'); $avatarUpload->resizeAndSave($fileObject, $userId, 'medium'); $avatarUpload->resizeAndSave($fileObject, $userId, 'big'); } catch (\Exception $e) { if (App::$Debug) { App::$Debug->addException($e); } } }
/** * Display nav listing block * @param array $elements */ public static function display($elements) { // check if elements isn't empty and contains rows if (!Obj::isArray($elements) || count($elements['items']) < 1) { return null; } // prepare tab order if ($elements['tabAnchor'] === null) { $elements['tabAnchor'] = Str::randomLatin(mt_rand(6, 12)); } // set global element properties $blockProperty = []; if ($elements['blockProperty'] !== null) { if (Obj::isArray($elements['blockProperty'])) { $blockProperty = $elements['blockProperty']; } unset($elements['blockProperty']); } // check if items have defined active order $activeDefined = Arr::in(true, Arr::ploke('active', $elements['items'])); // prepare tab content $tabContent = null; $tabIdx = 1; // initialize dom model $dom = new Dom(); // prepare items to drow listing $items = []; foreach ($elements['items'] as $item) { // its just a link, drow it as is if ($item['type'] === 'link') { $items[] = $item; } elseif ($item['type'] === 'dropdown') { // build bootstrap dropdown properties $item['dropdown'] = ['class' => 'dropdown-toggle', 'data-toggle' => 'dropdown', 'href' => '#']; $item['property']['class'] = Str::concat(' ', 'dropdown', $item['property']['class']); $items[] = $item; } elseif ($item['type'] === 'tab') { $activeObject = false; $item['type'] = 'link'; // fix for global Listing builder $item['link'] = '#' . $elements['tabAnchor'] . $tabIdx; $item['property']['role'] = 'presentation'; // check if active definition is exist in elements options if ($activeDefined) { if ($item['active'] === true) { $activeObject = true; } } elseif ($tabIdx === 1) { // if not exist set first as active $activeObject = true; } // mark active tab if ($activeObject === true) { $item['property']['class'] .= (Str::length($item['property']['class']) > 0 ? ' ' : null) . 'active'; } // tab special properties for bootstrap $item['linkProperty']['aria-controls'] = $elements['tabAnchor'] . $tabIdx; $item['linkProperty']['role'] = 'tab'; $item['linkProperty']['data-toggle'] = 'tab'; $itemContent = $item['content']; unset($item['content']); $items[] = $item; // draw tab content $tabContent .= $dom->div(function () use($item, $itemContent) { if ($item['html'] === true) { if ($item['!secure'] === true) { return $itemContent; } else { return self::safe($itemContent, true); } } else { return self::nohtml($itemContent); } }, ['role' => 'tabpanel', 'class' => 'tab-pane fade' . ($activeObject === true ? ' in active' : null), 'id' => $elements['tabAnchor'] . $tabIdx]); $tabIdx++; } } // check if global class "nav" isset if ($elements['property']['class'] !== null) { if (!Str::contains('nav ', $elements['property']['class'])) { $elements['property']['class'] = 'nav ' . $elements['property']['class']; } } else { $elements['property']['class'] = 'nav'; } // render final output return $dom->div(function () use($elements, $items, $tabContent, $dom) { // drow listing $listing = Listing::display(['type' => 'ul', 'property' => $elements['property'], 'activeOrder' => $elements['activeOrder'], 'items' => $items]); // drow tabs if isset if ($tabContent !== null) { $tabContent = $dom->div(function () use($tabContent) { return $tabContent; }, ['class' => 'tab-content']); } return $listing . $tabContent; }, $blockProperty); }
$breadcrumbs[] = __('Content') . ': ' . Str::sub($this->title, 0, 40); } $this->breadcrumbs = $breadcrumbs; } $properties = ['date' => (bool) $model->getCategory()->getProperty('showDate'), 'author' => (bool) $model->getCategory()->getProperty('showAuthor'), 'views' => (bool) $model->getCategory()->getProperty('showViews'), 'category' => (bool) $model->getCategory()->getProperty('showCategory'), 'rating' => (bool) $model->getCategory()->getProperty('showRating'), 'tags' => (bool) $model->getCategory()->getProperty('showTags')]; $showComments = (bool) $model->getCategory()->getProperty('showComments'); $showPoster = (bool) $model->getCategory()->getProperty('showPoster'); ?> <article class="article-item" itemscope="itemscope" itemtype="https://schema.org/NewsArticle"> <h1><?php echo $model->title; ?> </h1> <?php if (Arr::in(true, $properties)) { ?> <div class="meta"> <?php if ($properties['category'] === true) { ?> <span class="spaced"><i class="fa fa-list"></i> <?php echo Url::link(['content/list', $model->catPath, null, [], false], $model->catName, ['itemprop' => 'genre']); ?> </span> <?php } ?> <?php if ($properties['date'] === true) { ?>
/** * Check if user role contains permission * @param string $permission * @return bool */ public function can($permission) { // Role::get(id) is not initialized if ($this->permissions === null) { return false; } // global admin $permArray = explode(';', $this->permissions); if (count($permArray) < 1) { return false; } // admin can all :) if (Arr::in('global/all', $permArray)) { return true; } // check if current permission in user permission role if (Arr::in($permission, $permArray)) { return true; } return false; }
/** * Check if field is file or null * @param object $object * @param $value * @return bool */ public static function isFile($object, $value) { // allow empty fields, "required" option filter that if ($object === null) { return true; } $all = false; // if string is given if (!Obj::isArray($value)) { if ($value === '*') { $all = true; } else { $value = [$value]; } } // input file is not object? if ($object === null || !Obj::isObject($object)) { return false; } // get guess file type, based on mime-type $type = $object->guessExtension(); if ($type === null) { return false; } return $all ? true : Arr::in($type, $value); }
/** * List messages with correspondent * @param $cor_id * @return string * @throws ForbiddenException * @throws NotFoundException * @throws NativeException */ public function actionMessageList($cor_id) { if (!App::$User->isAuth()) { throw new ForbiddenException('Auth required'); } if (!Obj::isLikeInt($cor_id) || $cor_id < 1) { throw new NotFoundException('Corresponded id is wrong'); } // get special types for this action $queryType = $this->request->get('type'); $queryId = (int) $this->request->get('id'); // get current user object $user = App::$User->identity(); if (Arr::in($queryType, ['before', 'after']) && (!Obj::isLikeInt($queryId) || $queryId < 1)) { throw new NativeException('Bad input data'); } $messages = null; // sounds like a Hindi code, but we need more closures to organize where conditions // after raw: select * from `ffcms_messages` where `id` > ? and ((`target_id` = ? and `sender_id` = ?) or (`target_id` = ? and `sender_id` = ?)) order by `created_at` desc // before raw: select * from `ffcms_messages` where (`target_id` = ? and `sender_id` = ?) or (`target_id` = ? and `sender_id` = ?) order by `created_at` desc // default raw: select * from `ffcms_messages` where `id` < ? and ((`target_id` = ? and `sender_id` = ?) or (`target_id` = ? and `sender_id` = ?)) order by `created_at` desc switch ($queryType) { case 'after': $messages = Message::where('id', '>', $queryId)->where(function ($query) use($cor_id, $user) { $query->where(function ($q) use($cor_id, $user) { $q->where('target_id', '=', $user->getId())->where('sender_id', '=', $cor_id); })->orWhere(function ($q) use($cor_id, $user) { $q->where('target_id', '=', $cor_id)->where('sender_id', '=', $user->getId()); }); }); break; case 'before': $messages = Message::where('id', '<', $queryId)->where(function ($query) use($cor_id, $user) { $query->where(function ($q) use($cor_id, $user) { $q->where('target_id', '=', $user->getId())->where('sender_id', '=', $cor_id); })->orWhere(function ($q) use($cor_id, $user) { $q->where('target_id', '=', $cor_id)->where('sender_id', '=', $user->getId()); }); }); break; default: $messages = Message::where(function ($query) use($cor_id, $user) { $query->where('target_id', '=', $user->getId())->where('sender_id', '=', $cor_id); })->orWhere(function ($query) use($cor_id, $user) { $query->where('target_id', '=', $cor_id)->where('sender_id', '=', $user->getId()); }); break; } // set response header $this->setJsonHeader(); $messages->orderBy('created_at', 'DESC')->take(self::MSG_TEXT_LIST); // check if messages exist if ($messages->count() < 1) { return json_encode(['status' => 0, 'text' => 'No messages']); return; } // build response $response = null; foreach ($messages->get() as $msg) { $response[] = ['id' => $msg->id, 'my' => $msg->sender_id === $user->id, 'message' => $msg->message, 'date' => Date::convertToDatetime($msg->created_at, Date::FORMAT_TO_SECONDS), 'readed' => $msg->readed]; // update status to readed if ($msg->readed !== 1 && $msg->sender_id !== $user->id) { $msg->readed = 1; $msg->save(); } } return json_encode(['status' => 1, 'data' => array_reverse($response), 'blocked' => !Blacklist::check($user->id, $cor_id)]); }
/** * Build pathway from array $to. Example: ['controller/action', 'id', 'add', ['get' => 'value'], '#anchor'] * @param array $to * @param bool $encode * @return string|null */ public static function buildPathway(array $to = null, $encode = true) { // if empty passed - let show main page if ($to === null) { return null; } $response = Str::lowerCase(trim($to[0], '/')); // controller/action list($controller, $action) = explode('/', $response); $routing = App::$Properties->getAll('Routing'); // sounds like dynamic callback if (Str::startsWith('@', $controller)) { $controller = trim($controller, '@'); // search callback in properties if (isset($routing['Callback'][env_name]) && Arr::in($controller, $routing['Callback'][env_name])) { $pathInject = array_search($controller, $routing['Callback'][env_name]); // if path is founded - lets set source if ($pathInject !== false) { $controller = Str::lowerCase($pathInject); } } // if controller still looks like path injection - define last entity like controller name if (Str::contains('\\', $controller)) { $controller = Str::lastIn($controller, '\\', true); } $response = $controller . '/' . $action; } // check if controller and action is defined if (Str::likeEmpty($controller) || Str::likeEmpty($action)) { return null; } // id is defined? if (isset($to[1]) && !Str::likeEmpty($to[1])) { $response .= '/' . self::safeUri($to[1], $encode); } // add param is defined? if (isset($to[2]) && !Str::likeEmpty($to[2])) { $response .= '/' . self::safeUri($to[2], $encode); } // try to find static alias if (isset($routing['Alias'][env_name]) && Arr::in('/' . $response, $routing['Alias'][env_name])) { $pathAlias = array_search('/' . $response, $routing['Alias'][env_name]); if ($pathAlias !== false) { $response = Str::lowerCase(trim($pathAlias, '/')); } } // parse get attributes if (isset($to[3]) && Obj::isArray($to[3]) && count($to[3]) > 0) { // check if anchor bindig is exist $anchor = false; if (isset($to[3]['#']) && Obj::isString($to[3]['#']) && Str::startsWith('#', $to[3]['#'])) { $anchor = $to[3]['#']; unset($to[3]['#']); } $queryString = http_build_query($to[3]); if (Str::length($queryString) > 0) { $response .= '?' . http_build_query($to[3]); } if ($anchor !== false) { $response .= $anchor; } } // parse anchor link part #item-related-id-1 if (isset($to[4]) && Obj::isString($to[4]) && Str::startsWith('#', $to[4])) { $response .= $to[4]; } return $response; }
/** * 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(); }
/** * Check all params * @return bool */ public function checkAll() { return $this->checkPhpVersion() && $this->pdo && $this->gd && !Arr::in(false, $this->chmodCheck); }
/** * Build content data to model properties * @param $records * @throws ForbiddenException * @throws NotFoundException */ private function buildContent($records) { $nullItems = 0; foreach ($records as $row) { /** @var Content $row */ // check title length on current language locale $localeTitle = $row->getLocaled('title'); if (Str::likeEmpty($localeTitle)) { ++$nullItems; continue; } // get snippet from full text for current locale $text = Text::snippet($row->getLocaled('text')); $itemPath = $this->categories[$row->category_id]->path; if (!Str::likeEmpty($itemPath)) { $itemPath .= '/'; } $itemPath .= $row->path; // prepare tags data $tags = $row->getLocaled('meta_keywords'); if (!Str::likeEmpty($tags)) { $tags = explode(',', $tags); } else { $tags = null; } $owner = App::$User->identity($row->author_id); // make a fake if user is not exist over id if ($owner === null) { $owner = new User(); } // check if current user can rate item $ignoredRate = App::$Session->get('content.rate.ignore'); $canRate = true; if (Obj::isArray($ignoredRate) && Arr::in((string) $row->id, $ignoredRate)) { $canRate = false; } if (!App::$User->isAuth()) { $canRate = false; } elseif ($owner->getId() === App::$User->identity()->getId()) { // own item $canRate = false; } // build result array $this->items[] = ['id' => $row->id, 'title' => $localeTitle, 'text' => $text, 'date' => Date::humanize($row->created_at), 'updated' => $row->updated_at, 'author' => $owner, 'poster' => $row->getPosterUri(), 'thumb' => $row->getPosterThumbUri(), 'thumbSize' => File::size($row->getPosterThumbUri()), 'views' => (int) $row->views, 'rating' => (int) $row->rating, 'canRate' => $canRate, 'category' => $this->categories[$row->category_id], 'uri' => '/content/read/' . $itemPath, 'tags' => $tags]; } if ($nullItems === $this->_contentCount) { throw new NotFoundException(__('Content is not founded')); } }
/** * @param string $type * @param string $code * @return bool */ public function addPlainCode($type, $code) { $allowed = ['css', 'js']; if (!Arr::in($type, $allowed)) { return false; } $this->plainCode[$type][] = $code; return true; }
/** * Remove items from gallery (preview+full) * @param int $id * @param string $file * @throws ForbiddenException * @throws NativeException * @return string */ public function actionGallerydelete($id, $file = null) { if ($file === null || Str::likeEmpty($file)) { $file = (string) $this->request->query->get('file', null); } // check passed data if (Str::likeEmpty($file) || !Obj::isLikeInt($id)) { throw new NativeException('Wrong input data'); } // check passed file extension $fileExt = Str::lastIn($file, '.', true); $fileName = Str::firstIn($file, '.'); if (!Arr::in($fileExt, $this->allowedExt)) { throw new ForbiddenException('Wrong file extension'); } // generate path $thumb = '/upload/gallery/' . $id . '/thumb/' . $fileName . '.jpg'; $full = '/upload/gallery/' . $id . '/orig/' . $file; // check if file exists and remove if (File::exist($thumb) || File::exist($full)) { File::remove($thumb); File::remove($full); } else { throw new NativeException('Image is not founded'); } return json_encode(['status' => 1, 'msg' => 'Image is removed']); }