How can I write this Drupal snippet more efficiently? - php

I'm working on a patch to submit to the Registration Code module for Drupal. In short, is there a more efficient way to write the code below?
if (module_exists('regcode_voucher')) {
$cnfg = variable_get('regcode_voucher_display', array('regform' => 'regform'));
if (empty($cnfg['regform'])) {
return;
}
}
It seems like I should be able to reduce it to one if statement with && combining two conditions, but I haven't found the syntax or the necessary php array function that would allow me to do that.
In case some context helps, the regcode_voucher sub-module allows users to enter their registration code on the user edit page. On our sites, after a "beta" period, we want to simplify the registration form by removing the registration code field; but we'd like users to still be able to enter the code on their account edit page. The code above is part of a patch that allows the regcode's hook_user changes to be bypassed.

Code looks like good, what efficient do you want? Little changes may be:
if (module_exists('regcode_voucher')) {
$cnfg = variable_get('regcode_voucher_display', null);
if ($cnfg) {
// do your actions
}
}
And I don't recommend to merge if..., code should be clear and simpler to understand. If you merge these for optimizing, you win "tiny" milliseconds for real-live processors, but lost your clean code.

Why are you returning an array from variable_get if the variable is not found? variable_get will always return a string or a serialized array (that needs to be unserialized). If I'm missing something, you can use array_key_exists('regcode', variable_get(...)) to check for the array key.
This should work... note returning "false" from variable_get as a default if the variable is not found, which will cause the if conditions to not match. I personally find this more readable than nested if statements (for 3+ conditions I'd nest, though).
if( module_exists('regcode_voucher') && variable_get('regcode_voucher_display', false) ) {
// stuff
}

Related

PHP - Use a URL Key to get data from a separate file not normally index

I'm not a PHP dev and I have little experience with it. I ask for your forgiveness and assistance.
Here's my problem:
I have a script and I need to be able to append a 'key' (I don't know what else to call it) like:
http://my-web-address.com/packages.php?key=secret
When this key is present, I need to run the code responsible for extracting the data from a .json file in a separate directory. (Normally, the code wouldn't index this directory. It should only indexes it when the key is present in the URL.)
I believe this code to be the foreach section in the link above.
I'm having a hard time explaining this in a way that makes sense, so I guess it's easier to show you what I mean.
I know it should be easy; at first I thought I could simply do it with something like this:
if ($key == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}
But alas, simply appending that didn't make it work.
Any ideas?
As Ron Dadon said, but with a slight modification:
sanitize($value) {
// Sanitize the key - see below
return $value;
}
$key = sanitize($_GET['key']);
if ($key == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}
However you should sanitize that input, as anyone can change the key. Here are some resources on that:
Clean & Safe string in PHP
Remove all special characters from a string
The ultimate clean/secure function
You need to use the GET array:
if ($_GET['key'] == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}

Modx Plugin: Set createdby of Resource to Match TV Value

I am trying to create a plugin that will take the value of a listbox TV and set the document's createdby field to match that TV's setting onDocFormSave. The TV populates itself automatically with all active users and output's their ID.
I have the following code for the plugin, but when I try to save any resource it simply hangs and never saves. setCreatedBy is the name of the listbox TV:
switch ($modx->event->name) {
case 'onDocFormSave':
$created_by = $resource->getTVValue('setCreatedBy')
if ($resource->get('createdby') != $created_by) {
$modx->resource->set('createdby', $created_by));
}
break;
}
Untested.
It looks like setting also has to be done on the resource, not via the Modx-class.
$resource->set('createdby', $created_by); // You also have a ) too much in your code.
Inspected the docs.
If you omit the $resource->set... and run the plugin, will it pass? I'm wondering if you might be causing a loop, i.e $resource->set triggers another onDocFormSave. Do you have access to the server error.log? It probably contains whatever is crashing.
Those on the Modx forums were able to give me a leg up.
switch ($modx->event->name) {
case 'OnDocFormSave':
$created_by = $resource->getTVValue('setCreatedBy');
if (!empty($created_by) && $resource->get('createdby') != $created_by) {
$resource->set('createdby', $created_by);
$resource->save();
}
break;}
For reference, the way I handled gathering the names and user id's of Modx users and placing them in a selectbox TV was to use the Peoples snippet in an #EVAL binding:
#EVAL return $modx->runSnippet('Peoples',array('tpl'=>'peoplesTpl','outputSeparator'=>'||','active'=>'1'));
This is a petty dirty and slow way of doing things, but a request to have this be a standard field on Modx resources has been submitted to GitHub

How to make Drupal redirect to pages after user registration

I have a Drupal website and I want to show different welcome pages, depending on what my users enter as profile fields. I can't use the global $user variable, because users are not automatically logged in (They have to very their email address before they can log in).
Where can I add code to set the redirect?
I've tried with $form['#redirect'] and $form_state['redirect'] in the form validator, but that didn't work.
You can use logintobogan for inspiration:
#implementation of hook_user
mymodule_user($op) {
if ($op == 'login') {
$_REQUEST['destination'] = '/user/will/be/redirected/here'
}
}
The important part is to make sure, that by the time the final drupal_goto() is called in user.module, you have set your $_REQUEST['destination'].
A few things to note:
Logintoboggan has a lot of code to deal with all sorts of edge-cases, such as redirecting out/to https. You can ignore these, if your case is simple.
Your module must be called after user.module and probably after other modules implementing hook_user, for they might change this global too. Very ugly, but the way this works in Drupal.
Do not -ever- issue drupal_goto() in any hook. Especially not hook_user, or hook_form_alter. drupal_goto will prohibit other hooks from being called; breaking functionality at the least, but often corrupting your database.
Do not issue drupal_goto() in form_alter callbacks such as "_submit", this might break many other modules and might even corrupt your database.
Similar to Berke's answer, but it seems like you just want this to be a one time thing. For that, you can check for the $account->access property to check their last login. If it is 0, then they are logging in for the first time.
This should work fine for email or no email validation.
<?php
/**
* Implements hook_user().
*/
function mymodule_user($op, &$edit, &$account, $category = NULL) {
switch ($op) {
case 'login':
// execute this if they have never accessed the site before
if ($account->access == 0) {
// run conditional logic based on profile fields
// to set destination here
$_REQUEST['destination'] = 'path/to/welcome-page';
}
break;
}
}
?>
I suggest you use the Login Destionation module or you can use the Rules module redirect action which is maybe to robust for your purpose.
Just in case you don't want to write your own custom module :-)

Vaildate a Zip code against a list

I want to have a form on my intranet site... basically we are a home improvement company and have a list of bad area codes that we do not do business in ... IE list of bad zips 19020 19021 etc are bad so if they are I want it to return with a popup which says bad area ... if it is not on the list I want it to say Good Area
You haven't given too much information, so what follows is a very general solution. One way to approach this is to have two maps called badZips and goodZips:
var badZips = {
"19020": true,
"19021": true
...
};
var goodZips = {
"90210": true,
...
};
Then in your form-validation function, you can do:
if(badZips[zip]) {
alert("You entered a bad zip code");
}
else if(goodZips[zip]) {
alert("You entered a good zip code");
}
else {
alert("That zip code is not recognized");
}
Actually creating the maps depends on how your webapp is set up. How do you store the zips - is it in the database? Or have you hardcoded it?
Using apache, install geoIP. Echo their zipcode into a javascript function, which compares to a black-list you created.
http://www.maxmind.com/app/ip-location
Your functional requirements are pretty simple but you didn't really mention what setup you have. Do you want this functionality to happen on a form? What are you going to code with? Do you have a database? Based on the tags you've used I'll just assume that you don't have a database.
Basically you can have a list of area codes and a flag for each to indicate if it's a bad or a good code. You can keep this list in a multi-dimensional array in PHP as static data (http://www.webcheatsheet.com/PHP/multidimensional_arrays.php).
So it might look something like:
<?php
$areaCodes = array( array('aCode'='19020','aFlag'=>true),
array('aCode'='19021','aFlag'=>true),
array('aCode'='19022','aFlag'=>false)
);
?>
When you need an area code to be validated, just do a search in the array and check the flag to see if it's a good code or a bad code.
Store the zip codes in an array, then check if the given zip is in the array.
<?php
$BadZip = array("19020", "19021");
if (in_array($Zip, $BadZip))
{
echo "Bad Zip code!";
}
?>
If in_array returns true, then the zip code is in the list of bad zips.
Alternatively you could use the same method with a list of good zips.

php refactoring and better coding for php?

i have this process that is the heart of my app, that im creating, but for some reason i feel like its the worst way to do it(instinct) , and i wanted to see if thier is something wrong with this process, and am i approaching it in a bad way! p.s. the code works fine, just refactoring problem.
the process is:
users go to homepage, they see thier latest activities, by other site memebers(home.php),
//function to bring the latest activities from database
$results=function getUserUpdates($_SESSION['user_id'];
while($row = mysql_fetch_array($results))
{
//another function to format the activities in a social stream
echo formatUpdate($row['user_note'],$row['dt'],$row['picture'],$row['username'],$row['id'],$row['reply_id'],$row['reply_name'],$row['votes_up'],$row['votes_down']);
}
i have put the function codes in pastie.
formatUpdate function http://pastie.org/1213958
getUserUpdates function http://pastie.org/1213962
EDIT both functions are from different files they are included in home.php,
formatUpdate from functions.php
getUserUpdates from queries.php
First of all, it's good that you have separate functions for getting the data and for formatting the data. It's a good start toward refactoring your code. It makes it easier in the future: if you ever want to format your data differently, you can just expand your formatter.
Second, this is what coreyward meant by a lambda:
$results=function getUserUpdates($_SESSION['user_id'];
Remove the function keyword. You use function when you're defining a function. But here you're only calling one. (You defined it in queries.php.)
Third, I agree with webbiedave about the echo statements. A good way to avoid that: In the "heart" of your app, collect all the HTML into one place. Then, when you've collected everything you're going to display on the page, you can echo it all at once. This makes it a lot easier to keep track of what you're doing, and to remember the order of everything. It also makes it easier to add headers and footers, or do more formatting. Otherwise, if you have echo statements scattered around your code, it's a lot easier to let something slip that shouldn't be there.
Here's a very basic example of what I mean:
$html = '';
$results = getUserUpdates($_SESSION['user_id'];
while($row = mysql_fetch_array($results)) {
$fields = array(
'user_note' => $row['user_note'],
'dt' => $row['dt'],
'picture' => $row['picture'],
'username' => $row['username'],
'id' => $row['id'],
'reply_id' => $row['reply_id'],
'reply_name' => $row['reply_name'],
'votes_up' => $row['votes_up'],
'votes_down' => $row['votes_down'],
);
$html .= formatUpdate($fields);
}
// This way you can do whatever you want to $html here.
echo $html;
Also notice that I put all the fields from $row into an array and passed it to formatUpdate(). That has two advantages:
It's easier to read.
If you ever
want to change the fields that
formatUpdate deals with, you don't
have to worry about searching
through your code to change the
arguments every time you call it.
Firstly, I think you mean:
$results = getUserUpdates($_SESSION['user_id']);
In your getUserUpdates() function there is a redundant branch:
if ($username == $_SESSION['u_name']){
// return something
}
if ($username != $_SESSION['u_name']){
// return something else
}
You don't need the second if statement as any code run at that point will only be run if $username != $_SESSION['u_name'].
In my opinion, it's usually better not to have different functions directly echoing HTML up the stack (such as echoVote()). It's preferred to have functions return data and have the original caller echo it. This allows the caller to perform additional data massaging if desired.
Other than that, your code is fetching data, looping through and acting on the results which is pretty much standard fare.
I think your instinct is to be a little too harsh on yourself ;) There are improvements to be made but it's certainly not the worst way to do anything.

Categories