Create new page programatically within the panel

Hi all,

So if I want to create a sort of “Archive” page outside of the panel.
Well no problem, the code below works well and are quite self explained.

My question is this :
How do I create this from within / inside the panel ?

I push the “save” button and it will automatic fetch all children(index) pages that
has the “pager” checkbox checked and create the children…

In a,
custom field ?
in config ?
some where else ?

if($page->archive() == '1') {

        foreach($page->index()->visible() as $child) {
            if ($child->pager() == '1') {

                try {

                    $ID = (string)$child->uid();

                    $order = $page->children()->visible()->count() + 1;

                    $newPage = $page->children()->create($ID, 'page', array(
                        'title' => $child->title(),
                        'text' => $child->text()
                    ));

                    $newPage->sort($order);

                    echo '<p>The new page has been created </p>';

                } catch(Exception $e) {
                    echo '<p>' . $e->getMessage() . '</p>';
                }

            }
        }

    }

And when I am on that “child” page and check the field “pager” and hit save it should
automatic create a new page on the Archive page. (so I don´t have to go back and push the save button on the archive page)…

Hint:
Look at

Creating pages programatically?

and at

Subpage builder

Thanks, already looked at both…
My question was from within the panel…

Since panel only modifies the .txt files (in /content/) with the save button you will have to call a page or file from outside the panel.

Like this:

  1. create a template (e.g. /site/templates/create-archive.php) with your php code and may be some output for error logging
    (some code for checking if a user is logged in is reccomended since this page is accessible from “public”)
  2. create a page based on that template. No content necessary, just the title.
  3. create a widget that calls this panel-external page or call this page itself from the url while logged in
    you can also create an info-field within the page blueprint that contains a link to the page (e.g. yoursite.com/create-archive/) if you do not want to switch pages

What this does is: you call code operations from “within” the panel without having to modify the panel itself.
This is sort of a workaround of getting things done without having to dig into the panel too much.

Hope I did not mess up the explanation too much. :smiley:

/edit: you can surely do this with a widget and not having to create a page/template for this.

1 Like

thanks @andi242 !
I kind of solved it with a hidden custom field, that actually works quite well.
In debug mode for the moment, will post my final solution later today.

A hidden field in the template? sounds interesting, looking forward to your solution. :smile:

This works quite well.
The Idea is this.

When you use category, tags and stuff to organize your content, you don´t
get a clear view of what is happening to your content and you don´t have
the ability to organize it on each level( change content, sort order, style etc…)

Well now you can… It is very powerful in the meaning of full control.

For an example :

First you define your structure:

Home > Sport > Fotball > England > Premier League

Then you do your “post” (Arsenal) :
Home > Sport > Fotball > England > Premier League > Arsenal

In my case I have 2 checkboxes that define the page. If it´s a
"Archive" or a “post”. All parents pages with Archive “checked” will get
the post “Arsenal”.

Then if you for instance want to save the hole post “thread” in one go,
I have 1 “frontsave” and 1 “backsave”. I have one field for how the post will
display when it is a child of a page and 1 when you are on actually page.

So if you check the “frontsave” and hit the save button it will update all posts on each
level in one go… This is kind of nice, In cases you don´t need to display the post different on every level…

In your “create, update” array you put all your fields.

Hope this make some sense ; )

It ´s in beta mode so, the code is probably not the best and most effective,
hope you guys find it interesting and are willing to collaborate on it.

Your Monk.

class PagerField extends BaseField {

   public function template() {

      $page = $this->page();
      $site = site();


      if($page->pager() == '1' && $page->isVisible()) {
           foreach($page->parents()->visible() as $parent) {
               if ($parent->archive() == '1') {

                   try {
                       $ID = (string)$page->uid();

                       $order = $parent->children()->visible()->count() + 1;

                       $newPage = $parent->children()->create($ID, 'page', array(
                           'title' => $page->title(),
                     'fronttext' => $page->fronttext(),
                     'backtext' => $page->backtext()
                       ));

                       $newPage->sort($order);

                   } catch(Exception $e) {
                  continue;
                   }

               }
           }
       }

      if($page->frontsave() == '1') {
         foreach($site->index()->visible() as $child) {
            if($page->uid() == $child->uid()) {

               try {
                  $child->update(array(
                     'fronttext' => $page->fronttext()
                  ));

               } catch(Exception $e) {
                  continue;
               }
            }
         }
      }

      if($page->backsave() == '1') {
         foreach($site->index()->visible() as $child) {
            if($page->uid() == $child->uid()) {

               try {
                  $child->update(array(
                     'backtext' => $page->backtext()
                  ));

               } catch(Exception $e) {
                  continue;
               }
            }
         }
      }


   }

And in your blueprint:

ohThisIsCool:
   type: pager

Ah, the field approach is much better in this case :smiley:

I’m not sure if I get it correctly, though.

What you’re doing is to ‘archive’ a post by activating your checkbox.
Save button literally creates copies of this archived post to all parent pages. if content in the archive post is changed, it updates all parent copies of this.

Right?

What you’re achieving is an archive view for all parent folders/pages?

I also hacked the panel a little bit to display which “post” that are connected to which “archive”.

Hmm yeah I think ; )

You basically create your so called post “arsenal” and then all parents
with the checkbox “archive” active will get a copy(child) of the page “arsenal”.

Then if you want you can on each “archive” page change order, content, style etc, of the page “Arsenal”.

Then later on if you want to change them all in one go, you tick the for instance “frontsave” box and it will update all the instances of the page “Arsenal” (uid). It does not matter where you are in hierarchy it finds all pages with the uid Arsenal.

Although not best approach to use site()->index() (lazy approach) will fix it so its looks in the same level(hierarchy) .

I see. : )

no offense, but could you achieve this with a filter instead of creating copies?

// check if parent page is archived
if($page->archive() == 1) {

    // if so, grab all children that are archived, too
    $items = $page->children()->filterBy('archive', 1);

    // loop through $items and echo content or whatever
    foreach ($items as $item) {
        echo $item->title()
        // etc....
    }
}

Not sure if this goes through sub-children, though.

for sub children use index() instead of children().

There are no problem to fetch, filter, sort the pages.
But the point of all this is the ability to manually change the appearance like (order, style, content) of each “post” on each level. There are no way of doing this if you just fetch them in an array. Also you can set an overall rule on each “archive” page how the “post” are going to displayed.

For instance. In “Archive” page football, create a field to change background color on all, override it with setting the background color on the post, sort them, do what ever you want and so on… ; )

1 Like

Now I get it :smiley:

Cool :stuck_out_tongue_winking_eye:

1 Like

If anyone now how to do this without the need to make a copy of the page on each level i would be very happy. Was able to get it going with structure fields, but did not feel like it belonged there… I cluttered up the page with long list. Then you have to be on two “fronts” like okey first I check all the pages, then I check all the structures…

Maybe trying to hack the panel but that´s no fun…

When you look at this it feels kind of ridiculous tho haha omg… :grimacing:

…and that’s how you get a website with 1 million files. :grin:

I am thinking of a dropdown on each parent page that lets you select from a bunch of css to get different styles for each page.

switch ($page->style()) {
    case "football":
        echo css('path/to/football.css');
        break;
    case "hockey":
        echo css('path/to/hockey.css');
        break;
    // default, etc...
}

call this in the header snippet…

Yeah lol… :scream: but hey hopefully the client will never look there haha :sunglasses:
Ahh crap will do A try with the structure thing… or maybe trying out a more simple page relation plugin of some sort…

I will probably trying doing a proper plugin and post it here later…

Thanks @andi242 !