CakePHP Shell Script Environment Setting - cakephp

I am new to shell development in Cake. The problem I am facing is to setting datasource in the script itself. My database.php is;
function __construct()
{
if(getenv('ENVIRONMENT') == 'staging') {
$this->default = $this->staging;
} else {
$this->default = $this->production;
}
}
So, I am setting database based on the web server's environment setting. Naturally, php-cli can't access this variable. What I end up doing is to create a cakephp shell task.
class SelectEnvTask extends Shell {
public function execute()
{
App::Import('ConnectionManager', 'Model');
$configs = ConnectionManager::enumConnectionObjects();
if (!is_array($configs) || empty($configs)) {
$this->out('Error! No database configuration has been found.');
}
$connections = array_keys($configs);
if(!isset($this->args[0])) {
$this->out('Error! Please enter one of the environment settings as an argument: ' . implode('/', $connections) .
"\n\n" . 'eg. ./Console/cake *script_name* *environment*', 2);
exit(1);
}
if(!in_array($this->args[0], $connections)) {
$this->out($this->args[0] . ' environment could not be found!', 2);
exit(1);
}
//hacky solution until finding a better one
$models = App::objects('Model');
foreach($models as $model) {
ClassRegistry::init($model)->setDataSource($this->args[0]);
}
}
}
This works correctly, however as you see in the below of the task, I get all the model names and change their DB connection, which is not a good practice. I also don't want to set more variables into the database class and would like to handle these in shells/tasks.
Is there any more elegant way to achieve this?
Thanks,

Here is a far more elegant solution. Add the following method to your shell or task, and then execute it whenever you need to in order to change your data profile (listed in app/Config/database.php) on the fly:
function change_database_profile($database = 'default') {
$connected = ConnectionManager::getDataSource($database);
if($connected->isConnected()) {
return true;
}
return false;
}

Related

CodeIgniter - displaying view based on variable from database

I've been learning codeigniter recently and trying to push an application out. im running into problems with the if else statements displaying views. i am trying to pull in_party from the databaseci_admin_info and display views depending if its set to 1 or 0. its bypassing any condition and just displaying the first view set.
Model
function get_in_par(){
$this->db->select('in_party');
$this->db->from('ci_admin_info');
$query = $this->db->get();
$ret = $query->row();
return $ret->in_party;
}
Controller
public function index(){
$data['title'] = 'Party';
$data['party'] = $this->party_model->get_party();
$data['prov'] = $this->party_model->get_prov_name();
$data['info'] = $this->party_model->get_all();
$data['res'] = $this->party_model->get_party_res();
$data['rank'] = $this->party_model->get_pa_rank();
$this->load->view('admin/includes/_header', $data);
$inpar = $this->party_model->get_in_par();
if(isset($inpar['in_party'])==0){
$this->load->view('admin/party/join');
} else {
$this->load->view('admin/party/index');
}
$this->load->view('admin/includes/_footer');
}
I've tried rearranging it into the parent construct as well and it just bypassed it completely. just trying to make it load the join view if in_party = 0 . i've tried without isset bypasses it as well. i've tried switch but don't think it registered that as well. i think i'm missing something in my model
$query = $this->db->select('*')
->from('ci_admin_info')
->get();
$result = $query->result_array();
return $result[0];
$inpar = $this->party_model->get_in_par();
if(!isset($inpar['in_party']) || $inpar['in_party']=="0"){....

translating the Time text to another language

How can i translate the default Cake php time helper strings in my application, i'm using in Cake php a function called timeAgoInWords which from the time helper function, it give me a text like 5 hours, 52 minutes ago .
I want to translate this to another language, how can i do that ? i searched the documentation and i didn't get anything .
<?php echo $this->Time->timeAgoInWords($question['Question']['created']) ?>
You need a customized helper to get your stuff done. timeAgoInWords helper does not give the flexiblity of replacing words with your words.
Here, create a file called TimeagoHelper.php under your View/Helper
I am not sure which language you want translation in, I will write in English, you can replace your words.
<?php
App::uses('AppHelper', 'View/Helper');
class TimeagoHelper extends AppHelper {
public function __construct(View $view, $settings = array()) {
parent::__construct($view, $settings);
}
public function timeago($datetime) {
$datetime1 = new DateTime($datetime);
$datetime2 = new DateTime('now');
$obj = $datetime1->diff($datetime2);
if($obj->days == 1) {
$time = $obj->format('%a day'); // Replace your word
} elseif($obj->days == 0) {
if($obj->h == 0) {
if($obj->i == 0) {
$time = $obj->s . ' seconds'; // Replace your word
} else {
$time = $obj->i . ' minutes'; // Replace your word
}
} else {
$time = $obj->h . ' hours'; // Replace your word
}
} else {
$time = $obj->format('%a days'); // Replace your word
}
return $time.' ago'; // Replace your word
}
}
Load this helper in your action or controller.
I have been using php 5.5 since quite sometime, am not sure if it works on lesser versions, i.e. don't remember if concat is allowed as done for seconds and minutes. Incase, it doesn't work, assign them to variables and concat those.
Use it in View's .ctp file like so:
$this->Timeago->timeago($question['Question']['created']);
PS: CakeTime comes in handy too, check out the api for possibilities.
Cheers!

joomla - Storing user parameters in custom component issue

Hi for my custom component I need to set some custom parameters for joomla user for membership for checking if the user ni trial period or not and it can be change from the component admin panel for specific user.
The problem arises while retrieving the parameter. I think it is stored in cookie and it isn^t updated. I wrote the code like that to check it.
$user = JFactory::getUser(JRequest::getVar('id','0'));
echo $user->getParam('trialPeriod','0');
to save the value I am useing JHTML booleanlist.
$user->setParam('trialPeriod',$data['trialPeriod']);
$user->save();
Then is stores the value in joomla users table in the row of that user with column of params as;
{"trialPeriod":"0"}
in this situation it echoes the value as 0. Then I am changin the state of trialPeriod var as 1 and storing in db it updates the db as;
{"trialPeriod":"1"}
After all I am refreshing the page where the value is prompt the the screen the the value remains still the same as 0;
To clarify;
First of all there is no problem with saving the param it is changed properly. The problem is retrieving the changed one. The releated piece of code is following;
$user = JFactory::getUser();
$doc = JFactory::getDocument();
if($user->getParam('trialPeriod',0) == 0){
$ed = JFactory::getDate($obj->expirationDate);//obj is user from custom table and there is no problem with getting it.
$isTrialEnd = FALSE;
}else{
$ed = JFactory::getDate($user->getParam('trialExp',0));
$isTrialEnd = TRUE;
}
if($isTrialEnd){
//do something else
}else{
echo $user->getParam('trialPeriod','0');
}
actually big part of the code is unneccessary to explain it but you will get the idea.
What is the solution for this?
Editted.
$app = JFactory::getApplication();
$config = JFactory::getConfig();
$db = $this->getDbo();
$isNew = empty($data['uid']) ? true : false;
$params = JComponentHelper::getParams('com_dratransport');
if($isNew){
// Initialise the table with JUser.
$user = new JUser;
// Prepare the data for the user object.
$username = self::getCreatedUserName($data['type']);
$data['username'] = !empty($data['username']) ? $data['username'] : $username;
$data['password'] = $data['password1'];
$useractivation = $params->get('useractivation');
// Check if the user needs to activate their account.
if (($useractivation == 1) || ($useractivation == 2)) {
$data['activation'] = JApplication::getHash(JUserHelper::genRandomPassword());
$data['block'] = 1;
}
}else{
$user = JFactory::getUser($data['uid']);
$data['password'] = $data['password1'];
}
$membership = DraTransportHelperArrays::membershipCFG();
$membership = $membership[$data['membership']];
if($data['membership'] == 4)
$data['groups'] = array($params->get('new_usertype',2),$params->get($membership,2));
else
$data['groups'] = array($params->get($membership,2));
$data['name'] = $data['companyName'];
$user->setParam('trialPeriod',$data['trialPeriod']);
// Bind the data.
if (!$user->bind($data)) {
$this->setError(JText::sprintf('COM_USERS_REGISTRATION_BIND_FAILED', $user->getError()));
return false;
}
// Load the users plugin group.
JPluginHelper::importPlugin('user');
// Store the data.
if (!$user->save()) {
$app->enqueuemessage($user->getError());
$this->setError(JText::sprintf('COM_USERS_REGISTRATION_SAVE_FAILED', $user->getError()));
return false;
}
this piece of code is for storing the data releated with the users table.
Turns out this was the fact that Joomla stores the JUser instance in the session that caused the problem.
When changing a user's parameters from the back-end, the changes are not reflected in that user's session, until she logs out and back in again.
We could not find an easy option to modify anther user's active session, so we resorted to the use of a plugin that refreshes the JUser instance in the logged-in users' session, something like the following:
$user = JFactory::getUser();
$session = JFactory::getSession();
if(!$user->guest) {
$session->set('user', new JUser($user->id));
}
(reference: here).

Inserting variables in mysql queries

I've written a function which updates the mysql database row with some new column data.
Here is the function:
function sql($set,$data){
$sql = mysql_query("UPDATE members SET '".$set."' = '".$data."' WHERE login = '".$_SESSION['login']."'");
if($sql){
echo 'Profile updated.';
}
else{
echo 'Could not update profile. Please try again later.';
}
}
And here is a fragment from the program which is supposed to utilise the function:
$array = array("$password", "$email", "$age");
if($array[0] != 0){
sql("password",$password);
}
if($array[1] != 0){
sql("email",$email);
}
if($array[2] != 0){
sql("age",$age);
}
It doesn't write the values to the database. What's wrong? Maybe it's the quotation of the variables in the function?
Remove the single quote on the SET :
function sql($set,$data){
$sql = mysql_query("UPDATE members SET ".$set." = '".$data."' WHERE login = '".$_SESSION['login']."'");
if($sql){
echo 'Profile updated.';
}
else{
echo 'Could not update profile. Please try again later.';
}
}
Column names don't dont need to be quoted
Working example here -> http://www.sqlize.com/c34I44c37r
It is indeed the quotation. To be specific, it's the quotation for the filed name (name, email, ..)
Just ` instead of '
SET `foo` = 'bar'
PS: Please make sure that you escape the user input before writing it to db using mysql_real_escape_string($data). Otherwise one could alter your query, which is called mysql injection.

RIA-Services - how to WhereOr or use an IN style construct

I am using SL 4, WCF RIA Services against Entity Framework 4.0. I have an Entity, Visit, that has a string Status field. I have a search screen where I need to display results that have StatusA or StatusB. I am struggling to find a way to specify a client-side query that specifies a collection of statuses that should be matched. If I was to write what I want in SQL it would look something like:
select * from Visit where Status in ('StatusA', 'StatusB');
Client side, it appears to be straightforward to chain Where methods for a WhereAnd effect:
var query = this.PqContext.GetVisitsQuery();
if (!string.IsNullOrEmpty(this.PracticeName))
{
query = query.Where(v => v.PracticeName.ToUpper().Contains(this.PracticeName.ToUpper()));
}
if (this.VisitDateAfter.HasValue)
{
query = query.Where(v => v.VisitDate > this.VisitDateAfter);
}
if (this.VisitDateBefore.HasValue)
{
query = query.Where(v => v.VisitDate < this.VisitDateBefore);
}
However, I can't seem to find a straightforward way to do a WhereOr style operation. I have tried this:
var statuses = new List<string>();
if (this.ShowStatusA)
{
statuses.Add("StatusA");
}
if (this.ShowStatusB)
{
statuses.Add("StatusB");
}
if (statuses.Any())
{
query = query.Where(BuildContainsExpression<Visit, string>(e => e.Status, statuses));
}
Where BuildContainsExpression looks like:
private static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
if (null == valueSelector)
{
throw new ArgumentNullException("valueSelector");
}
if (null == values)
{
throw new ArgumentNullException("values");
}
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
{
return e => false;
}
var equals =
values.Select(
value =>
(Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
var body = equals.Aggregate<Expression>(Expression.Or);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
But this throws a "Bitwise operators are not supported in queries." exception. Any clues? Is there an alternative way to build an expression tree that works here or do I need to pass all the parameters over to the server and use the BuildContainsExpression there?
Your time and your guidance are much appreciated.
You can create a query method such as the following in your domain service:
GetVisitsByStatus(string[] statusList) {
// create the LINQ where clause here
}
And then from the client, call context.GetVistsByStatusQuery(string[]).
Not all of LINQ is (or even can) be exposed over the URL, so there are always cases where you need to use simple parameters, and have the middle tier construct the LINQ expressions that eventually define the query that goes to the back-end data store.
Hope that helps.

Resources