Пример #1
0
 /**
  * The default before filter for the controllers in this file.
  *
  * Refer to the routing.yml config file for overridding.
  *
  * @param Request $request The Symfony Request
  *
  * @return null|BoltResponse|RedirectResponse
  */
 public function before(Request $request)
 {
     // Start the 'stopwatch' for the profiler.
     $this->app['stopwatch']->start('bolt.frontend.before');
     // If there are no users in the users table, or the table doesn't exist.
     // Repair the DB, and let's add a new user.
     if (!$this->hasUsers()) {
         $this->flashes()->info(Trans::__('general.phrase.users-none-create-first'));
         return $this->redirectToRoute('userfirst');
     }
     // If we are in maintenance mode and current user is not logged in, show maintenance notice.
     if ($this->getOption('general/maintenance_mode')) {
         if (!$this->isAllowed('maintenance-mode')) {
             $template = $this->templateChooser()->maintenance();
             $response = $this->render($template);
             $response->setStatusCode(Response::HTTP_SERVICE_UNAVAILABLE);
             return $response;
         }
     }
     // If we have a valid cache respose, return it.
     if ($response = $this->app['render']->fetchCachedRequest()) {
         // Stop the 'stopwatch' for the profiler.
         $this->app['stopwatch']->stop('bolt.frontend.before');
         // Short-circuit the request, return the HTML/response. YOLO.
         return $response;
     }
     // Stop the 'stopwatch' for the profiler.
     $this->app['stopwatch']->stop('bolt.frontend.before');
     return null;
 }
Пример #2
0
 /**
  * Check whether or not the GD-library can be used in PHP. Needed for making thumbnails.
  */
 protected function gdCheck()
 {
     if (!function_exists('imagecreatetruecolor')) {
         $notice = "The current version of PHP doesn't have the GD library enabled. Without this, Bolt will not be able to generate thumbnails. Please enable <tt>php-gd</tt>, or ask your system-administrator to do so.";
         $this->app['logger.flash']->configuration(Trans::__($notice));
     }
 }
Пример #3
0
 /**
  * Handle a login attempt.
  *
  * @param \Silex\Application $app     The application/container
  * @param Request            $request The Symfony Request
  *
  * @return \Symfony\Component\HttpFoundation\RedirectResponse
  */
 public function postLogin(Silex\Application $app, Request $request)
 {
     switch ($request->get('action')) {
         case 'login':
             // Log in, if credentials are correct.
             $result = $app['users']->login($request->get('username'), $request->get('password'));
             if ($result) {
                 $app['logger.system']->info('Logged in: ' . $request->get('username'), array('event' => 'authentication'));
                 $retreat = $app['session']->get('retreat');
                 $redirect = !empty($retreat) && is_array($retreat) ? $retreat : array('route' => 'dashboard', 'params' => array());
                 return Lib::redirect($redirect['route'], $redirect['params']);
             }
             return $this->getLogin($app, $request);
         case 'reset':
             // Send a password request mail, if username exists.
             $username = trim($request->get('username'));
             if (empty($username)) {
                 $app['users']->session->getFlashBag()->add('error', Trans::__('Please provide a username', array()));
             } else {
                 $app['users']->resetPasswordRequest($request->get('username'));
                 return Lib::redirect('login');
             }
             return $this->getLogin($app, $request);
     }
     // Let's not disclose any internal information.
     $app->abort(Response::HTTP_BAD_REQUEST, 'Invalid request');
 }
Пример #4
0
 /**
  * List browse on the server, so we can insert them in the file input.
  *
  * @param Request $request
  * @param string  $namespace
  * @param string  $path
  *
  * @return \Bolt\Response\BoltResponse
  */
 public function browse(Request $request, $namespace, $path)
 {
     // No trailing slashes in the path.
     $path = rtrim($path, '/');
     $filesystem = $this->filesystem()->getFilesystem($namespace);
     // $key is linked to the fieldname of the original field, so we can
     // Set the selected value in the proper field
     $key = $request->query->get('key');
     // Get the pathsegments, so we can show the path.
     $pathsegments = [];
     $cumulative = '';
     if (!empty($path)) {
         foreach (explode('/', $path) as $segment) {
             $cumulative .= $segment . '/';
             $pathsegments[$cumulative] = $segment;
         }
     }
     try {
         $filesystem->listContents($path);
     } catch (\Exception $e) {
         $msg = Trans::__("Folder '%s' could not be found, or is not readable.", ['%s' => $path]);
         $this->flashes()->error($msg);
     }
     list($files, $folders) = $filesystem->browse($path, $this->app);
     $context = ['namespace' => $namespace, 'files' => $files, 'folders' => $folders, 'pathsegments' => $pathsegments, 'key' => $key];
     return $this->render('files_async/files_async.twig', ['context' => $context], ['title', Trans::__('Files in %s', ['%s' => $path])]);
 }
Пример #5
0
 /**
  * Set up Composer JSON file.
  *
  * @return array|null
  */
 public function updateJson()
 {
     if (!is_file($this->getOption('composerjson'))) {
         $this->initJson($this->getOption('composerjson'));
     }
     $jsonFile = new JsonFile($this->getOption('composerjson'));
     if ($jsonFile->exists()) {
         $json = $jsonorig = $jsonFile->read();
         // Workaround Bolt 2.0 installs with "require": []
         if (isset($json['require']) && empty($json['require'])) {
             unset($json['require']);
         }
         $json = $this->setJsonDefaults($json);
     } else {
         // Error
         $this->messages[] = Trans::__("The Bolt extensions file '%composerjson%' isn't readable.", ['%composerjson%' => $this->getOption('composerjson')]);
         $this->app['extend.writeable'] = false;
         $this->app['extend.online'] = false;
         return null;
     }
     // Write out the file, but only if it's actually changed, and if it's writable.
     if ($json != $jsonorig) {
         try {
             umask(00);
             $jsonFile->write($json);
         } catch (\Exception $e) {
             $this->messages[] = Trans::__('The Bolt extensions Repo at %repository% is currently unavailable. Check your connection and try again shortly.', ['%repository%' => $this->app['extend.site']]);
         }
     }
     return $json;
 }
Пример #6
0
 /**
  * Set up Composer JSON file.
  *
  * @return array|null
  */
 public function update()
 {
     /** @var \Bolt\Filesystem\Handler\JsonFile $jsonFile */
     $jsonFile = $this->app['filesystem']->get('extensions://composer.json', new JsonFile());
     if (!$jsonFile->exists()) {
         try {
             $this->init('extensions://composer.json');
         } catch (IOException $e) {
             $this->messages[] = Trans::__("The Bolt extensions composer.json isn't readable.");
             $this->app['extend.writeable'] = false;
             $this->app['extend.online'] = false;
             return;
         }
     }
     $json = $jsonOrig = $jsonFile->parse();
     // Workaround Bolt 2.0 installs with "require": []
     if (isset($json['require']) && empty($json['require'])) {
         unset($json['require']);
     }
     $json = $this->setJsonDefaults($json);
     $json = $this->setJsonLocal($json);
     // Write out the file, but only if it's actually changed, and if it's writable.
     if ($json != $jsonOrig) {
         try {
             $jsonFile->dump($json);
         } catch (IOException $e) {
             $this->messages[] = Trans::__("The Bolt extensions composer.json isn't writable.");
         }
     }
     return $json;
 }
Пример #7
0
 public function initialize()
 {
     // For europeana, stupid hardcoded redirect for a domain:
     if (strpos($_SERVER['HTTP_HOST'], "europeanacreative.eu") !== false) {
         \Bolt\Library::simpleredirect('http://pro.europeana.eu/get-involved/projects/project-list/europeana-creative');
         die;
     }
     // structure tree overview
     $this->boltPath = $this->app['config']->get('general/branding/path');
     // listings
     if ($this->app['config']->getWhichEnd() === 'backend' || $this->app['config']->getWhichEnd() === 'cli') {
         // back-end listings
         $this->addMenuOption(\Bolt\Translation\Translator::__('Structure Tree'), "{$this->boltPath}/structure-tree/overview", "fa:sitemap");
         $this->app->get("{$this->boltPath}/structure-tree/overview", array($this, 'structureTreeOverview'))->bind('structureTreeOverview');
         // convert legacy relationships to column values in contenttypes.
         $this->app->get("{$this->boltPath}/structure-tree/convert", array($this, 'structureTreeConvert'))->bind('structureTreeConvert');
     } else {
         // slug listing
         $this->app->match("/{slug}", array($this, 'slugTreeRecord'))->assert('slug', '[a-zA-Z0-9_\\-]+[^(sitemap)^(search)]')->bind('slugTreeRecord');
         // strucutureslug / slug listing
         $this->app->match("/{structureSlugs}/{slug}", array($this, 'structureTreeRecord'))->assert('structureSlugs', '(?!(async|_profiler)).*')->assert('slug', '[a-zA-Z0-9_\\-]+')->bind('structureTreeRecord');
     }
     // twig functions
     $this->addTwigFunction('structurelink', 'getStructureLink');
     $this->addTwigFunction('structurecontenttype', 'getContenttypeByStructure');
     $this->addTwigFunction('breadcrumb', 'breadCrumb');
     $this->addTwigFunction('subsite', 'subSite');
     $this->addTwigFunction('sortRecords', 'sortObject');
     $this->addTwigFunction('getContenttype', 'getContenttype');
     $this->addTwigFunction('getTreeChildren', 'getTreeChildren');
     $this->contenttypeslugs = $this->config['contenttypes'];
 }
Пример #8
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(FormBuilderInterface $builder, array $options)
 {
     $passwordConstraints = [];
     if ($this->requirePassword) {
         $passwordConstraints = [new Assert\NotBlank(), new Assert\Length(['min' => 6])];
     }
     $builder->add('email', EmailType::class, ['label' => Trans::__($this->config->getLabel('email')), 'attr' => ['placeholder' => $this->config->getPlaceholder('email')], 'constraints' => [new Assert\Email(['message' => 'The address "{{ value }}" is not a valid email.', 'checkMX' => true])]])->add('password', RepeatedType::class, ['type' => PasswordType::class, 'first_options' => ['label' => Trans::__($this->config->getLabel('password_first')), 'attr' => ['placeholder' => $this->config->getPlaceholder('password_first')], 'constraints' => $passwordConstraints], 'second_options' => ['label' => Trans::__($this->config->getLabel('password_second')), 'attr' => ['placeholder' => $this->config->getPlaceholder('password_second')], 'constraints' => $passwordConstraints], 'empty_data' => null, 'required' => $this->requirePassword])->add('submit', SubmitType::class, ['label' => Trans::__($this->config->getLabel('profile_save'))]);
 }
Пример #9
0
 public function initialize()
 {
     if ($this->app['config']->getWhichEnd() === 'backend') {
         $path = $this->app['config']->get('general/branding/path') . '/extensions/image-cleanup';
         $this->app->mount($path, new Controller\ImageCleanupAdminController());
         $this->app['extensions.Image cleanup for Bolt']->addMenuOption(Translator::__('Image Cleanup'), $this->app['resources']->getUrl('bolt') . 'extensions/image-cleanup', 'fa:pencil-square-o');
     }
 }
 public function buildForm(FormBuilderInterface $builder, array $options)
 {
     $builder->add('name', 'text', ['label' => Trans::__('Internal name for field'), 'read_only' => true, 'attr' => ['help' => Trans::__('Only letters, numbers and underscores allowed')]])->add('label', 'text', ['label' => Trans::__('Label for this form field'), 'attr' => ['help' => Trans::__('This is the user-visible label')]])->add('type', 'choice', ['label' => Trans::__('Type of form element'), 'choices' => ['text' => Trans::__('Text'), 'textarea' => Trans::__('Text Area'), 'choice' => Trans::__('Select Dropdown'), 'submit' => Trans::__('Submit Button')]])->add('required', 'checkbox', ['label' => Trans::__('Required Field'), 'required' => false]);
     $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
         $form = $event->getForm();
         $data = $event->getData();
         $form->add('choices', 'choice', ['label' => Trans::__('Options to show'), 'required' => false, 'multiple' => true, 'attr' => ['help' => Trans::__('Setup the available choices')], 'choices' => array_combine((array) $data['choices'], (array) $data['choices'])]);
     });
 }
Пример #11
0
 /**
  * No mail transport has been set. We should gently nudge the user to set
  * the mail configuration.
  *
  * @see https://github.com/bolt/bolt/issues/2908
  *
  * @param Request $request
  */
 protected function mailConfigCheck(Request $request)
 {
     if (!$request->hasPreviousSession()) {
         return;
     }
     if (!$this->app['config']->get('general/mailoptions') && $this->app['users']->getCurrentuser() && $this->app['users']->isAllowed('files:config')) {
         $error = "The mail configuration parameters have not been set up. This may interfere with password resets, and extension functionality. Please set up the 'mailoptions' in config.yml.";
         $this->app['logger.flash']->error(Trans::__($error));
     }
 }
Пример #12
0
 /**
  * No Mail transport has been set. We should gently nudge the user to set
  * the mail configuration.
  *
  * For now, we only pester the user, if an extension needs to be able to
  * send mail, but it's not been set up.
  *
  * @see: the issue at https://github.com/bolt/bolt/issues/2908
  *
  * @param Request $request
  */
 protected function mailConfigCheck(Request $request)
 {
     if (!$request->hasPreviousSession()) {
         return;
     }
     if ($this->app['users']->getCurrentuser() && !$this->app['config']->get('general/mailoptions') && $this->app['extensions']->hasMailSenders()) {
         $error = "One or more installed extensions need to be able to send email. Please set up the 'mailoptions' in config.yml.";
         $this->app['logger.flash']->error(Trans::__($error));
     }
 }
Пример #13
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 = ['version' => Bolt\Version::VERSION, 'payoff' => 'Sophisticated, lightweight & simple CMS', 'dashboardlink' => sprintf('<a href="%s">%s</a>', $this->app['url_generator']->generate('dashboard'), 'Dashboard'), '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'];
     }
 }
Пример #14
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 = ['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>', $this->app->generatePath('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'];
     }
 }
Пример #15
0
 function initialize()
 {
     $this->path = $this->app['config']->get('general/branding/path') . '/extensions/google-analytics';
     $this->app->match($this->path, array($this, 'GoogleAnalytics'));
     $this->app['htmlsnippets'] = true;
     if ($this->app['config']->getWhichEnd() == 'frontend') {
         $this->addSnippet('endofhead', 'insertAnalytics');
     } else {
         $this->app->before(array($this, 'before'));
     }
     if (isset($this->config['backend']) && $this->config['backend']) {
         $this->addMenuOption(Trans::__('Statistics'), $this->app['paths']['bolt'] . 'extensions/google-analytics', "fa:area-chart");
     }
 }
Пример #16
0
 public function signin(Request $request)
 {
     $login = new \Bolt\Extension\Blimp\Client\AccessControl\Login($this->app);
     $login->setRequest($request);
     $query = $request->query->all();
     $code = array_key_exists('code', $query) ? $query['code'] : null;
     $state = array_key_exists('state', $query) ? $query['state'] : null;
     $error = array_key_exists('error', $query) ? $query['error'] : null;
     $error_description = array_key_exists('error_description', $query) ? $query['error_description'] : null;
     $destination = $this->app['blimp_client.session_from_code']($code, $state, $error, $error_description);
     $access_token = $this->app['blimp_client.access_token']();
     $logged_in = !empty($access_token) ? $this->app['blimp_client.validate_access_token']($access_token, true, true) : false;
     if (!$logged_in) {
         $this->flashes()->error(Trans::__($error_description ?: $error));
         $response = new RedirectResponse($destination);
     } else {
         $user_id = $logged_in['profile_id'];
         if (!($userEntity = $this->getUser($user_id))) {
             $users_repo = $this->app['storage']->getRepository('Bolt\\Storage\\Entity\\Users');
             $userEntity = new \Bolt\Storage\Entity\Users();
             $userEntity->setUsername($user_id);
             $userEntity->setPassword('not_local_user');
             $userEntity->setEmail($logged_in['profile']['email']);
             $userEntity->setDisplayname($logged_in['profile']['name']);
             $userEntity->setEnabled(true);
             $userEntity->setRoles(explode(' ', $logged_in['scope']));
             $users_repo->save($userEntity);
         }
         if (!$userEntity->getEnabled()) {
             $this->flashLogger->error(Trans::__('Your account is disabled. Sorry about that.'));
             $url = $this->app['blimp_client.request_code'](['return_to' => $destination]);
             $response = new RedirectResponse($url);
         } else {
             $login->loginFinish($userEntity);
             // Authentication data is cached in the session and if we can't get it
             // now, everyone is going to have a bad day. Make that obvious.
             if (!($token = $this->session()->get('authentication'))) {
                 $this->flashes()->error(Trans::__("Unable to retrieve login session data. Please check your system's PHP session settings."));
                 $url = $this->app['blimp_client.request_code'](['return_to' => $destination]);
                 $response = new RedirectResponse($url);
             } else {
                 // Log in, if credentials are correct.
                 $this->app['logger.system']->info('Logged in: ' . $user_id, ['event' => 'authentication']);
                 $response = $this->setAuthenticationCookie(new RedirectResponse($destination), (string) $token);
             }
         }
     }
     return $response;
 }
Пример #17
0
 public function publish(Content $content, $comment = null)
 {
     $contenttype = $content->contenttype;
     $fieldvalues = $content->values;
     // Test to see if this is a new record, or an update
     if (empty($fieldvalues['blimp_id'])) {
         $create = true;
     } else {
         $create = false;
     }
     // Update the content object
     $content->setValues($fieldvalues);
     $extra = [];
     if (!empty($contenttype['relations'])) {
         $relations = $content->related();
         if (!empty($relations)) {
             foreach ($relations as $related) {
                 if (!empty($related->values['blimp_id'])) {
                     if (!empty($contenttype['relations'][$related->contenttype['slug']])) {
                         $multiple = !empty($contenttype['relations'][$related->contenttype['slug']]['multiple']) && $contenttype['relations'][$related->contenttype['slug']]['multiple'];
                         if ($multiple) {
                             if (empty($extra[$related->contenttype['slug']])) {
                                 $extra[$related->contenttype['slug']] = [];
                             }
                             $extra[$related->contenttype['slug']][] = $related->values['blimp_id'];
                         } else {
                             $extra[$related->contenttype['singular_slug']] = $related->values['blimp_id'];
                         }
                     }
                 }
             }
         }
     }
     // Decide whether to insert a new record, or update an existing one.
     $ok = false;
     if ($create) {
         $ok = $this->insertContent($content, $comment, $extra);
     } else {
         $ok = $this->updateContent($content, $comment, $extra);
     }
     if ($ok !== true) {
         return $ok;
     }
     $content->setValue('status', 'published');
     $comment = Trans::__('The content has been published.');
     $result = $this->app['storage']->saveContent($content, $comment);
     return $result;
 }
Пример #18
0
 /**
  * Check the database, create tables, add missing/new columns to tables.
  *
  * @param Request $request The Symfony Request
  *
  * @return \Symfony\Component\HttpFoundation\RedirectResponse
  */
 public function update(Request $request)
 {
     $output = $this->schemaManager()->repairTables()->getResponseStrings();
     // If 'return=edit' is passed, we should return to the edit screen.
     // We do redirect twice, yes, but that's because the newly saved
     // contenttype.yml needs to be re-read.
     $return = $request->get('return');
     if ($return === 'edit') {
         if (empty($output)) {
             $content = Trans::__('Your database is already up to date.');
         } else {
             $content = Trans::__('Your database is now up to date.');
         }
         $this->flashes()->success($content);
         return $this->redirectToRoute('fileedit', ['namespace' => 'config', 'file' => 'contenttypes.yml']);
     } else {
         $this->session()->set('dbupdate_result', $output);
         return $this->redirectToRoute('dbupdate_result');
     }
 }
Пример #19
0
 public function getTranslationAction(Application $app, Request $request)
 {
     $default_locale = $app['config']->get('general/locale', 'en_GB');
     $prefix = $app['config']->get('general/database/prefix', 'bolt_');
     $translation_table_name = $prefix . 'translation';
     $locale = $request->query->get('locale');
     $content_type = $request->query->get('content_type');
     $content_type_id = $request->query->get('content_type_id');
     $content_type_config = $app['config']->get('contenttypes/' . $content_type);
     $translatable_fields = $this->getTranslatableFields($content_type_config['fields']);
     if (!$app['users']->isAllowed('contenttype:' . $content_type . ':edit')) {
         return new Response(Trans::__('Permission denied'), Response::HTTP_FORBIDDEN);
     }
     $response = array();
     // Return default record if default locale
     if ($locale === $default_locale) {
         $query = 'SELECT * FROM ' . $prefix . $content_type . ' WHERE id = :content_type_id';
         $default_content = $app['db']->fetchAssoc($query, array(':content_type_id' => $content_type_id));
         foreach ($translatable_fields as $translatable_field) {
             $element = new \stdClass();
             $element->field = $translatable_field;
             $element->value = $default_content[$translatable_field];
             $response[] = $element;
         }
         return $app->json($response);
     }
     $query = 'SELECT field, value FROM ' . $translation_table_name . ' WHERE locale = :locale AND content_type = :content_type AND content_type_id = :content_type_id';
     $translated_content = $app['db']->fetchAll($query, array(':locale' => $locale, ':content_type' => $content_type, ':content_type_id' => $content_type_id));
     foreach ($translatable_fields as $translatable_field) {
         $element = new \stdClass();
         $element->field = $translatable_field;
         $element->value = '';
         foreach ($translated_content as $content) {
             if ($content['field'] === $translatable_field) {
                 $element->value = $content['value'];
             }
         }
         $response[] = $element;
     }
     return $app->json($response);
 }
Пример #20
0
 /**
  * The default before filter for the controllers in this file.
  *
  * Refer to the routing.yml config file for overridding.
  *
  * @param Request     $request The Symfony Request
  * @param Application $app     The application/container
  *
  * @return null|Response|RedirectResponse
  */
 public function before(Request $request, Application $app)
 {
     // Start the 'stopwatch' for the profiler.
     $app['stopwatch']->start('bolt.frontend.before');
     // If there are no users in the users table, or the table doesn't exist. Repair
     // the DB, and let's add a new user.
     if (!$app['users']->getUsers()) {
         $app['session']->getFlashBag()->add('info', Trans::__('There are no users in the database. Please create the first user.'));
         return Lib::redirect('useredit', array('id' => ''));
     }
     $app['debugbar'] = true;
     $app['htmlsnippets'] = true;
     // If we are in maintenance mode and current user is not logged in, show maintenance notice.
     if ($app['config']->get('general/maintenance_mode')) {
         if (!$app['users']->isAllowed('maintenance-mode')) {
             $template = $app['templatechooser']->maintenance();
             $body = $app['render']->render($template)->getContent();
             return new Response($body, Response::HTTP_SERVICE_UNAVAILABLE);
         }
     }
     // Stop the 'stopwatch' for the profiler.
     $app['stopwatch']->stop('bolt.frontend.before');
     return null;
 }
Пример #21
0
Файл: Log.php Проект: d-m-/bolt
 /**
  * System log overview route
  *
  * @param Request $request
  *
  * @return \Bolt\Response\BoltResponse|\Symfony\Component\HttpFoundation\RedirectResponse
  */
 public function systemOverview(Request $request)
 {
     $action = $request->query->get('action');
     if ($action == 'clear') {
         $this->manager()->clear('system');
         $this->flashes()->success(Trans::__('The system log has been cleared.'));
         return $this->redirectToRoute('systemlog');
     } elseif ($action == 'trim') {
         $this->manager()->trim('system');
         $this->flashes()->success(Trans::__('The system log has been trimmed.'));
         return $this->redirectToRoute('systemlog');
     }
     // Test/get page number
     $page = $this->app['pager']->getCurrentPage('activity');
     $options = ['level' => $request->query->get('level'), 'context' => $request->query->get('context')];
     $activity = $this->manager()->getActivity('system', $page, 16, $options);
     return $this->render('@bolt/activity/systemlog.twig', ['entries' => $activity]);
 }
Пример #22
0
 /**
  * Check for a user with the 'root' role.
  *
  * There should always be at least one If there isn't we promote the current
  * user.
  *
  * @return boolean
  */
 public function checkForRoot()
 {
     // Don't check for root, if we're not logged in.
     if ($this->getCurrentUsername() === false) {
         return false;
     }
     // Loop over the users, check if anybody's root.
     foreach ($this->getUsers() as $user) {
         if (in_array('root', $user['roles'])) {
             // We have a 'root' user.
             return true;
         }
     }
     // Make sure the DB is updated. Note, that at this point we currently don't have
     // the permissions to do so, but if we don't, update the DB, we can never add the
     // role 'root' to the current user.
     $this->app['schema']->update();
     // Show a helpful message to the user.
     $this->app['logger.flash']->info(Trans::__("There should always be at least one 'root' user. You have just been promoted. Congratulations!"));
     // If we reach this point, there is no user 'root'. We promote the current user.
     return $this->addRole($this->getCurrentUsername(), 'root');
 }
Пример #23
0
 /**
  * Generate tab groups.
  *
  * @param array $contenttype
  * @param array $has
  *
  * @return array
  */
 private function createGroupTabs(array $contenttype, array $has)
 {
     $groups = [];
     $groupIds = [];
     $addGroup = function ($group, $label) use(&$groups, &$groupIds) {
         $nr = count($groups) + 1;
         $id = rtrim('tab-' . Slugify::create()->slugify($group), '-');
         if (isset($groupIds[$id]) || $id === 'tab') {
             $id .= '-' . $nr;
         }
         $groups[$group] = ['label' => $label, 'id' => $id, 'is_active' => $nr === 1, 'fields' => []];
         $groupIds[$id] = 1;
     };
     foreach ($contenttype['groups'] ? $contenttype['groups'] : ['ungrouped'] as $group) {
         if ($group === 'ungrouped') {
             $addGroup($group, Trans::__('contenttypes.generic.group.ungrouped'));
         } elseif ($group !== 'meta' && $group !== 'relations' && $group !== 'taxonomy') {
             $default = ['DEFAULT' => ucfirst($group)];
             $key = ['contenttypes', $contenttype['slug'], 'group', $group];
             $addGroup($group, Trans::__($key, $default));
         }
     }
     if ($has['relations'] || $has['incoming_relations']) {
         $addGroup('relations', Trans::__('contenttypes.generic.group.relations'));
         $groups['relations']['fields'][] = '*relations';
     }
     if ($has['taxonomy'] || is_array($contenttype['groups']) && in_array('taxonomy', $contenttype['groups'])) {
         $addGroup('taxonomy', Trans::__('contenttypes.generic.group.taxonomy'));
         $groups['taxonomy']['fields'][] = '*taxonomy';
     }
     if ($has['templatefields'] || is_array($contenttype['groups']) && in_array('template', $contenttype['groups'])) {
         $addGroup('template', Trans::__('Template'));
         $groups['template']['fields'][] = '*template';
     }
     $addGroup('meta', Trans::__('contenttypes.generic.group.meta'));
     $groups['meta']['fields'][] = '*meta';
     // References fields in tab group data.
     foreach ($contenttype['fields'] as $fieldname => $field) {
         $groups[$field['group']]['fields'][] = $fieldname;
     }
     return $groups;
 }
Пример #24
0
 /**
  * Generate a copy of a theme package.
  *
  * @param Request $request
  *
  * @throws PackageManagerException
  *
  * @return Response
  */
 public function generateTheme(Request $request)
 {
     $theme = $request->get('theme');
     $newName = $request->get('name');
     if (empty($theme)) {
         return new Response(Trans::__('No theme name found. Theme is not generated.'));
     }
     if (!$newName) {
         $newName = basename($theme);
     }
     $source = $this->resources()->getPath('extensions/vendor/' . $theme);
     $destination = $this->resources()->getPath('themebase/' . $newName);
     if (is_dir($source)) {
         try {
             $filesystem = new Filesystem();
             $filesystem->mkdir($destination);
             $filesystem->mirror($source, $destination);
             if (file_exists($destination . "/config.yml.dist")) {
                 $filesystem->copy($destination . "/config.yml.dist", $destination . "/config.yml");
             }
             return new Response(Trans::__('Theme successfully generated. You can now edit it directly from your theme folder.'));
         } catch (\Exception $e) {
             return new Response(Trans::__('We were unable to generate the theme. It is likely that your theme directory is not writable by Bolt. Check the permissions and try reinstalling.'));
         }
     }
     throw new PackageManagerException("Invalid theme source directory: {$source}");
 }
Пример #25
0
 /**
  * Process an individual file upload.
  *
  * @param string $namespace
  * @param string $path
  * @param string $filename
  * @param array  $fileToProcess
  *
  * @return void
  */
 private function processUpload($namespace, $path, $filename, array $fileToProcess)
 {
     $this->app['upload.namespace'] = $namespace;
     $handler = $this->app['upload'];
     $handler->setPrefix($path . '/');
     $result = $handler->process($fileToProcess);
     if ($result->isValid()) {
         $this->flashes()->info(Trans::__('page.file-management.message.upload-success', ['%file%' => $filename]));
         // Add the file to our stack.
         $this->app['stack']->add($path . '/' . $filename);
         $result->confirm();
     } else {
         foreach ($result->getMessages() as $message) {
             $this->flashes()->error((string) $message);
         }
     }
 }
Пример #26
0
 /**
  * Check that the user has a valid GSRF token and the required access control
  * to action the record.
  *
  * @param Request $request
  * @param string  $contenttypeslug
  * @param integer $id
  *
  * @return bool|\Symfony\Component\HttpFoundation\RedirectResponse
  */
 private function checkEditAccess(Request $request, $contenttypeslug, $id)
 {
     // Is the record new or existing
     $new = empty($id) ?: false;
     // Check for a valid CSRF token
     if ($request->isMethod('POST') && !$this->checkAntiCSRFToken()) {
         $this->app->abort(Response::HTTP_BAD_REQUEST, Trans::__('Something went wrong'));
     }
     /*
      * Check the user is allowed to create/edit this record, based on:
      *     contenttype-all:
      *     contenttype-default:
      *     contenttypes:
      *         edit: []
      *         create: []
      */
     $perm = $new ? "contenttype:{$contenttypeslug}:create" : "contenttype:{$contenttypeslug}:edit:{$id}";
     if (!$this->isAllowed($perm)) {
         $action = $new ? 'create' : 'edit';
         $this->flashes()->error(Trans::__("You do not have the right privileges to {$action} that record."));
         return $this->redirectToRoute('dashboard');
     }
     return false;
 }
Пример #27
0
 /**
  * Attempt to save the POST data for a translation file edit.
  *
  * @param string $contents
  * @param array  $tr
  *
  * @return boolean|\Symfony\Component\HttpFoundation\RedirectResponse
  */
 private function saveTranslationFile($contents, array &$tr)
 {
     $contents = Input::cleanPostedData($contents) . "\n";
     // Before trying to save a yaml file, check if it's valid.
     try {
         Yaml::parse($contents);
     } catch (ParseException $e) {
         $msg = Trans::__("File '%s' could not be saved:", ['%s' => $tr['shortPath']]);
         $this->flashes()->error($msg . ' ' . $e->getMessage());
         return false;
     }
     // Clear any warning for file not found, we are creating it here
     // we'll set an error if someone still submits the form and write is not allowed
     $this->flashes()->clear();
     try {
         $fs = new Filesystem();
         $fs->dumpFile($tr['path'], $contents);
     } catch (IOException $e) {
         $msg = Trans::__("The file '%s' is not writable. You will have to use your own editor to make modifications to this file.", ['%s' => $tr['shortPath']]);
         $this->flashes()->error($msg);
         $tr['writeallowed'] = false;
         return false;
     }
     $msg = Trans::__("File '%s' has been saved.", ['%s' => $tr['shortPath']]);
     $this->flashes()->info($msg);
     return $this->redirectToRoute('translation', ['domain' => $tr['domain'], 'tr_locale' => $tr['locale']]);
 }
Пример #28
0
 /**
  * No Mail transport has been set. We should gently nudge the user to set the mail configuration.
  *
  * @see: the issue at https://github.com/bolt/bolt/issues/2908
  *
  * For now, we only pester the user, if an extension needs to be able to send
  * mail, but it's not been set up.
  */
 public function initMailCheck()
 {
     if (!$this['config']->get('general/mailoptions') && $this['extensions']->hasMailSenders()) {
         $error = "One or more installed extensions need to be able to send email. Please set up the 'mailoptions' in config.yml.";
         $this['session']->getFlashBag()->add('error', Trans::__($error));
     }
 }
Пример #29
0
 /**
  * Helper function to wrap an image in a Magnific popup HTML tag, with thumbnail.
  *
  * example: {{ content.image|popup(320, 240) }}
  * example: {{ popup(content.image, 320, 240) }}
  * example: {{ content.image|popup(width=320, height=240, title="My Image") }}
  *
  * Note: This function used to be called 'fancybox', but Fancybox was
  * deprecated in favour of the Magnific Popup library.
  *
  * @param string  $filename Image filename
  * @param integer $width    Image width
  * @param integer $height   Image height
  * @param string  $crop     Crop image string identifier
  * @param string  $title    Display title for image
  *
  * @return string HTML output
  */
 public function popup($filename = '', $width = 100, $height = 100, $crop = '', $title = '')
 {
     if (!empty($filename)) {
         $thumbconf = $this->app['config']->get('general/thumbnails');
         $fullwidth = !empty($thumbconf['default_image'][0]) ? $thumbconf['default_image'][0] : 1000;
         $fullheight = !empty($thumbconf['default_image'][1]) ? $thumbconf['default_image'][1] : 800;
         $thumbnail = $this->thumbnail($filename, $width, $height, $crop);
         $large = $this->thumbnail($filename, $fullwidth, $fullheight, 'r');
         if (empty($title)) {
             $title = sprintf('%s: %s', Trans::__('Image'), $filename);
         }
         $output = sprintf('<a href="%s" class="magnific" title="%s"><img src="%s" width="%s" height="%s"></a>', $large, $title, $thumbnail, $width, $height);
     } else {
         $output = '&nbsp;';
     }
     return $output;
 }
Пример #30
0
 /**
  * Sanity checks for doubles in in contenttypes.
  */
 public function checkConfig()
 {
     $slugs = [];
     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', ['%contenttype%' => $key, '%field%' => $fieldname]);
                 $this->app['logger.flash']->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 (!empty($field['uses']) && is_array($field['uses'])) {
                 foreach ((array) $field['uses'] as $useField) {
                     if (!empty($field['uses']) && empty($ct['fields'][$useField]) && !in_array($useField, $this->reservedFieldNames)) {
                         $error = Trans::__('contenttypes.generic.wrong-use-field', ['%contenttype%' => $key, '%field%' => $fieldname, '%uses%' => $useField]);
                         $this->app['logger.flash']->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', ['%contenttype%' => $key, '%field%' => $fieldname, '%type%' => $field['type']]);
                 $this->app['logger.flash']->error($error);
                 unset($ct['fields'][$fieldname]);
             }
         }
         // 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']]++;
         }
     }
     // 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.", ['%taxonomytype%' => $key, '%slug%' => $taxo['slug']]);
             $this->app['logger.flash']->error($error);
             return;
         }
     }
     // if there aren't any other errors, check for duplicates across contenttypes.
     if (!$this->app['logger.flash']->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.", ['%slug%' => $slug]);
                 $this->app['logger.flash']->error($error);
                 return;
             }
         }
     }
 }