Kohana 3.2 - ORM Update field which have been modifed by admin - php

Im back to professional programming after 5 year late, so i have learn from beginning ;)
So i chose Kohana framework for my first framework i try to bulid first application now and i have a small problem, lets begin.
I use Kohana ORM and Auth module, as you know default Auth module user table have default fields (username, password, lastlogin) i try to extend User by:
Creating new table (user_additionals)
Creating new model (User_Additional)
Model look like this: http://pastie.org/private/412jflfoifyqs46uaxmga - Nothing special. Everything will be okay, i like easy reference like this: $user->additional->firstname etc.
At the moment i have bulid admin panel (admin can edit every user) and... every field. I have 10 fields like firstname, lastname, birthdate presented as form (filled form - placeholder loaded by template assign) and here is my small problem:
I want to give admin possibility to edit one from much fields, if admin need to edit user signature or something else - he edit one field from a lot fields available and click "Submit" it's easy - one form have been updated.
But, if i try use something like this:
$edit = ORM::Factory('User_Additional')->values($_POST); I get validation Exception (which be catched but, here are validation error - model required all fields to be !empty... (By validation rules)
I use temporary solution, but im a perfectionist and i want to create good code from begining, so here you can find my code: http://pastie.org/private/axtwxbt66gtvcwiv97hvlq
My solution start at line 29 (link above).
So my question is:
*How to make exceptions from Validation in cases like this?? *
*How make exceptions from validation for example for action /admin/edituser/ is it possible? *
*How do i can do my model code better? Thanks for any suggestions which can help me *
Thanks!

Validation will only run on "non-empty" fields, unless you specify the "not_empty" rule.
So basically, you could do the following: (when you need to enforce the "non emptiness" of a field)
class Model_User_Additional extends ORM
{
protected $foreign_key_suffix = 'user_id';
protected $_primary_key = 'user_id';
public function enforce_rules(array $fields)
{
$validation = Validation::factory($this->_object);
foreach ($fields as $field)
{
$validation->rule($field, 'not_empty');
}
return $validation;
}
public function rules()
{
/* Removed all not_empty */
return array(
/* 'user_id' => array(
array('not_empty'),
), */
'firstname' => array(
array('text'),
),
'lastname' => array(
array('text'),
),
'birthdate' => array(
array('date'),
),
'postprice' => array(
array('decimal'),
),
'articleprice' => array(
array('decimal'),
),
'phonenumber' => array(
array('phone'),
),
/* 'active' => array(
array('not_empty'),
), */
/* 'lastupdate' => array(
array('not_empty'),
), */
'info' => array(
array('text'),
),
);
}
public function edit_user($values, $expected, $extra_validation = NULL)
{
return $this->values($values, $expected)->update($extra_validation);
}
}
the usage would be:
$user = ORM::factory('User_Additional');
$user->values(array('field' => 'value'))->create($user->enforce_rules(array('user_id')));
/* and the same for updating */
$user->set('info', $_POST['info'])->update($user->enforce_rules(array('info')));

Related

Displaying search results on a separate page

I have a SilverStripe site with some code to display a search form. The for allows you to search for something based on 3 things. Problem is, I'm not sure how to get the results to display correctly on a separate page.
My code:
class InstitutionSearchPage extends Page {
}
class InstitutionSearchPage_Controller extends Page_Controller {
private static $allowed_actions = array(
'Search'
);
public function Form() {
$fields = new FieldList(array(
DropdownField::create('DegreeType', 'Degree', QualificationType::get()->filter('ParentID', 0)->map()),
DropdownField::create('Course', 'Course', Qualification::get()->map()),
DropdownField::create('City', 'City', City::get()->map()),
));
$actions = new FieldList(array(
FormAction::create('Search')->setTitle('Find a College')
));
$validator = ZenValidator::create();
$validator->addRequiredFields(array(
'DegreeType' => 'Please select a Degree',
'Course' => 'Please select a course',
'City' => 'Please select a city',
));
$form = new Form($this, 'Search', $fields, $actions, $validator);
$form->setLegend('Criteria')->addExtraClass('form-horizontal')->setAttribute('data-toggle', 'validator');
// Load the form with previously sent data
$form->loadDataFrom($this->request->postVars());
return $form;
}
public function Search() {
return array('Content' => print_r($this->getRequest()->postVars(), true));
}
}
It seems to be displaying results on the same page but gives me a bunch of weird data. For example, I got this when I tested the form: Array ( [DegreeType] => 53 [Course] => 1 [City] => 1 [SecurityID] => 02718d0283e27eeb539eff19616e0b23eadd6b94 [action_Search] => Find a College )
The result is supposed to be an organized list of colleges (along with other data).
I guess that what you are seeing is expected behavior, as the form will post to the Search function, and that one is just returning a print_r of an array with the post vars which will be picked up by the template.
Otherwise, there are a lot of things not corresponding with the Silverstripe default way to handle forms. Please take a look here and change your form accordingly: https://docs.silverstripe.org/en/3.4/tutorials/forms/
For example, give the form the same name as your function (or in your case, change the function name to the form name). Then implement the action function.

Seed Silverstripe database

Is it possible to "seed" a database like you can in rails? I want to use a seed in combination with an imageobject manager so that I can get records by title.
Based on your comment left on Ingo's answer, you want to add a requireDefaultRecords() method to your page class.
The below is from a recent project and ensures there is a particular user group, but you can do the same with any type of DataObject (e.g. Page).
public function requireDefaultRecords() {
// Make sure there is a readers security group
$group = Group::get('Group')->filter('Code', 'readers')
if ( !$group->exists() ) {
$group = Group::create(array('Title' => 'Readers'));
$group->write();
}
}
This function is run on all DataObject classes when you do a build.
You can set the default values of your page $db variables by setting the $defaults array.
class Page extends SiteTree {
public static $db = array(
'Title' => 'Text',
'Description' => 'Text'
);
public static $defaults = array(
'Title' => 'Default Title',
'Description' => 'Default Description'
);
...
}
Not quite sure what you mean by "seed" in this context. There's a "data-generator" module which writes random data with educated guesses on the ORM column types.

Conditional fieldgroups/fieldsets in Drupal 7

Background: In Drupal 7, I have created a form with CCK (aka the Field UI). I used the Field group module to create a fieldgroup, but I need it to be conditional, meaning it will only display depending on a previous answer.
Previous research: To create a conditional field, you can use hook_form_alter() to edit the #states attribute like so:
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'person_info_node_form') {
// Display 'field_maiden_name' only if married
$form['field_maiden_name']['#states'] = array(
'visible' => array(
':input[name="field_married[und]"]' => array('value' => 'Yes'),
),
);
}
}
However, there seems to be no way to use the States API for fieldgroups. One thing to note is that, while fields are stored in $form, fieldgroups are stored in $form['#groups'] as well as in $form['#fieldgroups']. I don't know how to distinguish between these, and with this in mind, I have tried to apply a #states attribute to a fieldgroup in the same manner as above. However, it only produces server errors.
Question: Is there a way to make a fieldgroup display conditionally using the States API or some alternative approach?
you have to use the hook_field_group_build_pre_render_alter()
Simply :
function your_module_field_group_build_pre_render_alter(&$element) {
$element['your_field_group']['#states'] = array(
'visible' => array(
':input[name="field_checkbox"]' => array('checked' => TRUE),
),
);
}
This works perfecly. If the group A is in an another group, do this
$element['groupA']['groupB']['#states'] etc....
You may need to add an id attribute if none exists:
$element['your_field_group']['#attributes']['id'] = 'some-id';
$element['yout_field_group']['#id'] = 'some-id';
Here's the simplest solution I came up with. There are essentially 2 parts to this: (1.) programmatically alter the display of the form, and (2.) use the GUI to alter the display of the content.
(1.) First, I used hook_form_alter() to programmatically create the conditional fieldset and add existing fields to it. The code is shown below.
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'FORM_ID_node_form') {
// programmatically create a conditional fieldset
$form['MYFIELDSET'] = array( // do NOT name the same as a 'Field group' fieldset or problems will occur
'#type' => 'fieldset',
'#title' => t('Conditional fieldset'),
'#weight' => intval($form['field_PARENT']['#weight'])+1, // put this fieldset right after it's "parent" field
'#states' => array(
'visible' => array(
':input[name="field_PARENT[und]"]' => array('value' => 'Yes'), // only show if field_PARENT == 'Yes'
),
),
);
// add existing fields (created with the Field UI) to the
// conditional fieldset
$fields = array('field_MYFIELD1', 'field_MYFIELD2', 'field_MYFIELD3');
$form = MYMODULE_addToFieldset($form, 'MYFIELDSET', $fields);
}
}
/**
* Adds existing fields to the specified fieldset.
*
* #param array $form Nested array of form elements that comprise the form.
* #param string $fieldset The machine name of the fieldset.
* #param array $fields An array of the machine names of all fields to
* be included in the fieldset.
* #return array $form The updated form.
*/
function MYMODULE_addToFieldSet($form, $fieldset, $fields) {
foreach($fields as $field) {
$form[$fieldset][$field] = $form[$field]; // copy existing field into fieldset
unset($form[$field]); // destroy the original field or duplication will occur
}
return $form;
}
(2.) Then I used the Field group module to alter the display of the content. I did this by going to my content type and using the 'Manage display' tab to create a field group and add my fields to it. This way, the fields will appear to be apart of the same group on both the form and the saved content.
Maybe you can try to look at the code of this module to help you find an idea.

CakePHP log in system

I am editing a website which someone has made in CakePHP, but I don't have any previous experience in Cake. I'm reading the manual but finding it quite hard to understand so thought I would post a question on here to see if I can get any quick answers.
I think that this code is being used to display a login box, and you can only log in with username test and password 123123
var $components = array("Auth", "Acl");
function beforeFilter(){
$this->Security->loginOptions = array(
'type' => 'basic',
'realm' => 'Authenticate Emergency Response Center'
);
$this->Security->loginCredentials = array(
'test' => '123123'
);
$this->Security->requireLogin();
$this->_bindToSite();
parent::beforeFilter();
}
I want the log in box to appear still, but I want to fill the loginCredentials array automatically with information from the database. I have a table called 'operators' which contains the fields 'user_id' and 'password'.
Could someone tell me how I would alter the code above to allow any of the usernames/passwords stored in the operators table to log in?
Thanks for any help
Build an array from the database and set $this->Security->loginCredentials equal to your array.
You can leave most of the hard work up to CakePHP's Auth component, but if you want to use a model other than the default 'User', you'll just need to set this in beforeFilter(). The best place to do this is probably app_controller.php in your app\ directory.
function beforeFilter(){
$this->Auth->userModel = 'Operator';
$this->Auth->fields = array(
'username' => 'user_id',
'password' => 'password'
);
);

CakePHP: Access Model in other Model / in app_model.php for Validation of Banknumber

I am wondering how I could use data from a Model B while I am validating Model A, here to check if an entered Banknumber is a correct one:
My Users specify their bankaccount during the registration. E.g. the "banknumber". I am validating this the normal way in my user.php model
var $validate = array(
'banknumber' => array(
'minLength' => array(
'rule' => array('minLength', 8),
'message' => '...',
'required' => true,
),
Now I want to know if the entered Banknumber is a real one, so I got a table "Banks" in my DB with all real Banknumbers, and I am using some own validation functions which I specify in app_model.php.
function checkBankExists($data) {
if (!$this->Bank->findByBanknumber($data)) {
return false;
} else {
return true;
}
}
But this is never working, because while I am validating the User-Model, I can only use this one in an app_model - function, accessing it with $this->name or so... a $this->Bank is NOT possible, I get:
Undefined property: User::$Bank [APP\app_model.php
Call to a member function findByBanknumber() on a non-object
Is there ANY way to import/access other models in a function in app_model.php?
Thank you!
ClassRegistry should generally be used instead of AppImport as AppImport only loads the file, rather than registering it properly, cake style.
Using the example above.
$bnk = ClassRegistry::init('Bank');
$bnk->findByBanknumber($data);
you can import your model, create instance of it and use it as you like:
App::import('model','Bank');
$bnk = new Bank();
$bnk->findByBanknumber($data);

Categories