Filtering custom objects by first letter

Permalink
Hello all,

I'm trying to make a glossary page. First, I've downloaded the Custom Objects Demo package (http://www.concrete5.org/marketplace/addons/custom-objects-demo/) and it is perfect for my requirements - as I have the Title of the object and a short description.

The problem is that when I make a new Page with the Page Type "Custom Object List" the objects are then displayed in the order as they were made. So if I created i.e. Wood first then Apple second, on the new Page Wood would be listed before Apple.

The current code is:
<ul id="custom-objects-list">
          <?php  
          $selectedCustomObjectID = intval($selectedCustomObject->getCustomObjectID());
          foreach ($allCustomObjects as $customObject) {
               $title = $customObject->getTitle();
               $handle = $txt->sanitizeFileSystem($title);
               $coID = $customObject->getCustomObjectID();
               if ($selectedCustomObjectID == $coID) {
                    ?>
                    <li class="selected">
                         <?php   echo $title; ?>
                    </li>
               <?php   } else { ?>
                    <li>
                         <a href="<?php   echo $filter_custom_objects_url . $handle; ?>">


Is there a way to filter these Objects to be displayed in order starting from their first letter, so that under A would be Apple, then B boat, ... W wood etc.

Thanks in advance!

brance
 
bbeng89 replied on at Permalink Best Answer Reply
bbeng89
If you check out the docs on the DatabaseItemList (which your CustomObjectList class extends) you'll see you have a few sorting options available to you. The docs are here:

http://www.concrete5.org/documentation/developers/system/searching-...

So in your CustomObjectList class you could set the $sortByString variable to be the title like so:

protected $sortByString = 'title asc';


Or you can use the sortBy() method:

$l->sortBy('title', 'asc');


Hope that helps!
brance replied on at Permalink Reply
brance
Hello bbeng89,

thank you very much for the hint! I've just found that in the concrete5/packages/custom_object_demo/models/custom_object_list.php there is:
class CustomObjectList extends DatabaseItemList {
public function filterByTitle($title){
   $db = Loader::db();
   $title = $db->quote("%" . $title . "%");
   $this->filter(false, '(title LIKE ' . $title . ")");
}
}


Can I use this in the custom_object_list.php file that displays the results?

Thanks again for your time, I really appreciate it!
bbeng89 replied on at Permalink Reply
bbeng89
Filtering would be the equivalent of searching. So that method is searching the custom objects based on the title that is passed into the method.

You want to look into sorting. If you always want your custom objects to be sorted by title I would add that $sortByString variable to the class-level variables of your CustomObjectsList class. So:
class CustomObjectList extends DatabaseItemList {
private $queryCreated;
protected $autoSortColumns = array("title");
protected $itemsPerPage = 10;
protected $sortByString = 'title asc'; // this will sort by title by default
...


However, if you want to sort them after you've already retrieved them you would use the sortBy method. So for example in the /custom_objects_demo/controllers/dashboard/custom_objects/search.php file in the view function you have:
$customObjectsList = $this->getRequestedSearchResults();


You could then do:

$customObjectsList->sortBy('title', 'asc');


Hopefully that makes sense!
brance replied on at Permalink Reply
brance
Ok, I've added the $sortByString = 'title asc'; into the CustomObjectList class, but when I try to retrieve the results I get
Fatal error: Call to a member function sortBy() on a non-object in

this is how I tried to do it:
<?php  
          $selectedCustomObjectID = intval($selectedCustomObject->getCustomObjectID());
          foreach ($allCustomObjects as $customObject) {
               $title = $customObject->getTitle();
               $handle = $txt->sanitizeFileSystem($title);
               $coID = $customObject->getCustomObjectID();
               $customObjectsList->sortBy('title', 'asc');
               if ($selectedCustomObjectID == $coID) {
                    ?>
                    <li class="selected">
                         <?php   echo $title; ?>
                    </li>
               <?php   } else { ?>
                    <li>
                         <a href="<?php   echo $filter_custom_objects_url . $handle; ?>">


Frankly, I am not even sure how to display the sorted array in the custom_object_list.php file, that displays the current non-sorted list of my custom objects. As the code right now just has echo $title; so I guess I have to sort the output of the $title somehow, but how?

This is really hard to figure out..
bbeng89 replied on at Permalink Reply
bbeng89
If you have defined the $sortByString variable in the CustomObjectList model then you can take this line out of your code:
$customObjectsList->sortBy('title', 'asc');


That line is something you would have to do in the controller at the time you retrieve the objects. Hopefully if you just take that line out it should work.
brance replied on at Permalink Reply
brance
Unfortunately it doesn't do anything. The list stays the same on the Page I create. The problem is probably in this piece of code:

<?php  
defined('C5_EXECUTE') or die("Access Denied.");
Loader::model("custom_object", "custom_objects_demo");
Loader::library("item_list");
$txt = Loader::helper("text");
$c = Page::getCurrentPage();
$filter_custom_objects_url = BASE_URL . View::url($c->getCollectionPath());
$this->inc('elements/header.php');
?>
<?php 
   $a = new GlobalArea('Header_Nav');
   $a->display($c);
   ?>
<div id="content-wrapper">
   <div id="main-content-inner">


The coID, is set to 1, 2, 3 ... I guess and with this code it will always print out the Custom Object with the ID 1 first, then the second, third and so on. Maybe the protected $sortByString = 'title asc'; even works but my output code is blocking it from displaying on the page.

Could that be the reason?
bbeng89 replied on at Permalink Reply
bbeng89
Hmm. What does the code look like that sets the $allCustomObjects variable?
brance replied on at Permalink Reply
brance
Here it is:
public static function getAllCustomObjects() {
   Loader::model("custom_object", "custom_objects_demo");
   $customObjectList = array();
   $customObjectList = new CustomObjectList();
   $customObjectList->createQuery();
   $customObjects = $customObjectList->get();
   return $customObjects;
}
brance replied on at Permalink Reply
brance
<?php  
defined('C5_EXECUTE') or die("Access Denied.");
/**
 *
 * A filtered list of custom objects
 * @package Item List Demo
 *
 */
class CustomObjectList extends DatabaseItemList {
private $queryCreated;
protected $autoSortColumns = array("title");
protected $itemsPerPage = 10;
protected $sortByString = 'title asc';
protected function setBaseQuery() {
   $this->setQuery('SELECT * FROM customObjects');


Here's the whole code
bbeng89 replied on at Permalink Reply
bbeng89
Try this:
public static function getAllCustomObjects() {
   Loader::model("custom_object", "custom_objects_demo");
   $customObjectList = array();
   $customObjectList = new CustomObjectList();
   $customObjectList->sortBy('title', 'asc');
   $customObjects = $customObjectList->get();
   return $customObjects;
}
brance replied on at Permalink Reply
brance
Nope, doesn't affect anything... Maybe the title attribute is missing in the custom_objects_list.php in the model folder...
this is really annoying me, as I've tried everything but nothing worked.
bbeng89 replied on at Permalink Reply
bbeng89
Man, i'm running out of ideas. So everything is displaying correctly and you aren't getting any errors, but they just aren't ordered correctly (by title)?
brance replied on at Permalink Reply
brance
Exactly.. The problem is I guess that the coID is being static and selects titles from Custom Object under ID 1, then under ID 2, then under ID 3 and so on, and prints it out in that order.
bbeng89 replied on at Permalink Reply
bbeng89
Man I really don't know. I installed a fresh copy of the Custom Objects demo and did nothing but add the line

protected $sortByString = 'title asc';


to the CustomObjectList class and that worked perfectly fine. Does it work for you if you do this on a totally fresh install of the package?

Also, you'll want to make sure you clear out your concrete5 cache just in case. You'll find the button to clear the cache in System & Settings, under the "Optimization" heading. Maybe give this a shot before anything else because the cache can cause a lot of weird problems. For development you usually want to go in to "Cache and Speed Settings" and just turn it all off. Let me know if you have any luck.
brance replied on at Permalink Reply
brance
It is really weird. I'll tell you what I did now:

1. Cleared the cache and disabled it in the settings.
2. Deleted the existing Custom Objects Demo (vers. 0.9.1) and all of its content.
3. Downloaded a fresh copy, unziped it.
4. Before even putting it in the Packages folder & installing it I have edited the custom_object_list.php file (located in: custom_objects_demo/models/custom_object_list.php) adding the
protected $sortByString = 'title asc';
in
<?php  
defined('C5_EXECUTE') or die("Access Denied.");
/**
 *
 * A filtered list of custom objects
 * @package Item List Demo
 *
 */
class CustomObjectList extends DatabaseItemList {
private $queryCreated;
protected $sortByString = 'title asc'; // <-- HERE
protected $autoSortColumns = array("title");
protected $itemsPerPage = 10;
protected function setBaseQuery() {
   $this->setQuery('SELECT * FROM customObjects');


5. Saved it, copied the package into the Package folder. Installed it via Add Functionality.
6. After installing I went into the fresh installed Custom Object Demo (now found in the Full Dashboard) and added 3 custom objects first was Berry, second was Apple, third was Sun.
7. Went to full Sitemap, added a new page with page type Custom Object List.
8. Visited the site, and still it lists the damn objects as
Berry
Apple
Sun, instead of
Apple
Berry
Sun.

I really have no freaking idea what am I doing wrong or why this is happening..
brance replied on at Permalink Reply
brance
It finally works!!

I don't know, but when I changed the custom_objects_list.php in the folder htdocs/concrete 5.6.2/concrete/packages/custom_objects_demo/models/ adding the protected $sortByString = 'title asc'; it worked. The problem was that I was changing the custom_object_list.php in the wrong folder htdocs/packages/custom_objects_demo/models/

Is there an explanation for this? So the initial folder for installing addons is just there to install/put the items into the main concrete folder or am I wrong? Because after changing anything in the packages folder nothing happened, only when I found that there is another folder in the main concrete folder, and changed the files there it started to work. Still if I delete the contents from the htdocs/packages/ folder I get an error. This is really confusing!!

But anyways you helped me out! Thank you a lot!
bbeng89 replied on at Permalink Reply
bbeng89
Hm, that is very strange. I don't think there should be anything in the /concrete/packages folder. Maybe that is part of your problem. Something strange might have been going on with the overrides. Maybe try taking the package out of the /concrete/packages folder and then making the change to the file in /packages.

I'm glad I was at least able to help you get the sorting working!
brance replied on at Permalink Reply
brance
Damn right, I copied the working folder in the concrete/pacakges and replaced it with the one in packages/ by deleting the old version and it still works. It has probably to do with that the package was in the wrong folder... strange that it even happened. So it should be that all packages are placed in the concrete 5.6.2/packages folder instead of concrete 5.6.2/concrete/pacakges?

just to be sure.
bbeng89 replied on at Permalink Reply
bbeng89
Yes, that's right. All your packages should go in the /packages folder. I'm honestly not sure what the /concrete/packages folder is used for but in all my projects it is just empty.