Question

Inside my processor class I have a statement that grabs all the projects from a db table and formats them to be displayed. This method does not work and halts at the getCollection call.

class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{

    public function initialize() {
        return parent::initialize();
    }

    public function process() {
        $result = $this->modx->getCollection('ManagerProjects');
        $project_names = array();
        foreach ($result as $row) {
            $projects = unserialize($row->get('manager_projects'));
            foreach($projects as $short_code => $project) {
                $project_names[] = array('project_name' => $project, 'project_short_code' => $short_code);
            }
        }
        return '{"total":' . count($project_names) . ',"results":' . $this->modx->toJSON($project_names) . ',"success":true}';
    }
...
}

This code that uses plain SQL does work:

class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{

    public function initialize() {
        return parent::initialize();
    }

    public function process() {
        $leadersql = "SELECT * FROM `modx_manager_projects`";
        $query = $this->modx->query($leadersql);
        $project_names = array();
        while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $projects = unserialize($row['manager_projects']);
            foreach($projects as $short_code => $project) {
                $project_names[] = array('project_name' => $project, 'project_short_code' => $short_code);
            }
        };
        return '{"total":' . count($project_names) . ',"results":' . $this->modx->toJSON($project_names) . ',"success":true}';
    }
...
}

I use similar method to the first which saves ManagerProjects and works fine, so I don't think it has to do with the model declaration. I could easily just use the second method above since it seems to work, but I want to use the best method.

What is wrong with the first method?

Is the first method the proper way to implement SQL in the Modx processor? Or is there a better way?

Was it helpful?

Solution 2

Because you do it wrong! Just see this. The right way to do it, is something like this:

<?php
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
    public $classKey = 'ManagerProjects';

    public function iterate(array $data) {
        $list = array();
        $list = $this->beforeIteration($list);
        $this->currentIndex = 0;
        /** @var xPDOObject|modAccessibleObject $object */
        foreach ($data['results'] as $object) {
            if ($this->checkListPermission && $object instanceof modAccessibleObject && !$object->checkPolicy('list')) continue;
            $projects = unserialize($object->get('manager_projects'));
            foreach($projects as $short_code => $project) {
                $objectArray = array('project_name' => $project, 'project_short_code' => $short_code);
                if (!empty($objectArray) && is_array($objectArray)) {
                    $list[] = $objectArray;
                    $this->currentIndex++;
                }
            }
        }
        $list = $this->afterIteration($list);
        return $list;
    }

}

OTHER TIPS

We can do this task easier a little bit.

@Vasis is right but we can use base prepareRow method instead of reloading iterate method:

<?php
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
    public $classKey = 'ManagerProjects';
    protected $projects = array();

    public function prepareRow(xPDOObject $object) {
        $_projects = unserialize($object->get('manager_projects'));
        foreach($_projects as $short_code => $project) {
            $this->projects[] = array('project_name' => $project, 'project_short_code' => $short_code);
        }
        return parent::prepareRow($object);
    }

    public function outputArray(array $array,$count = false) {
        $count = count($this->projects);
        return parent::outputArray($this->projects,$count);
    }
}
return 'GlobalLinkSettingsProcessor';

There we can see one of modx ‘features’. In modObjectGetListProcessor process method we can see this:

public function process() {
    $beforeQuery = $this->beforeQuery();
    if ($beforeQuery !== true) {
        return $this->failure($beforeQuery);
    }
    $data = $this->getData();
    $list = $this->iterate($data);
    return $this->outputArray($list,$data['total']);
}

getData method returns a list of objects and it goes to iterate method (where we can check if the object is accessible and change the list of these objects on demand). If you don't have access to some of objects we'll get changed list. And it goes to outputArray method but second parameter is still old for it. So you should count them again.

This is solution is quite well but you tried to get data which is stored in object's field. So afterIteration method will be unusable for further extension in my version of processor. But who cares? :)

P.S.: About your first version of processor. modObjectGetList processor is ready for getting collection. So you have not to use getcollection method. Just add proper classKey property to it. Another way is in modProcessor extension. It gives to you a base structure. But you can make your own kind of stuff.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top