Possible to split pages and paginate them?

Hey there,
is it possible to split pages into several parts, I didnt find anything on this matter on the forum or the docs … I got an open access journal but the articles are just too long …

I wrote an article about that for Kirby 1, guess you can adapt it to Kirby 2 if necessary: https://www.texniq.de/en/blog/kirby-cms-split-long-posts-into-pages

Example split post: https://www.texniq.de/de/texniq-u/css3-keyframe-animations/page:1

Two questions:

  • How would I translate the appended “page:n”
  • Is it possible to get it all in one page alongside the paginated one, so i got /page as the full version, and also /page:1 as the first shortened part, /page:2 .. n as the following?

Best regards,
S1SYPHOS

Q2: Hm, don’t know.

Q1:

$articles = $page->children()->paginate(20, array( 'variable' => $site->language()->code() == 'de' ? 'seite' : 'page' )); 
1 Like

Hey there.

Nice tutorial, but …

  • the comment isn’t on PHP land, so it’s content (no problem)
  • short opening tag <? depends on enabling short_open_tag in php.ini (minor problem)
  • $firstPage isn’t defined (headache)

Thank you very much for this anywhoozle!

Where did I use short tags?

$firstpage should be $pages->first().

As I said, it’s old stuff, would probably be easier now.

There you did :smile:

And there’s a rogue </main> on the loose :wink:

Shame on me…:blush: I’ve just updated it.

BTW: I think you can use several alternatives to using an HTML comment; at least at that time, it made the most sense to me, because I wanted to insert breaks manually instead of counting characters or paragraphs or headlines. I also wanted something that is not visible if I decided not to split the post anymore.

1 Like

I totally agree with you!

Hey there,

one thing: I am using the Footnotes plugin, and my code looks something like this:


<?php

  $text       = kirbytext($page->text()->footnotes(['bibliography' => false]));
  $parts      = explode('<!--pagebreak-->', $text);
  $partCount  = count ($parts);

  if($partCount >= 1) {
    $partLinkCount = 1;
  }
  else {
    $partLinkCount = 0;
  }

  $parts = new Collection($parts);
  $parts= $parts->paginate(1);

  foreach ($parts as $part) : ?>

    <?php snippet('header') ?>

      <article class="page-content row">
        <section>
          <h1 class="article-header"><?= $page->title()->html() ?></h1>
          <?= $page->text()->kirbytext()->footnotes(['bibliography' => false]) ?>
        </section>
        <aside>
          <h4>Bibliography</h4>
          <?= KirbyFootnotes::bibliography($page->text()) ?>
        </aside>
        <?php snippet('prevnext', ['flip' => false]) ?>
    <!-- </article> -->

        <?php if($parts->pagination()->hasPrevPage()) : ?>
        <nav>
          <a class="next" href="<?php echo $parts->pagination()->prevPageURL()?>">
            Prev
          </a>
        <?php endif; ?>

        <?php while($partLinkCount <= $partCount && $partCount > 1) : ?>
          <a <?= ($partLinkCount == ($parts->pagination()->page()))?' class="active"':''?> href="<?php echo $parts->pagination()->pageURL($partLinkCount) ?>">
            <?php echo $partLinkCount ?>
          </a>&nbsp;
          <?php $partLinkCount++; ?>
        <?php endwhile ?>

        <?php if($parts->pagination()->hasNextPage()):?>
          <a class="prev" href="<?php echo $parts->pagination()->nextPageURL()?>">Next</a>
        </nav>
        <?php endif?>

      </article>

    <?php snippet('footer')?>

  <?php endforeach ?>

This is exactly what you have on your blog post, except I replaced $page with $part. I entered one pagebreak, generating two pages. As you can see, I replaced the $text variable to contain the footnote method, rendering footnotes in text & generating footnotes below the text upon calling <?= KirbyFootnotes::bibliography($page->text()) ?>.

Now, my question is:
How could I modify the footnote output to contain only the footnotes from the current page? When doing something like <?= KirbyFootnotes::bibliography($part) ?> I get this:

I think the code for the class KirbyFootnotes is found in said github repo, legacy.php:

<?php

class KirbyFootnotes {

  public static function field($field, $args = []) {
    $field->value = Kirby\Footnotes\Core::run($field->value, $field->page, $args);
    return $field;
  }

  public static function bibliography($field) {
    return Kirby\Footnotes\Core::bibliography($field);
  }
}

I need this bit for a business journal I am developing, so any help is appreciated!

Shouldn’t it be

<?= KirbyFootnotes::bibliography($part->text()) ?>

instead of $part?

Nah, it gives this error:

Trying to get property of non-object:

  public static function bibliography($field) {
    $footnotes = new self($field->value, $field->page); // for this line
    $text      = $footnotes->convert(false);
    return Snippet::bibliography($footnotes->entries);
  }

I had another idea:

<?php
  $text  = $page->text()->kirbytext();
  $pages = explode('<!--pagebreak-->', $text);
  $pageCount = count ($pages);
  if($pageCount >= 1) : $pageLinkCount = 1;
  else : $pageLinkCount = 0;
  endif;

  $pages = new Collection($pages);
  $pages= $pages->paginate(1);
  foreach ($pages as $p): ?>
    <?php snippet('header'); ?>
      <article>
        <h1><?= $page->title()?></h1>
        <?php
          $field = new Field($page, null, trim($p));
          echo $field->footnotes(['bibliography' => false]);
        ?>
      </article>
      <aside>
        <h4>Bibliography</h4>
        <?= KirbyFootnotes::bibliography($field) ?>
      </aside>
    <?php snippet('footer')?>
<?php endforeach ?>

(I left out the navigation)

The only problem is that the footnotes start with 1 on the next page again.

Thank you very much. I just replaced them footnote numbers with asterisks, I mean who cares, right … :wink:

Hm, if it’s only one asterisk per page, I agree, but it might be confusing if you use multiple footnotes per page?

Well, I am using bigfoot.js in order to “tooltip” them directly in text, classic footnotes are still numbered and only appear when printed out and on screen readers.

Well, unless you could think of some other method, so I could keep the numbers? It’s very specific, but my client seems to disagree that it would be a good idea to do as I did -.-

Hey again, I just wanted to ask:
I wanted to put the top part, the logic and stuff, into a controller, only problem seems to be that my firstPage variable gets ignored. must be something obvious, but i dont get it …

<?php

return function($site, $pages, $page) {

  $text       = $page->text()->kirbytext();
  $parts      = explode('<!--pagebreak-->', $text);
  $partCount  = count ($parts);

  if($partCount >= 1) {
    $partLinkCount = 1;
  }
  else {
    $partLinkCount = 0;
  }

  $parts = new Collection($parts);
  $parts= $parts->paginate(1);
  $firstPage = $parts->first();

  return compact('parts', 'partCount', 'partLinkCount', 'firstPage');

};

and template looks like this (inside the loop):

<?php if($firstPage && $page->abstract()->isNotEmpty()) : ?>
  <?= $page->abstract()->kirbytext() ?>
<?php endif ?>

I think you’d better do it like this:

if($parts->pagination()->isFirstPage()) {
  echo 'hello';
};

works like a charm! thank you!