Expression Engine Module tables and datasort - codeigniter

I am currently working on a custom module add-on and I wanted to be able to use sorting and filtering on the a table in my control panel admin. I am using the EE table class and form helper. I'm trying to follow the documentation here for setting it up, but when I call try to call the '_datasource' method in my class I get this error
Fatal error: Call to undefined method Content_publish::_datasource() in /home/public_html/system/expressionengine/libraries/EE_Table.php on line 162
I have a feeling it's a scoping issue, but in the table class '$this->EE->table->datasource()' method you are supposed to just pass a string value with the name of your datasource function which is what I'm doing.
I don't seem to be the only one with this issue. There are more details and code examples on this EE Discussion forum thread
The documentation is not really clear. I also tried looking at EE's own comments module to see if i could figure it out, but no luck. Anyone have experience with this?
Here is the method I'm calling:
$data = $this->EE->table->datasource('_datasource');
And this is my function in my class:
function _datasource()
{
// ....
// $query comes from DB result set code above.
// I have omitted it here for brevity
$datarows = array();
foreach ($query->result_array() as $key => $row)
{
$datarows[] = array(
'entry_id' => $row['entry_id'],
'date' => date('Y-m-d',$row['entry_date']),
'author' => $row['screen_name'],
'payment' => $payment_amount,
'status' => $status,
'title' => $edit_href.$row['title']."</a>"
);
}
return $datarows;
}

Your datasource callback function must be on your Module_mcp class (looking at your forum thread you are trying to use it on a plugin which would explain the error).
If you want to put the datasource method on a different class, then just add this line right before you call datasource() to trick the table library into using the correct class:
// ensure table callbacks use this class rather than our MCP file
$this->EE->_mcp_reference =& $this;
$data = $this->EE->table->datasource('_datasource');
The table and form_validation libraries are the only two which use the special _mcp_reference variable, so I can't see any side effects to changing it, and have successfully done this in at least two modules.
On a side note, if you want a good example of how to use the built in tablesorter, take a look at system/expressionengine/controllers/cp/members.php. The documentation is pretty bad, but the source code always tells the truth :)

I've been having issues too and have a mixed solution of generate() and datasource working. Here it is here:
In my mcp file:
public function index()
{
$this->EE->cp->set_variable('cp_page_title', lang('my_module_name'));
$data = $this->EE->table->datasource('_datasource');
return $this->EE->load->view('index', $data, TRUE);
}
public function _datasource()
{
$headers = array(
'name' => array('header' => 'Name'),
'color' => array('header' => 'Color'),
'size' => array('header' => 'Size')
);
$rows = array(
array('name' => 'Fred', 'color' => 'Blue', 'size' => 'Small'),
array('name' => 'Mary', 'color' => 'Red', 'size' => 'Large'),
array('name' => 'John', 'color' => 'Green', 'size' => 'Medium'),
);
return array(
'rows' => $rows,
'headers' => $headers
);
}
In my index view file:
$this->table->set_columns($headers);
$this->table->set_data($rows);
echo $this->table->generate();
Seems to be working at the moment and I've not tried pagination yet, but sorting works.

Related

core/html_select set aria-selected Magento 1

I'm searching for a solution with the magento buildin way to create html select blocks, with aria-required. I can display basic attributes like the id or the class for example, but not this attribute.
Here is bellow my two essay:
my first essay:
$select = Mage::app()->getLayout()->createBlock('core/html_select');
$select->setName($name)
->setClass($class)
->setId($id);
->setArialRequired($ariaRequired); //doesn't work
my second essay:
$select = Mage::app()->getLayout()->createBlock('core/html_select');
$select->setData(array(
'name' => $name,
'class' => $class,
'id' => $id,
'aria-required' => $ariaRequired //doesn't work
));
I expect the aria-required="true", but i have nothing.
Here is the solution :
->setExtraParams('aria-required=true');

Relations in resources?

So I'm planning to start using resources for my "API" (vue endpoint). So I started to search for some tutorials about the subject, and found a youtuber that describes the process. And I started making my own API resource. The youtuber shows briefly how to use the relations, but the thing is that I receive Property [description] does not exist on this collection instance. when trying to use the relation in the resource.
The current setup is:
$stack = Stack::select(['id', 'name', 'subject_id', 'description', 'image'])->where('id', '=', $requestId)->first();
$questions = $stack->load('question.choiceInRandomOrder');
return $questions;
And with resource it would be something like (notice choiceInRandomOrde, I would need that relation also):
return [
'subject' => $this->subject->name,
'name' => $this->name,
'slug' => $this->slug,
'description' => $this->description,
'image' => $this->image,
'questions' => [
'description' => $this->question->description,
'is_info' => $this->question->is_info,
'source' => $this->question->source,
'image' => $this->question->image,
]
];
}
And for testing, I have setup the following in my routes web.php
use App\Stack;
use App\Http\Resources\StackResource;
Route::get('/json', function(){
$stack = Stack::find(2);
return new StackResource($stack);
});
You try to access the name of subject in 'subject' => $this->subject->name, but you do not load the relation.
i don't know if i'm right but i thnk it has to be with the fact that ure not doing an Eloquent call but a Query Builder call (when doing $stack = Stack::select ... ). Why select just some fields in the call if you can choose the parameters to show directly in the model class? (see this).
Try to doing an Eloquent call instead (something like Stack::find(1)) and test it. It should work.

How to add categories in Joomla 2.5

Does anyone know how to properly insert new content categories to the DB programatically?
For each post in the categories table, there is also a post saved in the assets table with lft and rgt set.
Is there any native Joomla class I can use for this instead of plain SQL?
Please Please Only use the native classes, which categories will handle for you seamlessly. As soon as you add categories the whole thing will be handled automagically. Just look at any core component to see how.
It is not easy to update the assets table using sql, it is all very specifically managed and part of a complex series of foreign keyed tables.
Extend JTable or JTableContent to handle this.
Here is some code I just whipped together that just uses the JTableCategory class, so it can be used simply on the front or admin side of Joomla
$table = JTable::getInstance('category');
$data = array();
// name the category
$data['title'] = $title;
// set the parent category for the new category
$data['parent_id'] = $parent_id;
// set what extension the category is for
$data['extension'] = $extension;
// Set the category to be published by default
$data['published'] = 1;
// setLocation uses the parent_id and updates the nesting columns correctly
$table->setLocation($data['parent_id'], 'last-child');
// push our data into the table object
$table->bind($data);
// some data checks including setting the alias based on the name
if ($table->check()) {
// and store it!
$table->store();
// Success
} else {
// Error
}
Naturally you would want to get the data pieces set correctly, but these are the core ones to set.
Here is a function I've created just for this purpose, after some digging & experimenting.
It uses core classes, so it needs an access to them (for me it's basically a part of Joomla component).
Mind, it's for Joomla 3, for Joomla 2.5 and before, you need to change JModelLegacy to JModel.
function createCategory( $name, $parent_id, $note )
{
JTable::addIncludePath( JPATH_ADMINISTRATOR . '/components/com_categories/tables' );
$cat_model = JModelLegacy::getInstance( 'Category', 'CategoriesModel' );
$data = array (
'id' => 0,
'parent_id' => $parent_id,
'extension' => 'com_content',
'title' => $name,
'alias' => '',
'note' => $note,
'description' => '',
'published' => '1',
'access' => '1',
'metadesc' => '',
'metakey' => '',
'created_user_id' => '0',
'language' => '*',
'rules' => array(
'core.create' => array(),
'core.delete' => array(),
'core.edit' => array(),
'core.edit.state' => array(),
'core.edit.own' => array(),
),
'params' => array(
'category_layout' => '',
'image' => '',
),
'metadata' => array(
'author' => '',
'robots' => '',
),
);
if( !$cat_model->save( $data ) )
{
return NULL;
}
$categories = JCategories::getInstance( 'Content' );
$subcategory = $categories->get( $cat_model->getState( "category.id" ) );
return $subcategory;
}
You can perhaps use the save() in category.php file.
File location: root\administrator\components\com_categories\models\category.php
It saves the form data supplied to it!
The JOS_assets table is to store the ACL for each asset that is created.
If you do not update this table while programatically creating the category, the default ACL will apply. And when later you open and save the category in the administrative panel, the ACL will be updated as it should have been by core Joomla!.
You can create an SQL query very easily though and update the asset table as well. Its easy to understand once you open the table's content in phpmyadmin.

Cakephp: choose which data to save after login

I cannot understand how to choose which user data to save after login. I have noticed that I can only change the recursivity of the model, but I cannot choose individual fields to use.
For example, normally Cakephp saves in session all user fields except the password, even the data that I don't need and I do not want stored.
If I increase the recursion, Cakephp saves all the fields of related models.
Is there a way as for the "fields" parameter of the Model find method?
I know that after login I can recover the data that I miss and add them in session, merging to those already stored, but I want to avoid making another query and find a more elegant solution, if it exists.
Thanks.
As of Cake 2.2, you can add a contain key to your authentication options to pull related data. Since the contain key accepts a fields key, you can restrict the fields there:
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'contain' => array(
'Profile' => array(
'fields' => array('name', 'birthdate')
)
)
)
)
)
);
If you want to change the fields the user model searches for, you can extend the authentication object you're using. Generally the users table contains a minimal amount of information, so this isn't usually necessary.
However, I'll give an example anyway. We'll use the FormAuthenticate object here, and use most of the _findUser method code from the BaseAuthenticate class. This is the function that Cake's authentication system uses to identify the user.
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class MyFormAuthenticate extends FormAuthenticate {
// overrides BaseAuthenticate::_findUser()
protected function _findUser($username, $password) {
$userModel = $this->settings['userModel'];
list($plugin, $model) = pluginSplit($userModel);
$fields = $this->settings['fields'];
$conditions = array(
$model . '.' . $fields['username'] => $username,
$model . '.' . $fields['password'] => $this->_password($password),
);
if (!empty($this->settings['scope'])) {
$conditions = array_merge($conditions, $this->settings['scope']);
}
$result = ClassRegistry::init($userModel)->find('first', array(
// below is the only line added
'fields' => $this->settings['findFields'],
'conditions' => $conditions,
'recursive' => (int)$this->settings['recursive']
));
if (empty($result) || empty($result[$model])) {
return false;
}
unset($result[$model][$fields['password']]);
return $result[$model];
}
}
Then use that authentication and pass our new setting:
public $components = array(
'Auth' => array(
'authenticate' => array(
'MyForm' => array(
'findFields' => array('username', 'email'),
'contain' => array(
'Profile' => array(
'fields' => array('name', 'birthdate')
)
)
)
)
)
);
I just spent a while on this problem, only to find out that a 'userFields' option has been implemented as of Cake 2.6
Have a look at the docs here:
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html

ZF2: How do I implement a custom filter?

I've been working with Zend Framework 2 for a few weeks now, and, even though the documentation online is pretty incomplete, I managed to build up a first draft of my website.
Unfortunately, I got stuck while trying to implement a custom version of the Zend\Filter\File\Rename filter; here I sum up what I've done:
1) In my module called 'Library', created the file
src\Library\Filter\File\Rename.php
namespace Library\Filter\File;
use Traversable;
use Zend\Filter;
use Zend\Filter\Exception;
use Zend\Stdlib\ArrayUtils;
class Rename extends Filter\AbstractFilter {
static $uploadDir = '/srv/default/htdocs/public/uploads/';
public function filter($value) {
do {
$newname = md5(uniqid(time()));
} while(file_exists(self::uploadDir . $newname);
if (rename($value, self::uploadDir . $newname) !== true)
throw new Exception\RuntimeException(sprintf("File '%s' could not be renamed. An error occurred while processing the file.", $value));
return self::uploadDir . $newname;
}
}
As you can see, is pretty simple. Here's the module config:
module.config.php
<?php
return array(
'controllers' => array(
// Invokables don't support dependencies
'invokables' => array(
'myFileRename' => 'Library\Filter\File\Rename',
),
));
While the form is:
[...]
public function getInputFilterSpecification() {
return array(
'file' => array(
'required' => false,
'filters' => array(
// Custom Renamer
array('name' => 'myFileRename'),
),
)
);
}
}
?>
But this is not working, as I always get an exception:
Fatal error: Uncaught exception 'Zend\ServiceManager\Exception\ServiceNotFoundException' with message 'Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for myFileRename' in /srv/default/vendor/ZF2/library/Zend/ServiceManager/ServiceManager.php:420
Stack trace:
#0 /srv/default/vendor/ZF2/library/Zend/ServiceManager/AbstractPluginManager.php(108): Zend\ServiceManager\ServiceManager->get('myfilerename', true)
#1 /srv/default/vendor/ZF2/library/Zend/Filter/FilterChain.php(179): Zend\ServiceManager\AbstractPluginManager->get('myfilerename', NULL)
#2 /srv/default/vendor/ZF2/library/Zend/InputFilter/Factory.php(263): Zend\Filter\FilterChain->attachByName('myfilerename', Array)
#3 /srv/default/vendor/ZF2/library/Zend/InputFilter/Factory.php(171): Zend\InputFilter\Factory->populateFilters(Object(Zend\Filter\FilterChain), Array)
#4 /srv/default/vendor/ZF2/library/Zend/InputFilter/Factory.php(237): Zend\InputFilter\Factory->createInput(Array)
#5 /srv/default/vendor/ZF2/library/Zend/Form/Form.php(672) in /srv/default/vendor/ZF2/library/Zend/ServiceManager/ServiceManager.php on line 420
Unfortunately I found no article on the entire internet to help me with this, and I still get this error even when aliasing my filter as a factory :/ What do I have to do?
You load the filter as if it is a controller (hence, the controller key in your module config). The filter has a plugin manager, but for this filter you do not need the plugin manager. There is also no link in the filter plugin manager with the MVC configuration.
The most simple way is to just instantiate the filter yourself. It should be something like this that would work:
use Library\Filter\File\Rename as RenameFilter;
public function getInputFilterSpecification()
{
return array(
'file' => array(
'required' => false,
'filters' => array(
new RenameFilter,
),
)
);
}
just use:
'name' => 'file',
'required' => false,
'filters' => array(
array('name' => 'Library\Filter\File\Rename'),
),
had the same problem... this was the solution for me...

Resources