/** * beforeCallback. * * This callback adds the CSS/JS for the localeswitcher on the backend * and checks that we are on a valid locale when on the frontend */ public function beforeCallback(Request $request) { $routeParams = $request->get('_route_params'); if ($this->app['config']->getWhichEnd() == 'backend') { if (array_key_exists('contenttypeslug', $routeParams)) { $this->addCss('assets/css/field_locale.css'); if (!empty($routeParams['id'])) { $this->addJavascript('assets/js/field_locale.js', array('late' => true)); } } } else { if (isset($routeParams['_locale'])) { $this->app['menu'] = $this->app->share(function ($app) { $builder = new Menu\LocalizedMenuBuilder($app); return $builder; }); $locales = $this->app['config']->get('general/locales'); foreach ($locales as $isolocale => $locale) { if ($locale['slug'] == $routeParams['_locale']) { $foundLocale = $isolocale; } } if (isset($foundLocale)) { setlocale(LC_ALL, $foundLocale); $this->app['config']->set('general/locale', $foundLocale); } else { $routeParams['_locale'] = reset($locales)['slug']; return $this->app->redirect(Lib::path($request->get('_route'), $routeParams)); } } } }
/** * Adds all resources that belong to a locale. * * @param Application $app * @param string $locale */ public static function addResources(Application $app, $locale) { // Directories to look for translation file(s) $transDirs = array_unique([$app['resources']->getPath("app/resources/translations/{$locale}"), $app['resources']->getPath("root/app/resources/translations/{$locale}")]); $needsSecondPass = true; foreach ($transDirs as $transDir) { if (!is_dir($transDir) || !is_readable($transDir)) { continue; } $iterator = new \DirectoryIterator($transDir); /** * @var \SplFileInfo $fileInfo */ foreach ($iterator as $fileInfo) { $ext = Lib::getExtension((string) $fileInfo); if (!$fileInfo->isFile() || !in_array($ext, ['yml', 'xlf'], true)) { continue; } list($domain) = explode('.', $fileInfo->getFilename()); $app['translator']->addResource($ext, $fileInfo->getRealPath(), $locale, $domain); $needsSecondPass = false; } } if ($needsSecondPass && strlen($locale) === 5) { static::addResources($app, substr($locale, 0, 2)); } }
public function patchTranslationPath() { # workaround for Bolt 2.2 - fix in master (3.0), see #3553 and #3800 // $app->before(function() use ($app) { // $path = $app['resources']->getPath('root/app/resources/translations'); // $app['translator']->addResource('yml', $path.'/contenttypes.de_DE.yml', 'de_DE', 'contenttypes'); // }); if ("Bolt\\Configuration\\Composer" != get_class($this->app['resources'])) { return; } // $versionParser = new \Composer\Package\Version\VersionParser(); // $version = $versionParser->parseConstraints($app['bolt_version']); // print_r($version); // Directory to look for translation file(s) $transDir = $this->app['resources']->getPath('root/app/resources/translations/' . $this->app['locale']); if (is_dir($transDir)) { $iterator = new \DirectoryIterator($transDir); /** * @var \SplFileInfo $fileInfo */ foreach ($iterator as $fileInfo) { $ext = Lib::getExtension((string) $fileInfo); if (!$fileInfo->isFile() || !in_array($ext, array('yml', 'xlf'))) { continue; } list($domain) = explode('.', $fileInfo->getFilename()); $this->app['translator']->addResource($ext, $transDir . '/' . $fileInfo->getFilename(), $this->app['locale'], $domain); } } }
public function handle($path) { $files = []; $folders = []; $list = $this->filesystem->listContents($path); $ignored = ['.', '..', '.DS_Store', '.gitignore', '.htaccess']; foreach ($list as $entry) { if (in_array($entry['basename'], $ignored)) { continue; } if (!$this->filesystem->authorized($entry['path'])) { continue; } if ($entry['type'] === 'file') { try { $url = $this->filesystem->url($entry['path']); } catch (\Exception $e) { $url = $entry['path']; } // Ugh, for some reason the foldername for the theme is included twice. Why? // For now we 'fix' this with an ugly hack, replacing it. :-/ // TODO: dig into Filesystem and figure out why this happens. $pathsegments = explode('/', $entry['path']); if (!empty($pathsegments[0])) { $url = str_replace('/' . $pathsegments[0] . '/' . $pathsegments[0] . '/', '/' . $pathsegments[0] . '/', $url); } $files[$entry['path']] = ['path' => $entry['dirname'], 'filename' => $entry['basename'], 'newpath' => $entry['path'], 'relativepath' => $entry['path'], 'writable' => true, 'readable' => false, 'type' => isset($entry['extension']) ? $entry['extension'] : '', 'filesize' => Lib::formatFilesize($entry['size']), 'modified' => date("Y/m/d H:i:s", $entry['timestamp']), 'permissions' => 'public', 'url' => $url]; /* **** Extra checks for files that can be resolved via PHP urlopen functions **** */ try { $files[$entry['path']]['permissions'] = $this->filesystem->getVisibility($entry['path']); } catch (\Exception $e) { // Computer says "No!" } $fullfilename = $this->filesystem->getAdapter()->applyPathPrefix($entry['path']); if (is_readable($fullfilename)) { $files[$entry['path']]['readable'] = true; if (!empty($entry['extension']) && in_array($entry['extension'], ['gif', 'jpg', 'png', 'jpeg'])) { $size = getimagesize($fullfilename); $files[$entry['path']]['imagesize'] = sprintf("%s × %s", $size[0], $size[1]); } $files[$entry['path']]['permissions'] = util::full_permissions($fullfilename); } } if ($entry['type'] == 'dir') { $folders[$entry['path']] = ['path' => $entry['dirname'], 'foldername' => $entry['basename'], 'newpath' => $entry['path'], 'modified' => date("Y/m/d H:i:s", $entry['timestamp']), 'writable' => true]; $fullfilename = $this->filesystem->getAdapter()->applyPathPrefix($entry['path']); /* **** Extra checks for files that can be resolved via PHP urlopen functions **** */ if (is_readable($fullfilename)) { if (!is_writable($fullfilename)) { $folders[$entry['path']]['writable'] = false; } } } } ksort($files); ksort($folders); return [$files, $folders]; }
/** * Collect the date for the Toolbar item. * * @param Request $request * @param Response $response * @param \Exception $exception */ public function collect(Request $request, Response $response, \Exception $exception = null) { $this->data = array('version' => $this->app->getVersion(false), 'name' => $this->app['bolt_name'], 'fullversion' => 'Version: ' . $this->app->getVersion(true), 'payoff' => 'Sophisticated, lightweight & simple CMS', 'aboutlink' => sprintf("<a href=\"%s\">%s</a>", Lib::path('about'), 'About'), 'branding' => null, 'editlink' => null, 'edittitle' => null); if ($this->app['config']->get('general/branding/provided_by/0')) { $this->data['branding'] = sprintf("%s <a href=\"mailto:%s\">%s</a>", Trans::__('Provided by:'), $this->app['config']->get('general/branding/provided_by/0'), $this->app['config']->get('general/branding/provided_by/1')); } if (!empty($this->app['editlink'])) { $this->data['editlink'] = $this->app['editlink']; $this->data['edittitle'] = $this->app['edittitle']; } }
/** * Checks if a given file is acceptable for upload. */ public function allowedUpload($originalFilename) { // no UNIX-hidden files if ($originalFilename[0] === '.') { return false; } // only whitelisted extensions $extension = strtolower(Lib::getExtension($originalFilename)); $allowedExtensions = $this->getAllowedUploadExtensions(); return in_array($extension, $allowedExtensions); }
/** * Helper function to make a path to an image. * * @param string $filename Target filename * @param string|integer $width Target width * @param string|integer $height Target height * @param string $crop String identifier for cropped images * * @return string Image path */ public function image($filename, $width = '', $height = '', $crop = '') { if ($width != '' || $height != '') { // You don't want the image, you just want a thumbnail. return $this->thumbnail($filename, $width, $height, $crop); } // After v1.5.1 we store image data as an array if (is_array($filename)) { $filename = isset($filename['filename']) ? $filename['filename'] : $filename['file']; } $image = sprintf('%sfiles/%s', $this->app['paths']['root'], Lib::safeFilename($filename)); return $image; }
/** * Helper function to make a path to an image. * * @param string $filename Target filename * @param string|integer $width Target width * @param string|integer $height Target height * @param string $crop String identifier for cropped images * * @return string Image path */ public function image($filename, $width = null, $height = null, $crop = null) { if ($width || $height) { // You don't want the image, you just want a thumbnail. return $this->thumbnail($filename, $width, $height, $crop); } // After v1.5.1 we store image data as an array if (is_array($filename)) { $filename = isset($filename['filename']) ? $filename['filename'] : $filename['file']; } $image = sprintf('%s%s', $this->app['resources']->getUrl('files'), Lib::safeFilename($filename)); return $image; }
public function record(\Silex\Application $app, $contenttypeslug, $slug = '') { $contenttype = $app['storage']->getContentType($contenttypeslug); // If the contenttype is 'viewless', don't show the record page. if (isset($contenttype['viewless']) && $contenttype['viewless'] === true) { return $app->abort(Response::HTTP_NOT_FOUND, "Page {$contenttypeslug}/{$slug} not found."); } // Perhaps we don't have a slug. Let's see if we can pick up the 'id', instead. if (empty($slug)) { $slug = $app['request']->get('id'); } $slug = $app['slugify']->slugify($slug); // First, try to get it by slug. $content = $app['storage']->getContent($contenttype['slug'], array('slug' => $slug, 'returnsingle' => true, 'log_not_found' => !is_numeric($slug))); if (!$content && !is_numeric($slug)) { // And otherwise try getting it by translated slugs $match = $this->matchTranslatedSlug($app, $contenttype['slug'], $slug); if (!empty($match)) { $content = $app['storage']->getContent($contenttype['slug'], array('id' => $match['content_type_id'], 'returnsingle' => true)); } } if (!$content && is_numeric($slug)) { // And otherwise try getting it by ID $content = $app['storage']->getContent($contenttype['slug'], array('id' => $slug, 'returnsingle' => true)); } // No content, no page! if (!$content) { return $app->abort(Response::HTTP_NOT_FOUND, "Page {$contenttypeslug}/{$slug} not found."); } // Then, select which template to use, based on our 'cascading templates rules' $template = $app['templatechooser']->record($content); $paths = $app['resources']->getPaths(); // Setting the canonical URL. if ($content->isHome() && $template == $app['config']->get('general/homepage_template')) { $app['resources']->setUrl('canonicalurl', $paths['rooturl']); } else { $url = $paths['canonical'] . $content->link(); $app['resources']->setUrl('canonicalurl', $url); } // Setting the editlink $app['editlink'] = Lib::path('editcontent', array('contenttypeslug' => $contenttype['slug'], 'id' => $content->id)); $app['edittitle'] = $content->getTitle(); // Make sure we can also access it as {{ page.title }} for pages, etc. We set these in the global scope, // So that they're also available in menu's and templates rendered by extensions. $app['twig']->addGlobal('record', $content); $app['twig']->addGlobal($contenttype['singular_slug'], $content); // Render the template and return. return $this->render($app, $template, $content->getTitle()); }
/** * Updates a menu item to have at least a 'link' key. * * @param array $item * * @return array Keys 'link' and possibly 'label', 'title' and 'path' */ private function menuHelper($item) { // recurse into submenu's if (isset($item['submenu']) && is_array($item['submenu'])) { $item['submenu'] = $this->menuHelper($item['submenu']); } if (isset($item['route'])) { $param = !empty($item['param']) ?: array(); $add = !empty($item['add']) ?: ''; $item['link'] = Lib::path($item['route'], $param, $add); } elseif (isset($item['path'])) { $item = $this->resolvePathToContent($item); } return $item; }
/** * Middleware function to check whether a user is logged on. * * @param Request $request * @param \Silex\Application $app * * @return null|\Symfony\Component\HttpFoundation\RedirectResponse */ public function before(Request $request, Silex\Application $app) { // This disallows extensions from adding any extra snippets to the output if ($request->get("_route") !== 'extend') { $app['htmlsnippets'] = false; } // Start the 'stopwatch' for the profiler. $app['stopwatch']->start('bolt.backend.before'); // Most of the 'check if user is allowed' happens here: match the current route to the 'allowed' settings. if (!$app['users']->isAllowed('extensions')) { $app['session']->getFlashBag()->add('error', Trans::__('You do not have the right privileges to view that page.')); return Lib::redirect('dashboard'); } // Stop the 'stopwatch' for the profiler. $app['stopwatch']->stop('bolt.backend.before'); return null; }
/** * Collect information from Twig. * * @param Request $request The Request Object * @param Response $response The Response Object * @param \Exception $exception The Exception */ public function collect(Request $request, Response $response, \Exception $exception = null) { $filters = array(); $tests = array(); $extensions = array(); $functions = array(); foreach ($this->getTwig()->getExtensions() as $extensionName => $extension) { /** @var $extension \Twig_ExtensionInterface */ $extensions[] = array('name' => $extensionName, 'class' => get_class($extension)); foreach ($extension->getFilters() as $filterName => $filter) { if ($filter instanceof \Twig_FilterInterface) { $call = $filter->compile(); if (is_array($call) && is_callable($call)) { $call = 'Method ' . $call[1] . ' of an object ' . get_class($call[0]); } } elseif ($filter instanceof \Twig_SimpleFilter) { $call = $filter->getName(); } else { continue; } $filters[] = array('name' => $filterName, 'extension' => $extensionName, 'call' => $call); } foreach ($extension->getTests() as $testName => $test) { if ($test instanceof \Twig_TestInterface) { $call = $test->compile(); } elseif ($test instanceof \Twig_SimpleTest) { $call = $test->getName(); } else { continue; } $tests[] = array('name' => $testName, 'extension' => $extensionName, 'call' => $call); } foreach ($extension->getFunctions() as $functionName => $function) { if ($function instanceof \Twig_FunctionInterface) { $call = $function->compile(); } elseif ($function instanceof \Twig_SimpleFunction) { $call = $function->getName(); } else { continue; } $functions[] = array('name' => $functionName, 'extension' => $extensionName, 'call' => $call); } } $this->data = array('extensions' => $extensions, 'tests' => $tests, 'filters' => $filters, 'functions' => $functions, 'templates' => Lib::parseTwigTemplates($this->app['twig.loader']), 'templatechosen' => $this->getTrackedValue('templatechosen'), 'templateerror' => $this->getTrackedValue('templateerror')); }
/** * Adds all resources that belong to a locale. * * @param Application $app * @param string $locale */ public static function addResources(Application $app, $locale) { // Directory to look for translation file(s) $transDir = $app['resources']->getPath('app/resources/translations/' . $locale); if (is_dir($transDir)) { $iterator = new \DirectoryIterator($transDir); /** * @var \SplFileInfo $fileInfo */ foreach ($iterator as $fileInfo) { $ext = Lib::getExtension((string) $fileInfo); if (!$fileInfo->isFile() || !in_array($ext, ['yml', 'xlf'])) { continue; } list($domain) = explode('.', $fileInfo->getFilename()); $app['translator']->addResource($ext, $fileInfo->getRealPath(), $locale, $domain); } } elseif (strlen($locale) == 5) { static::addResources($app, substr($locale, 0, 2)); } }
/** * File editor. * * @param Request $request The Symfony Request * @param string $namespace The filesystem namespace * @param string $file The file path * * @return \Bolt\Response\BoltResponse|\Symfony\Component\HttpFoundation\RedirectResponse */ public function edit(Request $request, $namespace, $file) { if ($namespace === 'app' && dirname($file) === 'config') { // Special case: If requesting one of the major config files, like contenttypes.yml, set the path to the // correct dir, which might be 'app/config', but it might be something else. $namespace = 'config'; } /** @var FilesystemInterface $filesystem */ $filesystem = $this->filesystem()->getFilesystem($namespace); if (!$filesystem->authorized($file)) { $error = Trans::__('general.phrase.access-denied-permissions-edit-file', ['%s' => $file]); $this->abort(Response::HTTP_FORBIDDEN, $error); } try { /** @var File $file */ $file = $filesystem->get($file); $type = Lib::getExtension($file->getPath()); $data = ['contents' => $file->read()]; } catch (FileNotFoundException $e) { $error = Trans::__('general.phrase.file-not-exist', ['%s' => $file->getPath()]); $this->abort(Response::HTTP_NOT_FOUND, $error); } catch (IOException $e) { $error = Trans::__('general.phrase.file-not-readable', ['%s' => $file->getPath()]); $this->abort(Response::HTTP_NOT_FOUND, $error); } /** @var Form $form */ $form = $this->createFormBuilder(FormType::class, $data)->add('contents', TextareaType::class)->getForm(); // Handle the POST and check if it's valid. if ($request->isMethod('POST')) { return $this->handleEdit($request, $form, $file, $type); } // For 'related' files we might need to keep track of the current dirname on top of the namespace. if (dirname($file->getPath()) !== '') { $additionalpath = dirname($file->getPath()) . '/'; } else { $additionalpath = ''; } $context = ['form' => $form->createView(), 'filetype' => $type, 'file' => $file->getPath(), 'basename' => basename($file->getPath()), 'pathsegments' => $this->getPathSegments(dirname($file->getPath())), 'additionalpath' => $additionalpath, 'namespace' => $namespace, 'write_allowed' => true, 'filegroup' => $this->getFileGroup($filesystem, $file), 'datechanged' => date_format(new \DateTime('@' . $file->getTimestamp()), 'c')]; return $this->render('@bolt/editfile/editfile.twig', $context); }
/** * Show the password form. If the visitor gives the correct password, they * are redirected to the page they came from, if any. * * @return \Twig_Markup */ public function passwordForm() { // Set up the form. $form = $this->app['form.factory']->createBuilder('form'); if ($this->config['password_only'] == false) { $form->add('username', 'text'); } $form->add('password', 'password'); $form = $form->getForm(); if ($this->app['request']->getMethod() == 'POST') { $form->bind($this->app['request']); $data = $form->getData(); if ($form->isValid() && $this->checkLogin($data)) { // Set the session var, so we're authenticated.. $this->app['session']->set('passwordprotect', 1); $this->app['session']->set('passwordprotect_name', $this->checkLogin($data)); // Print a friendly message.. printf("<p class='message-correct'>%s</p>", $this->config['message_correct']); $returnto = $this->app['request']->get('returnto'); // And back we go, to the page we originally came from.. if (!empty($returnto)) { Lib::simpleredirect($returnto); die; } } else { // Remove the session var, so we can test 'logging off'.. $this->app['session']->remove('passwordprotect'); $this->app['session']->remove('passwordprotect_name'); // Print a friendly message.. if (!empty($data['password'])) { printf("<p class='message-wrong'>%s</p>", $this->config['message_wrong']); } } } // Render the form, and show it it the visitor. $this->app['twig.loader.filesystem']->addPath(__DIR__); $html = $this->app['twig']->render('assets/passwordform.twig', array('form' => $form->createView())); return new \Twig_Markup($html, 'UTF-8'); }
/** * File editor. * * @param Request $request The Symfony Request * @param string $namespace The filesystem namespace * @param string $file The file path * * @return \Bolt\Response\BoltResponse|\Symfony\Component\HttpFoundation\RedirectResponse */ public function edit(Request $request, $namespace, $file) { if ($namespace === 'app' && dirname($file) === 'config') { // Special case: If requesting one of the major config files, like contenttypes.yml, set the path to the // correct dir, which might be 'app/config', but it might be something else. $namespace = 'config'; } /** @var FilesystemInterface $filesystem */ $filesystem = $this->filesystem()->getFilesystem($namespace); if (!$filesystem->authorized($file)) { $error = Trans::__("You don't have correct permissions to edit the file '%s'.", ['%s' => $file]); $this->abort(Response::HTTP_FORBIDDEN, $error); } /** @var File $file */ $file = $filesystem->get($file); $type = Lib::getExtension($file->getPath()); $contents = null; if (!$file->exists() || !($contents = $file->read())) { $error = Trans::__("The file '%s' doesn't exist, or is not readable.", ['%s' => $file->getPath()]); $this->abort(Response::HTTP_NOT_FOUND, $error); } $writeallowed = $this->isWriteable($file); $data = ['contents' => $contents]; /** @var Form $form */ $form = $this->createFormBuilder('form', $data)->add('contents', 'textarea')->getForm(); // Handle the POST and check if it's valid. if ($request->isMethod('POST')) { return $this->handleEdit($request, $form, $file, $type); } // For 'related' files we might need to keep track of the current dirname on top of the namespace. if (dirname($file->getPath()) !== '') { $additionalpath = dirname($file->getPath()) . '/'; } else { $additionalpath = ''; } $context = ['form' => $form->createView(), 'filetype' => $type, 'file' => $file->getPath(), 'basename' => basename($file->getPath()), 'pathsegments' => $this->getPathSegments(dirname($file->getPath())), 'additionalpath' => $additionalpath, 'namespace' => $namespace, 'write_allowed' => $writeallowed, 'filegroup' => $this->getFileGroup($filesystem, $file), 'datechanged' => date_format(new \DateTime('@' . $file->getTimestamp()), 'c')]; return $this->render('@bolt/editfile/editfile.twig', $context); }
/** * Set a Contenttype record's values. * * @param array $values */ public function setValues(array $values) { // Since Bolt 1.4, we use 'ownerid' instead of 'username' in the DB tables. If we get an array that has an // empty 'ownerid', attempt to set it from the 'username'. In $this->setValue the user will be set, regardless // of ownerid is an 'id' or a 'username'. if (empty($values['ownerid']) && !empty($values['username'])) { $values['ownerid'] = $values['username']; unset($values['username']); } foreach ($values as $key => $value) { if ($key !== 'templatefields') { $this->setValue($key, $value); } } // If default status is set in contentttype. if (empty($this->values['status']) && isset($this->contenttype['default_status'])) { $this->values['status'] = $this->contenttype['default_status']; } $serializedFieldTypes = ['geolocation', 'imagelist', 'image', 'file', 'filelist', 'video', 'select', 'templateselect', 'checkbox']; // Check if the values need to be unserialized, and pre-processed. foreach ($this->values as $key => $value) { if (in_array($this->fieldtype($key), $serializedFieldTypes) || $key == 'templatefields') { if (!empty($value) && is_string($value) && (substr($value, 0, 2) == "a:" || $value[0] === '[' || $value[0] === '{')) { try { $unserdata = Lib::smartUnserialize($value); } catch (\Exception $e) { $unserdata = false; } if ($unserdata !== false) { $this->values[$key] = $unserdata; } } } if ($this->fieldtype($key) == "video" && is_array($this->values[$key]) && !empty($this->values[$key]['url'])) { $video = $this->values[$key]; // update the HTML, according to given width and height if (!empty($video['width']) && !empty($video['height'])) { $video['html'] = preg_replace("/width=(['\"])([0-9]+)(['\"])/i", 'width=${1}' . $video['width'] . '${3}', $video['html']); $video['html'] = preg_replace("/height=(['\"])([0-9]+)(['\"])/i", 'height=${1}' . $video['height'] . '${3}', $video['html']); } $responsiveclass = "responsive-video"; // See if it's widescreen or not. if (!empty($video['height']) && $video['width'] / $video['height'] > 1.76) { $responsiveclass .= " widescreen"; } if (strpos($video['url'], "vimeo") !== false) { $responsiveclass .= " vimeo"; } $video['responsive'] = sprintf('<div class="%s">%s</div>', $responsiveclass, $video['html']); // Mark them up as Twig_Markup. $video['html'] = new \Twig_Markup($video['html'], 'UTF-8'); $video['responsive'] = new \Twig_Markup($video['responsive'], 'UTF-8'); $this->values[$key] = $video; } if ($this->fieldtype($key) == "date" || $this->fieldtype($key) == "datetime") { if ($this->values[$key] === "") { $this->values[$key] = null; } } } // Template fields need to be done last // As the template has to have been selected if ($this->isRootType) { if (empty($values['templatefields'])) { $this->setValue('templatefields', []); } else { $this->setValue('templatefields', $values['templatefields']); } } }
/** * Middleware function to check whether a user is logged on. * * @return null|\Symfony\Component\HttpFoundation\RedirectResponse */ public function before(Request $request, Application $app) { // Start the 'stopwatch' for the profiler. $app['stopwatch']->start('bolt.backend.before'); // If there's no active session, don't do anything. if (!$app['users']->isValidSession()) { $app->abort(Response::HTTP_NOT_FOUND, 'You must be logged in to use this.'); } if (!$app['users']->isAllowed("files:uploads")) { $app['session']->getFlashBag()->add('error', Trans::__('You do not have the right privileges to upload.')); return Lib::redirect('dashboard'); } // Stop the 'stopwatch' for the profiler. $app['stopwatch']->stop('bolt.backend.before'); return null; }
/** * Creates a link to EDIT this record, if the user is logged in. * * @return string */ public function editlink() { $perm = "contenttype:" . $this->contenttype['slug'] . ":edit:" . $this->id; if ($this->app['users']->isAllowed($perm)) { return Lib::path('editcontent', array('contenttypeslug' => $this->contenttype['slug'], 'id' => $this->id)); } else { return false; } }
/** * Stub for edit_post_link. */ function edit_post_link($text = null, $before = '', $after = '', $id = 0) { global $post, $currentuser; if (!is_object($post) || empty($currentuser['username'])) { return; } $path = \Bolt\Library::path('editcontent', ['contenttypeslug' => $post->contenttype['slug'], 'id' => $post['id']]); if (null === $text) { $text = __('Edit This'); } $link = '<a class="post-edit-link" href="' . $path . '">' . $text . '</a>'; /** * Filter the post edit link anchor tag. * * @since 2.3.0 * * @param string $link Anchor tag for the edit link. * @param int $post_id Post ID. * @param string $text Anchor text. */ echo $before . apply_filters('edit_post_link', $link, $post['id'], $text) . $after; }
public function slugTreeRecord($slug) { // Add snippets, since this is a Frontend route. $this->app['htmlsnippets'] = true; if (strripos($slug, '/')) { // find the last "/"" in the slug //dump($slug); // dump($this->app['config']); // dump($this->app['config']->get('data/contenttypes')); // dump($this->app['config']->get('general/homepage_template')); // dump(strripos($slug, '/') == strlen($slug)); // dump(strripos($slug, '/')); // dump(strlen($slug)); $slug = rtrim($slug, '/'); if (in_array($slug, array('blogs', 'locations', 'structures', 'pages', 'blogposts', 'jobs', 'events', 'persons', 'network', 'publications', 'pressreleases', 'projects', 'taskforces', 'homepage', 'footers'))) { switch ($slug) { case 'blogs': //dump('redirect blogs'); \Bolt\Library::simpleredirect('/blogposts'); die; break; default: \Bolt\Library::simpleredirect('/' . $slug); die; break; } } } // $slug = \Bolt\Helpers\String::slug($slug, -1); $slug = $this->app['slugify']->slugify($slug); $contenttype = $this->getContenttypeBySlug($slug, true); $frontend = new Bolt\Controllers\Frontend(); return $frontend->record($this->app, $contenttype, $slug); }
/** * Check if a user is logged in, and has the proper required permission. If * not, we redirect the user to the dashboard. * * @param string $permission * * @return bool True if permission allowed */ public function requireUserPermission($permission = 'dashboard') { if ($this->app['users']->isAllowed($permission)) { return true; } else { Lib::simpleredirect($this->app['config']->get('general/branding/path')); return false; } }
/** * Redirect the browser to another page. * * @param boolean $safe * * @return string */ public function redirect($path, $safe) { // Nope! We're not allowing user-supplied content to issue redirects. if ($safe) { return null; } Lib::simpleredirect($path); return ''; }
/** * Return a list with the current stacked items. Add some relevant info to each item, * and also check if the item is present and readable. * * @param integer $count * @param string $typefilter * * @return array */ public function listitems($count = 100, $typefilter = '') { $this->initialize(); // Make sure typefilter is an array, if passed something like "image, document" if (!empty($typefilter)) { $typefilter = array_map('trim', explode(',', $typefilter)); } // Our basepaths for all files that can be on the stack: 'files' and 'theme'. $filespath = $this->app['resources']->getPath('filespath'); $themepath = $this->app['resources']->getPath('themebasepath'); $items = $this->items; $list = []; foreach ($items as $item) { $extension = strtolower(Lib::getExtension($item)); if (in_array($extension, $this->imageTypes)) { $type = 'image'; } elseif (in_array($extension, $this->documentTypes)) { $type = 'document'; } else { $type = 'other'; } // Skip this one, if it doesn't match the type. if (!empty($typefilter) && !in_array($type, $typefilter)) { continue; } // Figure out the full path, based on the two possible locations. $fullpath = ''; if (is_readable(str_replace('files/files/', 'files/', $filespath . '/' . $item))) { $fullpath = str_replace('files/files/', 'files/', $filespath . '/' . $item); } elseif (is_readable($themepath . '/' . $item)) { $fullpath = $themepath . '/' . $item; } // No dice! skip this one. if (empty($fullpath)) { continue; } $thisitem = ['basename' => basename($item), 'extension' => $extension, 'filepath' => str_replace('files/', '', $item), 'type' => $type, 'writable' => is_writable($fullpath), 'readable' => is_readable($fullpath), 'filesize' => Lib::formatFilesize(filesize($fullpath)), 'modified' => date('Y/m/d H:i:s', filemtime($fullpath)), 'permissions' => util::full_permissions($fullpath)]; $thisitem['info'] = sprintf('%s: <code>%s</code><br>%s: %s<br>%s: %s<br>%s: <code>%s</code>', Trans::__('Path'), $thisitem['filepath'], Trans::__('Filesize'), $thisitem['filesize'], Trans::__('Modified'), $thisitem['modified'], Trans::__('Permissions'), $thisitem['permissions']); if ($type == 'image') { $size = getimagesize($fullpath); $thisitem['imagesize'] = sprintf('%s × %s', $size[0], $size[1]); $thisitem['info'] .= sprintf('<br>%s: %s × %s px', Trans::__('Size'), $size[0], $size[1]); } //add it to our list. $list[] = $thisitem; } $list = array_slice($list, 0, $count); return $list; }
/** * Cache built configuration parameters. */ protected function saveCache() { // Store the version number along with the config. $this->data['version'] = $this->app['bolt_long_version']; if ($this->get('general/caching/config')) { Lib::saveSerialize($this->app['resources']->getPath('cache/config_cache.php'), $this->data); return; } @unlink($this->app['resources']->getPath('cache/config_cache.php')); }
/** * Get the max upload value in a formatted string. * * @return string */ public function getMaxUploadSizeNice() { return Lib::formatFilesize($this->getMaxUploadSize()); }
/** * Set up the profilers for the toolbar. */ public function initProfiler() { // On 'after' attach the debug-bar, if debug is enabled. if (!($this['debug'] && ($this['session']->has('user') || $this['config']->get('general/debug_show_loggedoff')))) { error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_USER_DEPRECATED); return; } // Set the error_reporting to the level specified in config.yml error_reporting($this['config']->get('general/debug_error_level')); // Register Whoops, to handle errors for logged in users only. if ($this['config']->get('general/debug_enable_whoops')) { $this->register(new WhoopsServiceProvider()); // Add a special handler to deal with AJAX requests if ($this['config']->getWhichEnd() == 'async') { $this['whoops']->pushHandler(new JsonResponseHandler()); } } // Register the Silex/Symfony web debug toolbar. $this->register(new Silex\Provider\WebProfilerServiceProvider(), array('profiler.cache_dir' => $this['resources']->getPath('cache') . '/profiler', 'profiler.mount_prefix' => '/_profiler')); // Register the toolbar item for our Database query log. $this->register(new Provider\DatabaseProfilerServiceProvider()); // Register the toolbar item for our bolt nipple. $this->register(new Provider\BoltProfilerServiceProvider()); // Register the toolbar item for the Twig toolbar item. $this->register(new Provider\TwigProfilerServiceProvider()); $this['twig.loader.filesystem'] = $this->share($this->extend('twig.loader.filesystem', function (\Twig_Loader_Filesystem $filesystem, Application $app) { $filesystem->addPath($app['resources']->getPath('root') . '/vendor/symfony/web-profiler-bundle/Symfony/Bundle/WebProfilerBundle/Resources/views', 'WebProfiler'); $filesystem->addPath($app['resources']->getPath('app') . '/view', 'BoltProfiler'); return $filesystem; })); // PHP 5.3 does not allow 'use ($this)' in closures. $app = $this; $this->after(function () use($app) { foreach (Lib::parseTwigTemplates($app['twig.loader.filesystem']) as $template) { $app['twig.logger']->collectTemplateData($template); } }); }
/** * @runInSeparateProcess */ public function testSimpleRedirectAbort() { $app = $this->getApp(); $this->setExpectedException('Symfony\\Component\\HttpKernel\\Exception\\HttpException', "Redirecting to '/test2'."); $this->expectOutputString("<p>Redirecting to <a href='/test2'>/test2</a>.</p><script>window.setTimeout(function () { window.location='/test2'; }, 500);</script>"); $redirect = Library::simpleredirect('/test2', true); }
public function testBadLoadSerializeFails() { $file = PHPUNIT_ROOT . '/resources/data.php'; $data = "\n\n" . 'string'; file_put_contents($file, $data); $data = Library::loadSerialize($file); $this->assertFalse($data); unlink($file); }
/** * Set a Contenttype record's individual value. * * @param string $key * @param mixed $value */ public function setValue($key, $value) { // Don't set templateFields if not a real contenttype if ($key === 'templatefields' && !$this->isRootType) { return; } // Check if the value need to be unserialized. if (is_string($value) && substr($value, 0, 2) === "a:") { try { $unserdata = Lib::smartUnserialize($value); } catch (\Exception $e) { $unserdata = false; } if ($unserdata !== false) { $value = $unserdata; } } if ($key == 'id') { $this->id = $value; } // Set the user in the object. if ($key === 'ownerid' && !empty($value)) { $this->user = $this->app['users']->getUser($value); } // Only set values if they have are actually a field. $allowedcolumns = self::getBaseColumns(); $allowedcolumns[] = 'taxonomy'; if (!isset($this->contenttype['fields'][$key]) && !in_array($key, $allowedcolumns)) { return; } if (in_array($key, ['datecreated', 'datechanged', 'datepublish', 'datedepublish'])) { if (!preg_match("/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $value)) { // @todo Try better date-parsing, instead of just setting it to // 'now' (or 'the past' for datedepublish) if ($key == 'datedepublish') { $value = null; } else { $value = date('Y-m-d H:i:s'); } } } if ($key === 'templatefields') { if (is_string($value) || is_array($value)) { if (is_string($value)) { try { $unserdata = Lib::smartUnserialize($value); } catch (\Exception $e) { $unserdata = false; } } else { $unserdata = $value; } if (is_array($unserdata)) { $templateContent = new Content($this->app, $this->getTemplateFieldsContentType(), [], false); $value = $templateContent; $this->populateTemplateFieldsContenttype($value); $templateContent->setValues($unserdata); } else { $value = null; } } } if (!isset($this->values['datechanged']) || !preg_match("/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $this->values['datechanged'])) { $this->values['datechanged'] = date("Y-m-d H:i:s"); } $this->values[$key] = $value; }