PHP Playground: Cycle

Scenario:

<?php
  $items = ['Item 1', 'Item 2', 'Item 3'];

  $index = 0 ;
  print "<ul>"; 
  foreach( $items as $item ) { 
    print '<li class="'. ( $index % 2 ? 'even' : 'odd') .'">' . $item . '</li>'; 
    $index++; 
  } 
  print "</ul>";
?>

You can cleanup the code more or use the array key to detect odd/even. For more than 2 class names or other cases where you want to do some cyclic operation there is no simple way. In Ruby they have cycle function that cycles through items. Twig & Smarty introduced cycle for class names.

With PHP5 closure and Functional programming you can build a reusable solution:

<?php

/**
 * Cycle Function that rotates
 */
function cycle( $arr ) {

  return function() use(&$arr){
    $arr[] = array_shift($arr);
    return end($arr);
  };

}

$items = ['Item 1', 'Item 2', 'Item 3'];
$cycle = cycle(['odd','even']);

print "<ul>"; 
foreach( $items as $item ) { 
  print '<li class="'. $cycle() .'">' . $item . '</li>'; 
} 
print "</ul>";

?>

This time I am cycling through functions, maybe you could find its usage.

<?php

function cycle( $arr ) {

  return function( $item ) use(&$arr){
    $arr[] = array_shift($arr);
    $fn = end($arr);
    return $fn( $item );
  };

}

$items = ['Item 1', 'Item 2', 'Item 3'];
$cycle = cycle([
  function($item){ return strtoupper( $item ); },
  function($item){ return ucfirst( $item );  }
]);

print "<ul>"; 
foreach( $items as $item ) { 
  print '<li>' . $cycle($item) . '</li>'; 
} 
print "</ul>";

?>

If you have a better alternate plz share your thoughts.

Advertisement

Drupal Module Review: Services

URL :    Services
Sample Gist:  Request

Client wants to create a mobile application, now asks for JSON endpoints to fetch datas from your Drupal website. The easiest route has always been to create a menu route and a callback. Easy to work and we have control. In this setup things gets complicated when:

  • All these requests can only be accessed by logged in user.
  • Coding gets messy: Like you want to through an output of a view. In some harsh setup we had to get views result set then manually handled output. There are few supportive modules like views_data_export.
  • Need more fine grained control based on permission.
  • Today its json later they might ask for SOAP layer.

A scratch ( i call this) solution may seem attractive and faster but in a large system it all depends on the architecture you set up.

Services module provides robust base for mobile application to website communication. It provides multiple interfaces : XML, JSON etc. It ships with few helpful resources: user, node, views etc. Then you can create custom resource that can be exposed via services.

Here are few lessons I learnt during integration [ More to come ]:

Authentication: 

I used session authentication. Services module has a huge handbook that covers in details. But it took some time for me get hang on authentication. Here is gist that based on guzzle which shows sample request to drupal7 services.

Drupal 7 Migrate

Every now and then we came across projects that requires migration. The old website could be a WordPress, CodeIgniter or some other database driven application. Usually we do such migrations using Custom module with batch processing. In last project in Drupal 7 i decided to give a shot to migrate module. After few trial and error i found this to be ultimate solution to migration. I tried with csv data and mysql table; both solution took 25% time to solve compare to my old custom module solution.  I have also seen couple posts that explains how to migrate html raw files.

You can learn more about migrate module from their documentation, their sample migrate_example module also has tons of examples. Do look at migrate_extras that provides support for additional contributed modules.

Here i am collecting some obstacles that i faced and their solution.

I am migrating contents from old website but want to keep their url alias due to SEO factor. I have pathauto module setup but don’t want to trigger that.

// Block pathauto from interfering. This requires migrate_extras
$this->addFieldMapping('pathauto')->defaultValue(false);
// Lets Put new Path
$this->addFieldMapping('path', 'old_path');

After i migrate body content it seems full_html text format is not placed. Drupal is splitting the html code as plain text. Solution:

$this->addFieldMapping('body', 'content');  
$this->addFieldMapping('body:format')->defaultValue('full_html'); // You can set other formats

In that old system there was this type which is a select option with value : On and off . In D7 i have set this as  a Term Reference field. I had to use prepareRow to map select value to tid.

class MyNodeMigration extends Migration{

 public function __construct( $arguments )
 {
   #.. Other Code 
   $this->addFieldMapping('field_status', 'status');
   $this->addFieldMapping('field_status:source_type')->defaultValue('tid');;
   #.. Other code
 }

 public function prepareRow($row)
 {
   $row->status = $row->status === 'On' ? 12 : 13;
 }
}

I am migrating over 65,000 Contents. All my trials were less than 100 entries and i was happy to see the throughput which was over 800/min. Then I start a full run and things start to look horrific. At some point i am getting throughput of 2/min which means to finish all content migration will take 541 Hours . Impossible! . After few tinkering i re-run the test and i able to migrate 11000 posts within 15minutes.  Awesome!

$query = db_select('tbl_pages', 'page');
  #.. Other codes
   $query->orderBy('id');
  #.. Other code
 $this->highwaterField = array(
     'name' => 'id',
     'alias' => 'page',
     'type' => 'int', );

In my case, i had to skip particular rows based on some logic which i could not able to ignore in MySQL. You can put such logics inside prepareRow function.

public function prepareRow($row){
   // This will skip this row 
   if( $row->type == 'blah' and $row->some == 'foo' )  return FALSE; 
}

Make your terminal cool

Screen Shot 2014-07-03 at 4.01.45 PM

 

You can achieve this terminal look easily with few quick steps. In my case, I am using iterm2 in osx mavericks along with zsh powered by oh-my-zsh. I do know that its possible in bash too. My recipe does works in Mint, Ubutu too. Not sure of Fedora 😦 .. So lets begin.

Installing zsh and make it default shell

Install zsh using yum, brew or apt-get. In case of ubuntu run :    $sudo apt-get install zsh   . It will  ask for your password and finally it should complete its setup. Then we set zsh as default shell by running : $chsh -s /bin/zsh . To see the effect you have to logout then login. But dont logout now. As running zsh first time ; it asks to setup zshrc file for you. We want to logout after configuring our zshrc first.

Configuring oh-my-zsh

Lets quickly run few more commands. Dont blindly run commands try to understand each command .

$git clone https://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
$mkdir -p ~/.bin/dotfiles/zsh/
$cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.bin/dotfiles/zsh/zshrc
$ln -s ~/.bin/dotfiles/zsh/zshrc  ~/.zshrc

By running all this we are setting our default zshrc file. Now you can logout and login again to find zsh as your default shell.

Installing ducknorris theme and Powerline fonts

You are so close. We have to configure ducknorris theme and powerline fonts. Download powerline fonts from here and configure one of the fonts in your terminal profile preference. Then create ducknorris.zsh-theme file inside ~/.bin/dotfiles/zsh/ducknorris.zsh-theme  .  Copy the theme content from that website and paste it into the file. Now run following command :

$ln -s ~/.bin/dotfiles/zsh/ducknorris.zsh-theme ~/.oh-my-zsh/themes/

Edit ~/.bin/dotfiles/zsh/zshrc file and change replace ZSH_THEME setting to following :

ZSH_THEME="ducknorris"

POWERLINE_DETECT_SSH="true"
POWERLINE_GIT_CLEAN="✔"
POWERLINE_GIT_DIRTY="✘"
POWERLINE_GIT_ADDED="%F{green}✚%F{black}"
POWERLINE_GIT_MODIFIED="%F{blue}✹%F{black}"
POWERLINE_GIT_DELETED="%F{red}✖%F{black}"
POWERLINE_GIT_UNTRACKED="%F{yellow}✭%F{black}"
POWERLINE_GIT_RENAMED="➜"
POWERLINE_GIT_UNMERGED="═"
POWERLINE_HIDE_HOST_NAME="true"
POWERLINE_RIGHT_A="exit-status"

 

Reopen terminal to see your cool new terminal look. I usually keep all my dotfiles inside ~/.bin/dotfiles and sync them to a private repository in bitbucket. You can do that too. Have Fun !!