Exemplo n.º 1
0
 /**
  * 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));
             }
         }
     }
 }
Exemplo n.º 2
0
 public function testPath()
 {
     $app = $this->getApp();
     $app->run();
     $this->expectOutputRegex('#Redirecting to /bolt/#');
     $basic = 'homepage';
     $this->assertEquals('/', Library::path($basic));
     $this->assertEquals('/pages/content', Library::path('contentlink', ['contenttypeslug' => 'pages', 'slug' => 'content']));
     $query = 'testing=yes';
     $this->assertEquals('/search?testing=yes', Library::path('search', [], $query));
 }
Exemplo n.º 3
0
 /**
  * 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'];
     }
 }
Exemplo n.º 4
0
 public function testPath()
 {
     $app = $this->getApp();
     $app->run();
     $this->expectOutputRegex('#Redirecting to /bolt/#');
     $basic = "homepage";
     $this->assertEquals("/", Library::path($basic));
     $this->assertEquals('/pages/content', Library::path('contentlink', array('contenttypeslug' => 'pages', 'slug' => 'content')));
     $query = "testing=yes";
     $this->assertEquals("/search?testing=yes", Library::path("search", array(), $query));
 }
 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());
 }
Exemplo n.º 6
0
 /**
  * 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;
 }
Exemplo n.º 7
0
 /**
  * Sanity checks for doubles in in contenttypes.
  */
 public function checkConfig()
 {
     $slugs = array();
     $wrongctype = false;
     foreach ($this->data['contenttypes'] as $key => $ct) {
         /**
          * Make sure any field that has a 'uses' parameter actually points to a field that exists.
          *
          * For example, this will show a notice:
          * entries:
          *   name: Entries
          *     singular_name: Entry
          *     fields:
          *       title:
          *         type: text
          *         class: large
          *       slug:
          *         type: slug
          *         uses: name
          */
         foreach ($ct['fields'] as $fieldname => $field) {
             // Verify that the contenttype doesn't try to add fields that are reserved.
             if ($fieldname != 'slug' && in_array($fieldname, $this->reservedFieldNames)) {
                 $error = Trans::__('contenttypes.generic.reserved-name', array('%contenttype%' => $key, '%field%' => $fieldname));
                 $this->app['session']->getFlashBag()->add('error', $error);
                 return;
             }
             // Check 'uses'. If it's an array, split it up, and check the separate parts. We also need to check
             // for the fields that are always present, like 'id'.
             if (is_array($field) && !empty($field['uses'])) {
                 foreach ($field['uses'] as $useField) {
                     if (!empty($field['uses']) && empty($ct['fields'][$useField]) && !in_array($useField, $this->reservedFieldNames)) {
                         $error = Trans::__('contenttypes.generic.wrong-use-field', array('%contenttype%' => $key, '%field%' => $fieldname, '%uses%' => $useField));
                         $this->app['session']->getFlashBag()->add('error', $error);
                         return;
                     }
                 }
             }
             // Make sure the 'type' is in the list of allowed types
             if (!isset($field['type']) || !$this->fields->has($field['type'])) {
                 $error = Trans::__('contenttypes.generic.no-proper-type', array('%contenttype%' => $key, '%field%' => $fieldname, '%type%' => $field['type']));
                 $this->app['session']->getFlashBag()->add('error', $error);
                 $wrongctype = true && $this->app['users']->getCurrentUsername();
             }
         }
         // Keep a running score of used slugs.
         if (!isset($slugs[$ct['slug']])) {
             $slugs[$ct['slug']] = 0;
         }
         $slugs[$ct['slug']]++;
         if (!isset($slugs[$ct['singular_slug']])) {
             $slugs[$ct['singular_slug']] = 0;
         }
         if ($ct['singular_slug'] != $ct['slug']) {
             $slugs[$ct['singular_slug']]++;
         }
     }
     // Check DB-tables integrity
     if (!$wrongctype && $this->app['integritychecker']->needsCheck() && count($this->app['integritychecker']->checkTablesIntegrity()) > 0 && $this->app['users']->getCurrentUsername()) {
         $msg = Trans::__("The database needs to be updated/repaired. Go to 'Configuration' > '<a href=\"%link%\">Check Database</a>' to do this now.", array('%link%' => Lib::path('dbcheck')));
         $this->app['session']->getFlashBag()->add('error', $msg);
         return;
     }
     // Sanity checks for taxonomy.yml
     foreach ($this->data['taxonomy'] as $key => $taxo) {
         // Show some helpful warnings if slugs or keys are not set correctly.
         if ($taxo['slug'] != $key) {
             $error = Trans::__("The identifier and slug for '%taxonomytype%' are the not the same ('%slug%' vs. '%taxonomytype%'). Please edit taxonomy.yml, and make them match to prevent inconsistencies between database storage and your templates.", array('%taxonomytype%' => $key, '%slug%' => $taxo['slug']));
             $this->app['session']->getFlashBag()->add('error', $error);
             return;
         }
     }
     // if there aren't any other errors, check for duplicates across contenttypes.
     if (!$this->app['session']->getFlashBag()->has('error')) {
         foreach ($slugs as $slug => $count) {
             if ($count > 1) {
                 $error = Trans::__("The slug '%slug%' is used in more than one contenttype. Please edit contenttypes.yml, and make them distinct.", array('%slug%' => $slug));
                 $this->app['session']->getFlashBag()->add('error', $error);
                 return;
             }
         }
     }
 }
Exemplo n.º 8
0
/**
 * 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;
}
Exemplo n.º 9
0
 /**
  * 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;
     }
 }
Exemplo n.º 10
0
 /**
  * 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)
 {
     if (isset($item['submenu']) && is_array($item['submenu'])) {
         $item['submenu'] = $this->menuHelper($item['submenu']);
     }
     if (isset($item['path']) && $item['path'] == "homepage") {
         $item['link'] = $this->app['paths']['root'];
     } elseif (isset($item['route'])) {
         $param = empty($item['param']) ? array() : $item['param'];
         $add = empty($item['add']) ? '' : $item['add'];
         $item['link'] = Lib::path($item['route'], $param, $add);
     } elseif (isset($item['path']) && !isset($item['link'])) {
         if (preg_match('#^(https?://|//)#i', $item['path'])) {
             // We have a mistakenly placed URL, allow it but log it.
             $item['link'] = $item['path'];
             $this->app['logger.system']->error(Trans::__('Invalid menu path (%PATH%) set in menu.yml. Probably should be a link: instead!', array('%PATH%' => $item['path'])), array('event' => 'config'));
         } else {
             // Get a copy of the path minus trainling/leading slash
             $path = ltrim(rtrim($item['path'], '/'), '/');
             // Pre-set our link in case the match() throws an exception
             $item['link'] = '/' . $path;
             try {
                 // See if we have a 'content/id' or 'content/slug' path
                 if (preg_match('#^([a-z0-9_-]+)/([a-z0-9_-]+)$#i', $path)) {
                     // Determine if the provided path first matches any routes
                     // that we have, this will catch any valid configured
                     // contenttype slug and record combination, or throw a
                     // ResourceNotFoundException exception otherwise
                     $this->app['url_matcher']->match('/' . $path);
                     // If we found a valid routing match then we're still here,
                     // attempt to retrive the actual record.
                     $content = $this->app['storage']->getContent($path);
                     if ($content instanceof \Bolt\Content) {
                         if (empty($item['label'])) {
                             $item['label'] = !empty($content->values['title']) ? $content->values['title'] : "";
                         }
                         if (empty($item['title'])) {
                             $item['title'] = !empty($content->values['subtitle']) ? $content->values['subtitle'] : "";
                         }
                         $item['link'] = $content->link();
                     }
                 } else {
                     $item['link'] = $this->app['request']->getBasePath() . '/' . $path;
                 }
             } catch (ResourceNotFoundException $e) {
                 $this->app['logger.system']->error(Trans::__('Invalid menu path (%PATH%) set in menu.yml. Does not match any configured contenttypes or routes.', array('%PATH%' => $item['path'])), array('event' => 'config'));
             }
         }
     }
     return $item;
 }
Exemplo n.º 11
0
 /**
  * Create the first user.
  *
  * @param Application $app
  * @param Request     $request
  *
  * @return \Twig_Markup|\Symfony\Component\HttpFoundation\RedirectResponse
  */
 public function userFirst(Application $app, Request $request)
 {
     // We should only be here for creating the first user
     if ($app['integritychecker']->checkUserTableIntegrity() && $app['users']->hasUsers()) {
         return Lib::redirect('dashboard');
     }
     // Get and empty user array
     $user = $app['users']->getEmptyUser();
     // Add a note, if we're setting up the first user using SQLite.
     $dbdriver = $app['config']->get('general/database/driver');
     if ($dbdriver === 'sqlite' || $dbdriver === 'pdo_sqlite') {
         $note = Trans::__('page.edit-users.note-sqlite');
     } else {
         $note = '';
     }
     // If we get here, chances are we don't have the tables set up, yet.
     $app['integritychecker']->repairTables();
     // Grant 'root' to first user by default
     $user['roles'] = array(Permissions::ROLE_ROOT);
     // Get the form
     $form = $this->getUserForm($app, $user, true);
     // Set the validation
     $form = $this->setUserFormValidation($app, $form, true);
     /** @var \Symfony\Component\Form\Form */
     $form = $form->getForm();
     // Check if the form was POST-ed, and valid. If so, store the user.
     if ($request->isMethod('POST')) {
         if ($this->validateUserForm($app, $form, true)) {
             // To the dashboard, where 'login' will be triggered
             return $app->redirect(Lib::path('dashboard'));
         }
     }
     $context = array('kind' => 'create', 'form' => $form->createView(), 'note' => $note, 'displayname' => $user['displayname']);
     return $app['render']->render('firstuser/firstuser.twig', array('context' => $context));
 }
Exemplo n.º 12
0
 /**
  * Create a link to edit a .yml file, if a filename is detected in the string. Mostly
  * for use in Flashbag messages, to allow easy editing.
  *
  * @param string  $str
  * @param boolean $safe
  *
  * @return string Resulting string
  */
 public function ymllink($str, $safe)
 {
     // There is absolutely no way anyone could possibly need this in a "safe" context
     if ($safe) {
         return null;
     }
     $matches = array();
     if (preg_match('/ ([a-z0-9_-]+\\.yml)/i', $str, $matches)) {
         $path = Lib::path('fileedit', array('namespace' => 'config', 'file' => $matches[1]));
         $link = sprintf(' <a href="%s">%s</a>', $path, $matches[1]);
         $str = preg_replace('/ ([a-z0-9_-]+\\.yml)/i', $link, $str);
     }
     return $str;
 }
Exemplo n.º 13
0
 /**
  * Return the URI for a package's config file edit window.
  *
  * @param string $name
  *
  * @return string
  */
 private function linkConfig($name)
 {
     // Generate the configfilename from the extension $name
     $configfilename = join(".", array_reverse(explode("/", $name))) . '.yml';
     // Check if we have a config file, and if it's readable. (yet)
     $configfilepath = $this->app['resources']->getPath('extensionsconfig/' . $configfilename);
     if (is_readable($configfilepath)) {
         return Lib::path('fileedit', array('namespace' => 'config', 'file' => 'extensions/' . $configfilename));
     }
     return null;
 }
Exemplo n.º 14
0
 protected function showCleanup($output, $name, $version)
 {
     $pack = array();
     foreach ($output as $item) {
         if (strpos($item, ' : ') !== false) {
             $split = explode(' : ', $item);
             $split[0] = str_replace('.', '', $split[0]);
             $pack[trim($split[0])] = trim($split[1]);
             $pack['version'] = $version;
         }
     }
     if (count($pack) < 1) {
         $pack['name'] = $name;
         $pack['version'] = 'unknown';
         $pack['type'] = 'unknown';
         $pack['descrip'] = 'Not yet installed';
     }
     // flatten the composer array one level to make working easier
     $initializedExtensions = array();
     foreach ($this->app['extensions']->composer as $val) {
         $initializedExtensions += $val;
     }
     // For Bolt, we also need to know if the extension has a 'README' and a 'config.yml' file.
     // Note we only do this for successfully loaded extensions.
     if (isset($initializedExtensions[$name])) {
         $paths = $this->app['resources']->getPaths();
         if (is_readable($paths['extensionspath'] . '/vendor/' . $pack['name'] . '/README.md')) {
             $pack['readme'] = $pack['name'] . '/README.md';
         } elseif (is_readable($paths['extensionspath'] . '/vendor/' . $pack['name'] . '/readme.md')) {
             $pack['readme'] = $pack['name'] . '/readme.md';
         }
         if (!empty($pack['readme'])) {
             $pack['readmelink'] = $paths['async'] . 'readme/' . $pack['readme'];
         }
         // generate the configfilename from the extension $name
         $configfilename = join(".", array_reverse(explode("/", $name))) . '.yml';
         // Check if we have a config file, and if it's readable. (yet)
         $configfilepath = $paths['extensionsconfig'] . '/' . $configfilename;
         if (is_readable($configfilepath)) {
             $configfilename = 'extensions/' . $configfilename;
             $pack['config'] = Lib::path('fileedit', array('namespace' => 'config', 'file' => $configfilename));
         }
         // as a bonus we add the extension title to the pack
         $pack['title'] = $initializedExtensions[$name]['name'];
         $pack['authors'] = $initializedExtensions[$name]['json']['authors'];
     }
     return $pack;
 }