External pages combined with internal JSON page list

This is a tricky one to explain so i hope i manage to get the point across…

Im using the modules plugin on a site, and the auto ID plugin. I have a module that has three buttons in it that can have urls changed via a select in the panel that has a page list in it fed from a JSON route in the config, so that you can set the button to link to any page in the site. The problem is i now need to add 4 external pages to this list. These pages are not in the site, which means they do not have an ID. Ive manually set them with a ridiculously high ID, so they can never clash with a real page. The problem is the module code filters the sites pages based on the ID, and it fails because those pages are not in the site.

How can i detect that the ID is one of those 4, for each of the three buttons and feed the correct url through?

My route looks like this…

  // Page Links
  array(
    'pattern' => 'pagelist.json',
    'action'  => function() {
      header('Content-type: application/json; charset=utf-8');
      $pages = site()->index()->visible()->filterBy('template', 'not in', ['error', 'blogarticle']);
      $json = array();

      foreach ($pages as $page) {
          $json[$page->autoid()->value()] = $page->title()->value();
      }

      $json[999999999] = "https://externalone.com";
      $json[888888888] = "https://externaltwo.com";
      $json[777777777] = "https://externalthree.com";
      $json[666666666] = "https://externalfour.com";

      echo json_encode($json);
    }
  ),

And the important bit of the module code currently looks like this to get the ID & URL from the select (I know the URL in this is a bit ugly but its the only way i could get it to work):

// Link One
$cblocklinkurls = $module->cblocklinkurl();
$cblocklink = $site->url(). '/' .$site->index()->filterBy('autoid', '==', $cblocklinkurls);


// Link Two
$cblocklinkurlstwo = $module->cblocklinkurltwo();
$cblocklinktwo = $site->url(). '/' .$site->index()->filterBy('autoid', '==', $cblocklinkurlstwo);


// Link Three
$cblocklinkurlsthree = $module->cblocklinkurlthree();
$cblocklinkthree = $site->url(). '/' .$site->index()->filterBy('autoid', '==', $cblocklinkurlsthree);

Don’t use this $site->url()stuff.

Try something like this, you can define your external URLs in the config settings and then fetch with c::get()

<?php
  $highnumbers = [
    '777' => "https://externalone.com",
    '888' => "https://externaltwo.com"
  ];
  if($page = $site->index()->findBy('autoid', $cblocklinkurls)) {
    $cblocklinktwo = $page->url();
  } else if (in_array($cblocklinkurls, array_keys($highnumbers))) {
    $cblocklinktwo = $highnumbers[$cblocklinkurls];
  } else {
    $cblocklinktwo = '';
  }

I wish you wouldn’t use these unreadable variables…:pray:

Instead of storing those fake numbers, you might as well store the url itself as key in your JSON array. Would then also simplify the code, we wouldn’t need the array.

But i would still have to test wether it was a string or an integer though, right? If the key is a number, look it up with AutoID, else just spit out the value? So the route would look like this?..

// Page Links
array(
  'pattern' => 'pagelist.json',
  'action'  => function() {
    header('Content-type: application/json; charset=utf-8');
    $pages = site()->index()->visible()->filterBy('template', 'not in', ['error', 'blogarticle']);
    $json = array();

    foreach ($pages as $page) {
        $json[$page->autoid()->value()] = $page->title()->value();
    }

    $json["https://externalone.com"] = "External One";
    $json["https://externaltwo.com"] = "External Two";
    $json["https://externalthree.com"] = "External Three";
    $json["https://externalfour.com"] = "External Four";

    echo json_encode($json);
  }
),

cheeky! … They make sense to me :slight_smile:

Yes, that would be your route.

And in the module:

<?php

  if($page = $site->index()->findBy('autoid', $cblocklinkurls)) {
    $cblocklinktwo = $page->url();
  } else {
    $cblocklinktwo = $cblocklinkurls;
  }

You don’t have to check if the value is a string or a number, it is sufficient to check if it is a page or not, otherwise just print the string.

Variables: Of course, that’s up to you, but $cBlocklinkUrl is much more readable than $cblocklinkurls (which should also be singular if it is only one).

Note that I have changed your filterBy() to findBy(), because you only want to get (and you can only get) a single page, not a collection.

Sure, but im running into the old problem which is how i ended up with that ridiculously constructed URL. If i do it the way you suggest,

$site->index()->findBy('autoid', $cblocklinkurls)

The resulting URL is…

http://localhost:3000/34

but with the ridiculous way:

$site->url(). '/' .$site->index()->filterBy('autoid', '==', $cblocklinkurls)

I actually get the full URL to the page. Whats going on there then?

Well, this

$site->index()->findBy('autoid', $cblocklinkurls)

by itself will not return a URL, but ideally a page object or false.

Are you telling me that if you call the URL method you get 34 as page slug? Have you overwritten your methods in models?

Yes.

Nope. there is nothing anywhere that could interfere with this.

The code looks like this, ive set the route to what is in my last post about it (URL as key). The external links work fine, but picking any internal page gives me the number as the slug, not the url to the page that corresponds to that number:

$cblocklinkurls = $module->cblocklinkurl();
$cblocklinkurlstwo = $module->cblocklinkurltwo();
$cblocklinkurlsthree = $module->cblocklinkurlthree();

if($page = $site->index()->findBy('autoid', $cblocklinkurls)) {
 $cblocklink = $page->url();
} else {
 $cblocklink = $cblocklinkurls;
}

if($page = $site->index()->findBy('autoid', $cblocklinkurlstwo)) {
 $cblocklinktwo = $page->url();
} else {
 $cblocklinktwo = $cblocklinkurlstwo;
}

if($page = $site->index()->findBy('autoid', $cblocklinkurlsthree)) {
  $cblocklinkthree = $page->url();
} else {
  $cblocklinkthree = $cblocklinkurlsthree;
}

This works, but now the external links do not…

$cblocklinkurls = $module->cblocklinkurl();
$cblocklinkurlstwo = $module->cblocklinkurltwo();
$cblocklinkurlsthree = $module->cblocklinkurlthree();

if($page = $site->index()->filterBy('autoid', '==', $cblocklinkurls)) {
 $cblocklink = $site->url(). '/' .$page;
} else {
 $cblocklink = $cblocklinkurls;
}

if($page = $site->index()->filterBy('autoid', '==', $cblocklinkurlstwo)) {
 $cblocklinktwo = $site->url(). '/' .$page;
} else {
 $cblocklinktwo = $cblocklinkurlstwo;
}

if($page = $site->index()->filterBy('autoid', '==', $cblocklinkurlsthree)) {
  $cblocklinkthree = $site->url(). '/' .$page;
} else {
  $cblocklinkthree = $cblocklinkurlsthree;
}

Hm, I can’t currently test this with the AutoId plugin, looks like this doesn’t return a page object like it should, or does it if you dump $page?

var_dump gives me bool(false). if it put it in the if statement after setting $page it gives me nothing at all.

I now tested this in a fresh project, and the code works as expected.

Hrmm. Thats odd. Wonder why it doesnt work for me. I am at a loss. You did it inside a module, right?

No, just a blank (lang)starterkit; maybe the problem is indeed related to the modules, don’t know. But this $site->url()code just doesn’t make sense even if it delivers the correct result in your case.

Im starting to think the problem could be the data im feeding it, so i changed the vars that get the value to this

$cblocklinkurls = $module->cblocklinkurl()->value();
$cblocklinkurlstwo = $module->cblocklinkurltwo()->value();
$cblocklinkurlsthree = $module->cblocklinkurlthree()->value();

var_dump($cblocklinkurls);
var_dump($cblocklinkurlstwo);
var_dump($cblocklinkurlsthree);

So now im getting a string for each instead of an object. Can i work with that more easily? Dump result is…

string(3) "156"
string(23) "https://externaltwo.com"
string(2) "34"

before it was:

object(Field)#4836 (3) {
  ["page"]=>
  string(31) "home/modules/modulename"
  ["key"]=>
  string(13) "cblocklinkurl"
  ["value"]=>
  string(3) "156"
}
object(Field)#4838 (3) {
  ["page"]=>
  string(31) "home/modules/modulename"
  ["key"]=>
  string(16) "cblocklinkurltwo"
  ["value"]=>
  string(23) "https://externaltwo.com"
}
object(Field)#4840 (3) {
  ["page"]=>
  string(31) "home/modules/modulename"
  ["key"]=>
  string(18) "cblocklinkurlthree"
  ["value"]=>
  string(2) "34"
}

Or am i barking up the wrong tree?

Ah ha! i suspect your going to hate this but it works…

$cblocklinkurls = $module->cblocklinkurl()->value();

if (strpos($cblocklinkurls, 'http') !== false) {
    $cblocklink = $cblocklinkurls;
} else {
    $cblocklink = $site->url(). '/' .$site->index()->filterBy('autoid', '==', $cblocklinkurls);
}


Well, it’s your project…