3

I am trying to give 2 content types the same singular slug in bolt. both of them should have the same fields, and the same template. at this point i use the record_template: tag to set the default template for each content type.

vervolgpagina:
  name: vervolgpagina
  singular_slug: graszoden
  singular_name: vervolg
  fields:
      titel:
          type: text
          class: large
          group: Content
      slug:
          type: slug
          uses: titel
          group: Content
      body:
          type: html
          height: 500px
          group: Content
      meta_keywords:
          type: text
          group: SEO
          label: "Meta keywords"
      meta_description:
          type: textarea
          height: 50px
          group: SEO
          label: "Meta description"
  record_template: vervolgpagina.twig

graszoden:
  name: graszoden
  singular_slug: graszoden
  singular_name: gras
  fields:
      titel:
          type: text
          class: large
          group: Content
      slug:
          type: slug
          uses: titel
          group: Content
      body:
          type: html
          height: 500px
          group: Content
      meta_keywords:
          type: text
          group: SEO
          label: "Meta keywords"
      meta_description:
          type: textarea
          height: 50px
          group: SEO
          label: "Meta description"
  record_template: vervolgpagina.twig

so if i just put in one of the two content types and add a page to it then it redirects me to /graszoden/vervolgpagina

so if i add the secont content type and add another page to it /graszoden/randomexample

what happends now. is that the page that worked just fine. says ERROR 404, and the other page gives me an bolt error with "No listing.twig file specified."

is there a way to show a content type twice in the cms with other names? Or is there a way to give two content types the same singular slug?

Thanx in advance,

B. Dionys
  • 916
  • 7
  • 34
  • Not that I have much clue what this is about, but reads like a nice question ;-) – GhostCat May 04 '17 at 14:10
  • @GhostCat The question is about the routing bolt-cms uses. its a fixed bunch of standard routes but this question goes on about how to break open the standard and create our own routes – B. Dionys May 04 '17 at 14:17

2 Answers2

2

No, you can't. If you have two contenttypes with the same slug and same fields, it should really just be one CT.

Perhaps what you might want is a "Grouping Taxonomy", see the example in taxonomy.yml for that.

Bopp
  • 664
  • 3
  • 5
1

After some more projects in bolt using twig ive got some other solution.

If you want to use singular slugs multiple times u are forced to create a listing page. But with this you will not have to. Just create an local extension and fill in the part highlighted at the end in this answer.

Link to sourcecode No readme yet. But I hope the explanation here is good enough.

Here is the extension file code (This code is litteraly all the functionality, you will have to create a local extension for this to work ):

class MatchAllController
{
/**
 * The bolt application
 *
 * @var
 */
protected $app;

/**
 * The path to the config.yml
 *
 * @var string
 */
protected $configPath = __DIR__ . '/../../config/config.yml';

public function matchAll(Request $request, $slug, Application $application)
{
    $this->app = $application;

//        var_dump($this->getConfig());die;
    $contentTypes = ['provincies', 'vervolg'];

    foreach($contentTypes as $contentType)
    {
        if(null !== $result = $this->record($request, $contentType, $slug)) {
            return $result;
        }
    }

    $this->abort(Response::HTTP_NOT_FOUND, "Page $slug not found.");
    return null;
}

protected function getConfig()
{
    return Yaml::parse(file_get_contents($this->configPath));
}

public function record(Request $request, $contenttypeslug, $slug = '')
{
    $contenttype = $this->getContentType($contenttypeslug);

    // Perhaps we don't have a slug. Let's see if we can pick up the 'id', instead.
    if (empty($slug)) {
        $slug = $request->get('id');
    }

    $slug = $this->app['slugify']->slugify($slug);

    // First, try to get it by slug.
    $content = $this->getContent($contenttype['slug'], ['slug' => $slug, 'returnsingle' => true, 'log_not_found' => !is_numeric($slug)]);

    if (!$content && is_numeric($slug)) {
        // And otherwise try getting it by ID
        $content = $this->getContent($contenttype['slug'], ['id' => $slug, 'returnsingle' => true]);
    }

    // No content, no page!
    if (!$content) {
        return null;
    }

    // Then, select which template to use, based on our 'cascading templates rules'
    $template = $this->templateChooser()->record($content);

    // Setting the canonical URL.
    if ($content->isHome() && ($template === $this->getOption('general/homepage_template'))) {
        $url = $this->app['resources']->getUrl('rooturl');
    } else {
        $url = $this->app['resources']->getUrl('rooturl') . ltrim($content->link(), '/');
    }
    $this->app['resources']->setUrl('canonicalurl', $url);

    // Setting the editlink
    $this->app['editlink'] = $this->generateUrl('editcontent', ['contenttypeslug' => $contenttype['slug'], 'id' => $content->id]);
    $this->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.
    $globals = [
        'record'                      => $content,
        $contenttype['singular_slug'] => $content,
    ];

    return $this->render($template, [], $globals);
}

/**
 * Get the contenttype as an array, based on the given slug.
 *
 * @param string $slug
 *
 * @return boolean|array
 */
protected function getContentType($slug)
{
    return $this->storage()->getContentType($slug);
}

/**
 * Returns the Entity Manager.
 *
 * @return \Bolt\Storage\EntityManager
 */
protected function storage()
{
    return $this->app['storage'];
}

/**
 * Shortcut to abort the current request by sending a proper HTTP error.
 *
 * @param integer $statusCode The HTTP status code
 * @param string  $message    The status message
 * @param array   $headers    An array of HTTP headers
 *
 * @throws HttpExceptionInterface
 */
protected function abort($statusCode, $message = '', array $headers = [])
{
    $this->app->abort($statusCode, $message, $headers);
}

/**
 * Shortcut for {@see \Bolt\Legacy\Storage::getContent()}
 *
 * @param string $textquery
 * @param array  $parameters
 * @param array  $pager
 * @param array  $whereparameters
 *
 * @return \Bolt\Legacy\Content|\Bolt\Legacy\Content[]
 *
 * @see \Bolt\Legacy\Storage::getContent()
 */
protected function getContent($textquery, $parameters = [], &$pager = [], $whereparameters = [])
{
    return $this->storage()->getContent($textquery, $parameters, $pager, $whereparameters);
}

/**
 * Return the Bolt\TemplateChooser provider.
 *
 * @return \Bolt\TemplateChooser
 */
protected function templateChooser()
{
    return $this->app['templatechooser'];
}

/**
 * Shortcut for {@see UrlGeneratorInterface::generate}
 *
 * @param string $name          The name of the route
 * @param array  $params        An array of parameters
 * @param int    $referenceType The type of reference to be generated (one of the constants)
 *
 * @return string
 */
protected function generateUrl($name, $params = [], $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
{
    /** @var UrlGeneratorInterface $generator */
    $generator = $this->app['url_generator'];

    return $generator->generate($name, $params, $referenceType);
}

/**
 * Renders a template
 *
 * @param string $template  the template name
 * @param array  $variables array of context variables
 * @param array  $globals   array of global variables
 *
 * @return \Bolt\Response\BoltResponse
 */
protected function render($template, array $variables = [], array $globals = [])
{
    return $this->app['render']->render($template, $variables, $globals);
}
}

Becouse this is an new starting project. The only thing that is variable is this part

public function matchAll(Request $request, $slug, Application $application)
{
$this->app = $application;

//Fill your costum routes in here
$contentTypes = ['VARIABLE SINGULAR SLUG', 'VARIABLE SINGULAR SLUG 2'];

foreach($contentTypes as $contentType)
{
    if(null !== $result = $this->record($request, $contentType, $slug)) {
        return $result;
    }
}

$this->abort(Response::HTTP_NOT_FOUND, "Page $slug not found.");
return null;
}

$contentTypes = ['VARIABLE SINGULAR SLUG', 'VARIABLE SINGULAR SLUG 2'];

This particular piece of code is where u fill in the singular slug u want to use. It can contain infinite slugs

Hope this helps someone else later on. Happy coding!

B. Dionys
  • 916
  • 7
  • 34
  • Sorry, but I don't see how this could really help other people. You are basically saying: one can program a solution ... – GhostCat May 04 '17 at 13:40
  • @GhostCat yes sorry im working on putting this extension online so I can put link in the answer – B. Dionys May 04 '17 at 13:58
  • 1
    That sounds better. Although: you might want to include some summary into the answer - as "link only" answers are discouraged; as you know: links tend to break. – GhostCat May 04 '17 at 14:08
  • hmm its an extension for bolt ill try to give a run on it trough here but it will be a lot of code but as u say. links tend to break. – B. Dionys May 04 '17 at 14:15
  • 1
    Sure. Balancing is required. This site is not a source code repository. So linking to github or wherever is fine. But explaining the basics of your solution would make a great answer . – GhostCat May 04 '17 at 14:16
  • @GhostCat full extension code is here now I guess people will get a rough idea on how to get this to work now. :) – B. Dionys May 04 '17 at 14:29