/** * Uploads a new file for the given FileField instance. * * @param string $name EAV attribute name * @throws \Cake\Network\Exception\NotFoundException When invalid slug is given, * or when upload process could not be completed */ public function upload($name) { $instance = $this->_getInstance($name); require_once Plugin::classPath('Field') . 'Lib/class.upload.php'; $uploader = new \upload($this->request->data['Filedata']); if (!empty($instance->settings['extensions'])) { $exts = explode(',', $instance->settings['extensions']); $exts = array_map('trim', $exts); $exts = array_map('strtolower', $exts); if (!in_array(strtolower($uploader->file_src_name_ext), $exts)) { $this->_error(__d('field', 'Invalid file extension.'), 501); } } $response = ''; $uploader->file_overwrite = false; $folder = normalizePath(WWW_ROOT . "/files/{$instance->settings['upload_folder']}/"); $url = normalizePath("/files/{$instance->settings['upload_folder']}/", '/'); $uploader->process($folder); if ($uploader->processed) { $response = json_encode(['file_url' => Router::url($url . $uploader->file_dst_name, true), 'file_size' => FileToolbox::bytesToSize($uploader->file_src_size), 'file_name' => $uploader->file_dst_name, 'mime_icon' => FileToolbox::fileIcon($uploader->file_src_mime)]); } else { $this->_error(__d('field', 'File upload error, details: {0}', $uploader->error), 502); } $this->viewBuilder()->layout('ajax'); $this->title(__d('field', 'Upload File')); $this->set(compact('response')); }
/** * First step of the installation process. * * User must select the language they want to use for the installation process. * * @return void */ public function language() { $languages = ['en_US' => ['url' => '/installer/startup/requirements?locale=en_US', 'welcome' => 'Welcome to QuickAppsCMS', 'action' => 'Click here to install in English']]; $Folder = new Folder(Plugin::classPath('Installer') . 'Locale'); foreach ($Folder->read(false, true, true)[0] as $path) { $code = basename($path); $file = $path . '/installer.po'; if (is_readable($file)) { I18n::locale($code); // trick for __d() $languages[$code] = ['url' => "/installer/startup/requirements?locale={$code}", 'welcome' => __d('installer', 'Welcome to QuickAppsCMS'), 'action' => __d('installer', 'Click here to install in English')]; } } I18n::locale('en_US'); $this->title('Welcome to QuickAppsCMS'); $this->set('languages', $languages); $this->_step(); }
/** * Extracts the current ZIP package. * * @param string $file Full path to the ZIP package * @return bool True on success */ protected function _unzip($file) { include_once Plugin::classPath('Installer') . 'Lib/pclzip.lib.php'; $File = new File($file); $to = normalizePath($File->folder()->pwd() . '/' . $File->name() . '_unzip/'); if (is_readable($to)) { $folder = new Folder($to); $folder->delete(); } else { $folder = new Folder($to, true); } $PclZip = new \PclZip($file); $PclZip->delete(PCLZIP_OPT_BY_EREG, '/__MACOSX/'); $PclZip->delete(PCLZIP_OPT_BY_EREG, '/\\.DS_Store$/'); if ($PclZip->extract(PCLZIP_OPT_PATH, $to)) { list($directories, $files) = $folder->read(false, false, true); if (count($directories) === 1 && empty($files)) { $container = new Folder($directories[0]); $container->move(['to' => $to]); } $this->_workingDir = $to; return true; } $this->err(__d('installer', 'Unzip error: {0}', [$PclZip->errorInfo(true)])); return false; }
/** * Calculates comment's status using akismet. * * @param array $data Comment's data to be validated by Akismet * @return string Filtered comment's status */ protected function _akismetStatus($data) { require_once Plugin::classPath('Comment') . 'Lib/Akismet.php'; try { $akismet = new \Akismet(Router::url('/'), $this->config('settings.akismet_key')); if (!empty($data['author_name'])) { $akismet->setCommentAuthor($data['author_name']); } if (!empty($data['author_email'])) { $akismet->setCommentAuthorEmail($data['author_email']); } if (!empty($data['author_web'])) { $akismet->setCommentAuthorURL($data['author_web']); } if (!empty($data['body'])) { $akismet->setCommentContent($data['body']); } if ($akismet->isCommentSpam()) { return 'spam'; } } catch (\Exception $ex) { return 'pending'; } return $data['status']; }
/** * Renders a nested menu. * * This methods renders a HTML menu using a `threaded` result set: * * ```php * // In controller: * $this->set('links', $this->Links->find('threaded')); * * // In view: * echo $this->Menu->render('links'); * ``` * * ### Options: * * You can pass an associative array `key => value`. Any `key` not in * `$_defaultConfig` will be treated as an additional attribute for the top * level UL (root). If `key` is in `$_defaultConfig` it will temporally * overwrite default configuration parameters, it will be restored to its * default values after rendering completes: * * - `formatter`: Callable method used when formating each item. * - `activeClass`: CSS class to use when an item is active (its URL matches current URL). * - `firstItemClass`: CSS class for the first item. * - `lastItemClass`: CSS class for the last item. * - `hasChildrenClass`: CSS class to use when an item has children. * - `split`: Split menu into multiple root menus (multiple UL's) * - `templates`: The templates you want to use for this menu. Any templates * will be merged on top of the already loaded templates. This option can * either be a filename in App/config that contains the templates you want * to load, or an array of templates to use. * * You can also pass a callable function as second argument which will be * used as formatter: * * ```php * echo $this->Menu->render($links, function ($link, $info) { * // render $item here * }); * ``` * * Formatters receives two arguments, the item being rendered as first argument * and information abut the item (has children, depth, etc) as second. * * You can pass the ID or slug of a menu as fist argument to render that menu's * links: * * ```php * echo $this->Menu->render('management'); * * // OR * * echo $this->Menu->render(1); * ``` * * @param int|string|array|\Cake\Collection\Collection $items Nested items * to render, given as a query result set or as an array list. Or an integer as * menu ID in DB to render, or a string as menu Slug in DB to render. * @param callable|array $config An array of HTML attributes and options as * described above or a callable function to use as `formatter` * @return string HTML * @throws \Cake\Error\FatalErrorException When loop invocation is detected, * that is, when "render()" method is invoked within a callable method when * rendering menus. */ public function render($items, $config = []) { if ($this->_rendering) { throw new FatalErrorException(__d('menu', 'Loop detected, MenuHelper already rendering.')); } $items = $this->_prepareItems($items); if (empty($items)) { return ''; } list($config, $attrs) = $this->_prepareOptions($config); $this->_rendering = true; $this->countItems($items); $this->config($config); if ($this->config('breadcrumbGuessing')) { $this->Link->config(['breadcrumbGuessing' => $this->config('breadcrumbGuessing')]); } $out = ''; if (intval($this->config('split')) > 1) { $out .= $this->_renderPart($items, $config, $attrs); } else { $out .= $this->formatTemplate('root', ['attrs' => $this->templater()->formatAttributes($attrs), 'content' => $this->_render($items)]); } if ($this->config('beautify')) { include_once Plugin::classPath('Menu') . 'Lib/htmLawed.php'; $tidy = is_bool($this->config('beautify')) ? '1t0n' : $this->config('beautify'); $out = htmLawed($out, compact('tidy')); } $this->_clear(); return $out; }
/** * {@inheritDoc} * * Workaround patch that allows plugins and themes provide their own independent * "settings.ctp" files so themes won't "override" plugin element (as themes are * actually plugins and may have their own "settings.ctp"). * * The same goes for "help.ctp" template files. So themes and plugins can * provide help information. */ protected function _getElementFileName($name, $pluginCheck = true) { list($plugin, $element) = $this->pluginSplit($name, $pluginCheck); if ($plugin && ($element === 'settings' || strpos($element, 'Help/help') !== false)) { return Plugin::classPath($plugin) . "Template/Element/{$element}{$this->_ext}"; } return parent::_getElementFileName($name, $pluginCheck); }
/** * Fallback for template location when extending Comment UI API. * * If controller tries to render an unexisting template under its Template * directory, then we try to find that view under `Comment/Template/CommentUI` * directory. * * ### Example: * * Suppose you are using this trait to manage comments attached to `Persons` * entities. You would probably have a `Person` plugin and a `clean` controller * as follow: * * // http://example.com/admin/person/comments_manager * Person\Controller\CommentsManagerController::index() * * The above controller action will try to render * `/plugins/Person/Template/CommentsManager/index.ctp`. But if does not exists * then `<QuickAppsCorePath>/plugins/Comment/Template/CommentUI/index.ctp` will * be used instead. * * Of course you may create your own template and skip this fallback functionality. * * @param \Cake\Event\Event $event the event instance. * @return void */ public function beforeRender(Event $event) { $plugin = (string) Inflector::camelize($event->subject()->request->params['plugin']); $controller = Inflector::camelize($event->subject()->request->params['controller']); $action = Inflector::underscore($event->subject()->request->params['action']); $prefix = ''; if (!empty($event->subject()->request->params['prefix'])) { $prefix = Inflector::camelize($event->subject()->request->params['prefix']) . '/'; } $templatePath = Plugin::classPath($plugin) . "Template/{$prefix}{$controller}/{$action}.ctp"; if (!is_readable($templatePath)) { $alternativeTemplatePath = Plugin::classPath('Comment') . 'Template/CommentUI'; if (is_readable("{$alternativeTemplatePath}/{$action}.ctp")) { $this->plugin = 'Comment'; $this->viewBuilder()->templatePath('CommentUI'); } } parent::beforeRender($event); }