Programmically Creating Roles
I recently wrote a module that required certain roles to be created. My goal was to be able to drop the module in and go, so develop module, install module on live site, and boom goes the dynamite.
The first thing I did was create the function to create the roles:
function _create_roles() {
$existing_roles = user_roles();
$new_roles = array('VP of Finance & CFO', 'Finance', 'Senior Vice President and Academic Dean', 'Academic Programs', 'President and CEO', 'President\'s Office', 'Human Resources', 'Supervisor');
$roles = array();
foreach($new_roles as $new_role) {
if(array_search($new_role, $existing_roles) == FALSE) {
$roles[] = $new_role;
}
}
foreach($roles as $role) {
db_query('INSERT INTO {role}(name) VALUES(\'%s\')', $role);
}
}
The only thing I need to do is inject the roles into the database. However, it's best to make sure that I am not adding duplicate roles. On the first line inside the function, I am calling user_roles() which gets an array of all the currently defined roles in the system. I then create an array of roles I wish to add to the system which I iterate through by making sure that each role I want to add does not exist the array of existing roles. Roles that are not in the $existing_roles array gets added to another array which is then iterated through and a query is executed based on each element.
Creating Content Types Programmically
There are two ways to create content types in Drupal. The first is using hook_node_info in your module. When using this method, this only creates a content type with a title and a body (providing you implement the hook_form() function.)
function blog_node_info() {
return array(
'blog' => array(
'name' => t('Blog entry'),
'module' => 'blog',
'description' => t('A blog entry is a single post to an online journal, or blog.'),
'has_title' => TRUE,
'has_body' => TRUE,
)
);
}
function blog_form($node, $form_state) {
return node_content_form($node, $form_state);
}The other way is to programmically recreate a content type by exporting the content type with the Content Copy module. For example, you're working on module that relies on content type that you created along with a number of CCK fields. The first step in this method is to enable the Content Copy module. Once the module is enabled head over to admin/content/types/export to select the content type you wish to export. The export will be an array so you can use it in a module.
$content['type'] = array (
'name' => 'Membership',
'type' => 'product',
'description' => 'This node displays the representation of a membership for sale on the website. ',
'title_label' => 'Name',
'body_label' => 'Description',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'revision' => true,
'promote' => false,
'sticky' => false,
),
'old_type' => 'product',
'orig_type' => 'product',
'module' => 'uc_product',
'custom' => '0',
'modified' => '1',
'locked' => '1',
'reset' => 'Reset to defaults',
'uc_product_shippable' => 0,
'uc_image' => '',
'comment' => '0',
'comment_default_mode' => '4',
'comment_default_order' => '1',
'comment_default_per_page' => '50',
'comment_controls' => '3',
'comment_anonymous' => 0,
'comment_subject_field' => '1',
'comment_preview' => '1',
'comment_form_location' => '0',
);
$content['fields'] = array (
0 =>
array (
'label' => 'Image',
'field_name' => 'field_image',
'type' => 'filefield',
'widget_type' => 'imagefield_widget',
'change' => 'Change basic information',
'weight' => '31',
'file_extensions' => 'png gif jpg jpeg',
'progress_indicator' => 'bar',
'file_path' => '',
'max_filesize_per_file' => '',
'max_filesize_per_node' => '',
'max_resolution' => 0,
'min_resolution' => 0,
'custom_alt' => 0,
'alt' => '',
'custom_title' => 0,
'title_type' => 'textfield',
'title' => '',
'use_default_image' => 0,
'default_image_upload' => '',
'default_image' => NULL,
'description' => '',
'required' => 0,
'multiple' => '1',
'list_field' => '0',
'list_default' => 1,
'description_field' => '0',
'op' => 'Save field settings',
'module' => 'filefield',
'widget_module' => 'imagefield',
'columns' =>
array (
'fid' =>
array (
'type' => 'int',
'not null' => false,
'views' => true,
),
'list' =>
array (
'type' => 'int',
'size' => 'tiny',
'not null' => false,
'views' => true,
),
'data' =>
array (
'type' => 'text',
'serialize' => true,
'views' => true,
),
),
'display_settings' =>
array (
'label' =>
array (
'format' => 'above',
'exclude' => 0,
),
'teaser' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
'full' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
4 =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
'token' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
),
),
);
$content['extra'] = array (
'title' => '-5',
'body_field' => '-4',
'revision_information' => '20',
'author' => '20',
'options' => '25',
'comment_settings' => '30',
'menu' => '0',
'path' => '30',
'shipping' => '0',
'base' => '-1',
'body' => '1',
);In a hook_install or hook_enable function, and after making sure the content type doesn't already exist, you would do the following:
module_load_include('inc', 'content', 'includes/content.crud');
$content['type'] = array (
'name' => 'Membership',
'type' => 'product',
'description' => 'This node displays the representation of a membership for sale on the website. ',
'title_label' => 'Name',
'body_label' => 'Description',
'min_word_count' => '0',
'help' => '',
'node_options' =>
array (
'status' => true,
'revision' => true,
'promote' => false,
'sticky' => false,
),
'old_type' => 'product',
'orig_type' => 'product',
'module' => 'uc_product',
'custom' => '0',
'modified' => '1',
'locked' => '1',
'reset' => 'Reset to defaults',
'uc_product_shippable' => 0,
'uc_image' => '',
'comment' => '0',
'comment_default_mode' => '4',
'comment_default_order' => '1',
'comment_default_per_page' => '50',
'comment_controls' => '3',
'comment_anonymous' => 0,
'comment_subject_field' => '1',
'comment_preview' => '1',
'comment_form_location' => '0',
);
$content['fields'] = array (
0 =>
array (
'label' => 'Image',
'field_name' => 'field_image',
'type' => 'filefield',
'widget_type' => 'imagefield_widget',
'change' => 'Change basic information',
'weight' => '31',
'file_extensions' => 'png gif jpg jpeg',
'progress_indicator' => 'bar',
'file_path' => '',
'max_filesize_per_file' => '',
'max_filesize_per_node' => '',
'max_resolution' => 0,
'min_resolution' => 0,
'custom_alt' => 0,
'alt' => '',
'custom_title' => 0,
'title_type' => 'textfield',
'title' => '',
'use_default_image' => 0,
'default_image_upload' => '',
'default_image' => NULL,
'description' => '',
'required' => 0,
'multiple' => '1',
'list_field' => '0',
'list_default' => 1,
'description_field' => '0',
'op' => 'Save field settings',
'module' => 'filefield',
'widget_module' => 'imagefield',
'columns' =>
array (
'fid' =>
array (
'type' => 'int',
'not null' => false,
'views' => true,
),
'list' =>
array (
'type' => 'int',
'size' => 'tiny',
'not null' => false,
'views' => true,
),
'data' =>
array (
'type' => 'text',
'serialize' => true,
'views' => true,
),
),
'display_settings' =>
array (
'label' =>
array (
'format' => 'above',
'exclude' => 0,
),
'teaser' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
'full' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
4 =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
'token' =>
array (
'format' => 'image_plain',
'exclude' => 0,
),
),
),
);
$content['extra'] = array (
'title' => '-5',
'body_field' => '-4',
'revision_information' => '20',
'author' => '20',
'options' => '25',
'comment_settings' => '30',
'menu' => '0',
'path' => '30',
'shipping' => '0',
'base' => '-1',
'body' => '1',
);
$form_state = array();
$form = content_copy_import_form($form_state, $content['type']['type']);
$form_state['values']['type_name'] = $type_name ? $type_name : '';
$form_state['values']['macro'] = '$content = '. var_export($content, 1) .';';
$form_state['values']['op'] = t('Import');
content_copy_import_form_submit($form, $form_state); Disabling XOrg Standby, Suspend, and Sleep Mode
While wanting to watch Hulu on the computer connected to my TV I ran into the issue where every 5 minutes the TV would go into sleep mode. I was not able to find anything in KDE to prevent this from happening.
I did find a command that would allow you to set this option until XOrg was restarted.
# xset q
This will get you information about the keyboard, pointer, screen saver, colors, font path, and DPMS (which is what we want)
Keyboard Control:
auto repeat: on key click percent: 0 LED mask: 00000002
XKB indicators:
00: Caps Lock: off 01: Num Lock: on 02: Scroll Lock: off
03: Compose: off 04: Kana: off 05: Sleep: off
06: Suspend: off 07: Mute: off 08: Misc: off
09: Mail: off 10: Charging: off 11: Shift Lock: off
12: Group 2: off 13: Mouse Keys: off
auto repeat delay: 250 repeat rate: 30
auto repeating keys: 00ffffffdffffbbf
fadfffefffedffff
9fffffffffffffff
fff7ffffffffffff
bell percent: 50 bell pitch: 400 bell duration: 100
Pointer Control:
acceleration: 45/10 threshold: 4
Screen Saver:
prefer blanking: yes allow exposures: yes
timeout: 0 cycle: 600
Colors:
default colormap: 0x20 BlackPixel: 0x0 WhitePixel: 0xffffff
Font Path:
catalogue:/etc/X11/fontpath.d,built-ins
DPMS (Energy Star):
Standby: 300 Suspend: 600 Off: 900
DPMS is Enabled
Monitor is On
To keep the monitor from turning off or anything run the following command as root:
xset dpms 0 0 0
Screen Captures on Android Phones
I know you can take a screen shot on an iPhone by holding down the only two buttons, which got me thinking "I should be able to do that on Android phones too." So doing some googling for a few minutes, the only thing that I was able to find was connecting phone to a computer and firing up Eclipse and doing it through the SDK/IDE, downloading a special App and again connecting it to your computer, or installing a 3rd party app.
I know it's possible to do this without rooting the phone, or having to do any of the above ways. I was able to do this on two Samsung phones running Android 2.2 and 2.3, but with different key combinations. So far these are the only two phones I was able do a screen capture on:
- Samsung Droid Charge: Hold the Back button and hit Home
- Samsung Galaxy S: Hold the Back button and hit the Power button.
When I get some more free time, I'm going to go to a Verizon store and try to figure out how to do this on other phones, providing that it's possible. It doesn't make sense why this feature was would be left out because it's such a small and nice feature to have.
Having Views Initially Display Empty Text and Setting a Default Value
I have found a way to initially show no results when a view loads, but if I want to display a specific value if nothing is found, that's a different story. One instance that you would want to do something like this is when you're making a distributor or representative locator. In this case, if no results are found, then you want to display the corporate office's contact information.
I am assuming you have selected the fields you want to display, filtered how you wanted, and exposed what filters you want the user to use.
The first set is to add an argument of null. After clicking on the '+' in the arguments section of the display, select Global from the group dropdown.
When configuring the argument select the following options:
- Under where it says ACTION TO TAKE IF ARGUMENT IS NOT PRESENT
- Select provide default argument.
- Provide a default argument by supplying PHP Code
- In the PHP Argument Code Box paste the following code:
$is_filtered = FALSE; foreach ($view->filter as $filter) { if ($filter->options['exposed']) { if (!empty($view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value)) { $is_filtered = TRUE; break; } } } return $is_filtered; - The Validator needs to be set as PHP Code
- Select ACTION TO TAKE IF ARGUMENT DOES NOT VALIDATE
- Make sure that there actually isn't anything in the settings for 'Empty Text'
Now the view will not display anything until you filter it. However, the next step is to only display something if there aren't any results. Throw the following code into a glue module:
function MODULENAME_views_pre_render(&$view) {
if ($view->name == 'VIEWNAME' && count($view->result) == 0) {
if ($view->current_display == 'DISPLAY' && $view->exposed_data['EXPOSEFIELD'] != 'All')
$view->attachment_after = HTML;
}
}
Change the following to fit your needs:
- MODULENAME - The name of your module.
- VIEWNAME - The name of the view you are working with.
- DISPALY - This may or may not be needed. If you have more than one display on this view, then you will need to be specific.
- EXPOSEDFIELD - This will vary depending on what field you have exposed or not.
- HTML - The message, plain text or HTML to display when no results are found.
Setting up a Static IP and route in Linux
The first step is to setup the interface with an IP and a netmask:
# ifconfig eht0 192.168.1.25 netmask 255.255.255.0 up
Next we need to tell where we want to route the information to:
# route add default gw 192.168.1.1 eth0
The above command is saying that we want a default gateway on interface eth0 to be 192.168.1.1 which is a router.
Creating a Database, User, and Granting Privleges
I always for get how to creat a database, user, and granting privileges to the new user for that database:
> CREATE DATABASE new_db; Query OK, 1 row affected (0.02 sec) > CREATE USER 'new_user'@'localhost' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.03 sec) > CREATE USER 'new_user'@'%' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.03 sec) > GRANT ALL PRIVILEGES ON 'new_db'.* TO 'new_user'@'localhost' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.03 sec) > GRANT ALL PRIVILEGES ON 'new_db'.* TO 'new_user'@'%' IDENTIFIED BY 'password'; Query OK, 0 rows affected (0.03 sec)
Privileges
| ALL |
| ALTER |
| ALTER_ROUTINE |
| CREATE |
| CREATE ROUTINE |
| CREATE TEMPORARY TABLES |
| CREATE USER |
| CREATE VIEW |
| DELETE |
| DROP |
| EVENT |
| EXECUTE |
| FILE |
| GRANT OPTION |
| INDEX |
| INSERT |
| LOCK TABLES |
| PROCESS |
| REFERENCES |
| RELOAD |
| REPLICATION CLIENT |
| REPLICATION SLAVE |
| SHOW DATABASES |
| SHOW VIEWS |
| SHUTDOWN |
| SUPER |
| TRIGGER |
| UPDATE |
| USAGE |
Using Git
Below are some notes on how to use git from day to day.
Basics
| Command | Description |
|---|---|
|
$ git config --global user.name "<your name>" |
Configures git with your name and your email. If you don't do this at a global level or at a repository level, git will complain about this. |
| $ git init | Run this command inside a directory that alread has source code to set up a repository. |
| $ git clone <url> <dest_dir> | Creates a new repository in the specified directory. |
| $ git status | Checks that status of the files in the repository. There are two states for files, one being Tracked, and the other being Untracked. Tracked includes all file that are unmodified, modified, or stages while Untracked is everything else. For example, if you add a file to the repositiory after cloning, then the added file is considered Untracked. |
| $ git add <file> | Adds a file to be tracked and commited next time the commit comand is issued. If you run this command, and then make changes and then commit. The changes that were made after it was staged will not be commited. |
| $ git commit $ git commit -m "message" $ git commit -a -m "message" |
First command will open up the default editor so you can create a commit message. The second command will take the commit message as a parameter. The third command will stage all files and then take the commit message as a parameter. This means you do not need to do git add <file> |
| $ git diff $ git giff --cached |
First command shows what changes that were made and that are unstaged. The second command shows what will be commited. |
| $ git rm <file> $ git rm --cached <file> $ git rm mv <file> <file> |
First command deletes the file from the repository and the hard drive. The second command will remove the file from being tracked. The last command will rename the file. |
Ignoring Files
| Pattern | Description |
|---|---|
| dir/ | Ending slash means to exclude directory. |
| /README | Ignore the README file in root directory. |
| *.log | Ignore all files with the extension of log. |
| !out.log | Do not ignore the out.log file, this would be used in conjunction with the above pattern. |
Git Logs
| Comand | Description |
|---|---|
| $ git log | lists the commits made in the repository in reverse chronological order. |
| $ git log stat | Shows stats on commits. |
| $ git log -p -2 | Shows the differences in each commit. The -2 shows last two commits. |
| $ git log --pretty=format:"%h - %n, %ar : %s" | For mats the log according to user input. |
| $ git log --pretty=format:"%H - %ar" --graph | Displays the commits in a ASCII graph. |
Filtering and Output Options
| Option | Description |
|---|---|
| -p | Shwo the patch introduced with each commit. |
| --stat | Show statics for files modified in each commit. |
| --shortstat | Display only the changed/insertions/deletions line from the --stat command. |
| --name-only | Show the list of files modified after the commit information. |
| --name-status | Show the list of files affected with added/modified/deleted information as well. |
| --abbrev-commit | Display the date in relative format instead of using the full date format. |
| --graph | Show an ASCII graph of the brand and merge history beside the log output. |
| --pretty | show commits in an alternat format. Options include oneline, short, full, fuller, and format -- where you specify your format. |
| -(n) | Show the last n commits. |
| --since, --after | Limit the commits to those made after a specified date. |
| --until, --before | Limit the commits to those made before a specified date. |
| --author | Only show commits in which the author entry matches the specified string. |
| --commiter | Show only mitts in which the commiter entry matches the specified string. |
Log Formatting Options
| Option | Description |
|---|---|
| %H | Commit Hash |
| %h | Abbreviated commit hash |
| %T | Tree hash |
| %t | Abbreviated tree hash |
| %P | Parent hashes |
| %p | Abbreviated parent hashes |
| %an | Author name |
| %ae | Author email |
| %ad | Author date |
| %ar | Author date, relative |
| %cn | Commiter name |
| %ce | Commiter e-mail |
| %cd | commiter date |
| %cr | commiter date, relative |
| %s | subject |
Changing Last Commit
$ git commit -m "message" $ git add stdio.h $ git commit --ammend
Misc commands
To unstage a file:
$ git reset HEAD stdio.h
To discard changes to a file
$ git checkout -- stdio.h
Working with Remote Repositories
| Command | Description |
|---|---|
| $ git remote -v | Shows short name and url for repositories |
| $ git remote add <name> <url> | Adds a remote repository. |
| $ git fetch <remote-name> | Doing this will give you access to all branches of the remote repository. No local files will exist for you to work on.To get files to work on, you must check out the branch. |
| $ git pull | gets a branch and merges it. |
| $ git push <remote-name> <branch> | Pushes a branch to a remote repository. If the remote branch has changed since you started working on it, you must run git fetch <remote-name> to synchornize the work. |
| $ git remote rename <from> <to> | Rename |
| $ get remote rm <remote-name> | Deletes a remote name. |
Defaulting PHP safe_mode to off in Plesk
When creating a domain in Plesk, PHP safe_mode is enabled by default. To change the default behavor do the following as the admin:
- On the home screen in Plesk go to Event Manager
- Click on Add New Event Handler
- Fill in the form with the following values:
Event: Physical Hosting Created
Priority: default is fine
User: root
Command: /usr/local/psa/bin/domain -u <new_domain_name> -php_safe_mode false
Adding Custom Fields to Ubercart Checkout
I had to add the SKU to the checkout of Ubercart, to do that, I had to do the following:
function MODULENAME_form_alter(&$form, &$form_state, $form_id) {
switch($form_id) {
....
case 'uc_cart_view_form':
// Reordering existing columns
$form['items']['#columns']['desc']['weight'] = 3;
$form['items']['#columns']['qty']['weight'] = 4;
// Adding SKU column
$form['items']['#columns']['sku'] = array('cell' => 'SKU', 'weight' => 2);
// Iterating through the items array element. Since there are more than just
// products in this array, we have to make sure we are modifying the correct
// arrays. I do this by checking to see if the element has an array element
// called 'nid'
for($i=0; $i < count($form['items']); $i++) {
if(isset($form['items'][$i]['nid'])) {
// Loading the node so we can retrieve the information we need.
$product = node_load($form['items'][$i]['nid']['#value']);
// Adding the sku/model to the prodct that is in the user's cart.
$form['items'][$i]['sku']['#value'] = $product->model;
$form['items'][$i]['sku']['#cell_attributes'] = array('class' => 'cart-sku');
}
}
break;
......
}
} 