How to set quicksearch initial value? - php

where I want tu put an initial value.
I have seen that quicksearch has 'q' element but I can't access it, for example this does not find the q element:
$quickSearch->getElement('q');
How can I access the quicksearch in order to set an initial value?

Looking at the source of it can help you find things out. Agile Toolkit is designed in a way where developer should take advantage of the knowledge of the source code.
QuickSearch is derived from Filter which is derived from Form, so there should be addField somewhere. Looking at the QuickSearch, you'll find it inside recallAll() function. There are no calls to this functions so we should look into the parent class - Filter.
Filter sets up a hook in api to call recallAll after initialization have been finished. That means to be able to access the field you can either redefine a method or add a hook yourself.
Hook:
$this->api->addHook('post-init',function() use($quickSearch){
$quickSearch->getElement('q')->set('hello');
});
Extending
class MyQuicksearch extends QuickSearch {
function recallAll(){
parent::recallAll();
$this->getElement('q')->set('hello');
}
}
Finally you can take advantage of knowing where recallAll is loading their default values from and simply do this:
$quicksearch->memorize('q','hello');

to address this, we must first understand how the Search Field of the QuickSearch Class is added to the Grid Basic Class. so upon investigation of the source code, we can see that:
QuickSearch Class does not track (or save a PUBLIC reference of) the Form_Field q
Form_Field q is ONLY added DURING the Rendering phase of the grid
knowing these, we can now proceed adding the modifications to address item #1.
first, we need to add a variable to track the Form_Field q in the QuickSearch Class:
var $search_field=null; // add this line (1)
function recallAll(){
$ff=$this->addField('line','q','');
$this->search_field=$ff; // and this line (2)
parent::recallAll();
:
:
}
second, to address item #2, on our page where the grid is defined, we need add a follow-up hook, example:
class page_gridsearchtest extends Page {
var $search=null;
function init() {
parent::init();
$g = $this->add('MVCGrid');
$g->setModel('Employees');
if($g){
$this->search=$g->addQuickSearch(array('fullname'));
if($this->search)
$this->api->addHook('post-init',array($this,'MyHook')); // add hook
}
}
function MyHook(){ // hooked method
if($this->search->search_field) {
if($this->search->search_field->get()=='')
$this->search->search_field->set('Juan'); // set initial search if blank
$this->search->search_field->setCaption('Employee Name Search');
}
}
}
this will set a CAPTION beside the QuickSearch field and add a DEFAULT search text if the search field is empty.
if this is just a one-time thing, then this may be useful as a quick fix because directly making changes to the library source is very unorthodoxed and does not follow the OOP concept of extending and sub-classing as promoted by ATK.

Related

Is there a way to change the format on how Yii2 creates ID's for fields within ActiveForm?

I'm using ActiveForm with Yii2 and by default it seems to generate default id's for fields if you don't set one, in the format of:
{action-name}-{field-name}
So for example if I had a field with the name of foo_bar used in an action of actionSettings then the id of this field would be generated as:
settings-foo_bar
I would prefer this to just be foo_bar.
Is this possible to change on a form by form basis?
Based on the answer provided by #Bizley I was investigating how the method calculated the name and found out there is another way to achieve this as well.
You can simply override the formName method of your respective model to return a blank value, such as:
public function formName() {
return '';
}
Whilst this has less overheads as you don't need to create a new class, it will also affect other things within your form such as the field names and also should not be used for forms which contain multiple different models as explained here.
Lastly, because this question was about changing how Yii formats the id, #Bizleys answer is the correct one; my solution is just another option of possibly achieving it another way.
ActiveField id is by default created based on the form's model name and field's name.
If you want to change it for the whole form override the method that does it:
protected function getInputId()
{
return $this->_inputId ?: Html::getInputId($this->model, $this->attribute);
}
and use this modified class in your form.

How to use usort on an object with an array of arrays

Simply put: I need to sort an array of objects based on a specific value of a specific array element inside a class property.
This would be great, if it worked:
In this picture, the code illustrates what I want: I want to be able to tell usort to look in a specific array element and find the priority key, and sort based on that integer value.
So, for a given hook (hook-foo), I would need the comparison to be done on:
$plugin->hooks['hook-foo']['priority']
For another hook (hook-bar), for which the same plugin might act upon, I need the sort to look at:
$plugin->hooks['hook-bar']['priority']
if usort supported me sending an arbitrary argument to it, this would be solved. But, the code pictured below was written to illustrate my point and then tested because "maybe it will work". It didn't.
How do I rearrange this to get the sort I need?
(Note: Plugin::hooks is an array of arrays and represents all the metadata required to execute a plugin on a given hook. So, it may contain 'hook-foo' and 'hook-bar', which do not execute at the same time. It may also contain one or the other, or... neither.)
Edit: Here are the example structures, which may help illustrate my point. This shows 2 of 14 plugins loaded.
You can see that each plugin responds to multiple different hooks.
So, if I wanted to control the order for a given hook, I should only have to change the priority of that hook.
For example, here: you can see the cli-init hook fires a method of the class declareMySelf, which simply says: "Plugin XYZ loaded" in the command line interface. Both of the priorities are 50, so it will display them in whatever order the system finds the plugins.
But, if I wanted to display "PHP Mailer loaded" BEFORE I display "Config / Settings management loaded", all I should have to do is drop the PHP Mailer plugin priority to 40.
You should probably have a $hookSearchKey property within your class and set it with a setHookSearchKey() method when needed:
class Whatever {
// ...
private $hookSearchKey
public function setHookSearchKey($key) {
$this->hookSearchKey = $key;
}
//... this is your method of sorting:
public function fooSort(...) {
$this->setHookSearchKey('hook-foo');
usort(...); // do your thing
}
//... this is your method of sorting:
public function barSort(...) {
$this->setHookSearchKey('hook-bar');
usort(...); // do your thing
}
//...
public function sortByHookPriority(...) {
if($a[$this->hookSearchKey] == $b[$this->hookSearchKey]) return 0;
// ...
}
}
Would this work for you?

How do I add a custom field to a model in Laravel?

I'm very new to Laravel and php frameworks in general, so sorry if I miss anything basic. I've created a new model called Journey in my application which extends the standard Eloquent model. What I've noticed is that I'm using my Journey model in two different Controllers and I'm duplicating a bit of code because of it.
Essentially, what I'm doing is I'm taking the title of a Journey and I'm formatting it with a custom class to clean the title (convert to lowercase, add hyphens, remove whitespace, etc) so I can append it to my page URLs.
In one controller, I'm calling:
$journey = Journey::find($id);
$journey->cleanURL = Url::clean($journey['name']); // This creates a new element/property with a clean string
And in the other, I'm calling:
$journeys = Journey::all();
foreach ($journeys as $journey) {
$journey->cleanURL = URL::clean($journey['name']);
}
It would be inappropriate to add a fixed field to my database with the cleaned URL because I may change the title (which the cleaned URL is based on) at any time and I'd like the URL to update automatically in this event. However, saying this, I'm repeating myself by calling Url::clean twice.
What I'd like to do is write a method or alter an existing method, so that when I call Journey::all() or Journey::find() or any query-based method, the URL field is already present and filled. I've tried looking through some of the Vendor/Eloquent files, but they just make me confused.
How would I go about doing this?
You can use accessor for this.
Add to your Journey model the following function:
public function getCleanUrlAttribute($value)
{
return Url::clean($this->name);
}
Now you will be able to use:
$journey = Journey::find($id);
echo $journey->clean_url;

CodeIgniter / Pyrocms - how do I make my custom modules sub-navigation alter to suit the section?

I'm making a custom module for PyroCMS, and I want to get the section menu working with regard to applying the current class. The CMS php, which I don't want to change looks like this:
<li class="<?php if ($name === $active_section) echo 'current' ?>">
When I'm viewing /admin/courses/ this is correct, and the first navigation element has the class, current.
$name is taken from the language file, as set up in details.php.
$active_section is taken from the view, and is equal to
$this->_ci_cached_vars['active_section']
However when I view /admin/courses/chapters/, 'courses' is still determined by the system to be the current section, so the navigation is confusing.
What I need is a way of changing the value of $active_session in the view acording to which function of the controller (index, chapters or pages) is being used.
I've tried changing the value of $this->_ci_cached_vars['active_section'] in each controller function, but that doesn't work. Any ideas?
I'm sure there's something basic I'm missing completely.
Got it.
I'm using multiple methods in one controller, and the 'protected $section = 'courses'; line, which happens before the index method, was setting the section for everything.
It couldn't be set a second time within another method, but there is a way to define a section within a method.
$this->template->active_section = 'section';
Starting my method as follows gave me what I wanted.
public function chapters(){
//Set active section
$this->template->active_section = 'chapters';
...
}

How do I use a custom #theme function to a fieldset in a drupal module?

I have a module that builds a form that includes a fieldset. Instead of using the <legend> element to render the fieldset title, I want to place this content in a <div> element instead. But I want to change the behavior only for the form returned by my module, so I don't want to place any new functionality into my theme's template.php file.
In mymod.module I have defined:
// custom rendering function for fieldset elements
function theme_mymod_fieldset($element) {
return 'test';
}
// implement hook_theme
function mymod_theme() {
return array(
'mymod_fieldset' => array('arguments' => array('element' => NULL)),
'mymod_form' => array('arguments' => array())
);
}
// return a form that is based on the 'Basic Account Info' category of the user profile
function mymod_form() {
// load the user's profile
global $user;
$account = user_load($user->uid);
// load the profile form, and then edit it
$form_state = array();
$form = drupal_retrieve_form('user_profile_form', $form_state, $account, 'Basic Account Info');
// set the custom #theme function for this fieldset
$form['Basic Account Info']['#theme'] = 'mymod_fieldset';
// more form manipulations
// ...
return $form;
}
When my page gets rendered, I expected to see the fieldset representing 'Basic Account Info' to be wholly replaced by my test message 'test'. Instead what happens is that the <fieldset> and <legend> elements are rendered as normal, but with the body of the fieldset replaced by the test message instead, like this:
<fieldset>
<legend>Basic Account Info</legend>
test
</fieldset>
Why doesn't my #theme function have the chance to replace the entire <fieldset> element? If I wrap a textfield in this function instead, I am able to completely replace the <input> element along with its label. Furthermore, if I provide an override in my site's template.php for theme_fieldset, it works as expected and I am able to completely replace the <fieldset>, so I know it is possible.
What's different about providing #theme functions to fieldsets inside a module?
Have you tried overriding theme_fieldset() instead of using the #theme function? I believe you could do something like this in your .module file:
function mymodule_fieldset($element) {
// do something;
return $html;
}
This would apply to all fieldsets. You could do some kind of check on $element for the fieldsets you want to affect and then use the default implementation for all others.
Take a look at: http://api.drupal.org/api/function/theme_fieldset/6
I know this is an old post -- but I've run into the same issue. I came up with an ugly work around. This is definitely a bug in the Form API. Maybe my temporary fix will be helpful to someone.
I found (and appended) a bug report here: http://drupal.org/node/225698
Worth checking that before trying my hacky fix.
I'm not sure what the children are in $form['Basic Account Info'] in this example, but basically what you can do is use drupal_render() on that fieldset's children, and then recreate a fieldset array separate from $form['Basic Account Info'], theme it with theme() and pass it back to the form array as markup..
$fieldsetElement = array(
//$child is the key of whatever child you need in the fieldset
//you may have to alter this for multiple children, stringing
//together multiple drupal_render calls on each children
//(#children needs to be a string.. unless your theme can handle the array)
'#children'=>drupal_render($form['Basic Account Info'][$child]),
'#attributes'=>array(),//set real attributes
'#title'=>$form['Basic Account Info']['#title']
);
$form['Basic Account Info'] = array(
'#type'=>'markup',//not really needed, is default
'#value'=>theme('mymod_fieldset',$fieldsetElement)
);
super-duper hacking, likely causes disconnect with form state and potential validation failure -- but both are fixable by trial and error with the form api. I wouldn't recommend this unless you really want to get your hands dirty with PHP and drupal form API, but that's really the only way, unless you can live without variable fieldset themes in your module... Maybe try prefix and suffix?
This is just off the top of my head but maybe the difference is because a fieldset is not a form element but just a seperator or a grouper, if you will. Maybe the #theme callback is only for form elements?
The concept of your code works, meaning you can do what you want to do.
There are some things that can explain why it doesn't work.
The fieldset is not $form['Basic Account Info'].
Need to clear cache.
$form['Basic Account Info']['#theme'] is lost/overridden later in the code execution.
Try to take a look at $form before you do any of the moderations. When I tried to copy your code I run into a bug:
user.pages.inc file needed to be loaded
I was having the same issue.
You need to use #theme_wrappers instead of #theme
'#type' => 'fieldset',
'#theme_wrappers' => array('mymodule_fieldset'),

Categories