Blogs
New Twitter API v1.1 and getting user status timeline
So I recently had problem with twitter api as they dropped down v1 and now Twitter API v1.1 required authentication for all request to twitter apis. I had implemented twitter api in some of the blogs I developed and this will effect all of them. So Below is code based on WordPress but can be implemented on other php applications as well. You will need to create your app and get consumer key and consumer secret. What this script does is get usertimeline from twitter and saved in cache folder of template which can be later used to display user tweets. I hope it will be useful for you guys who are affected by this version change.
<?php
$twitter_json_file = get_theme_root() . '/' . get_template() . '/cache/twitter.json';
if ((is_file($twitter_json_file) and filemtime($twitter_json_file) < time() - 3600) OR !is_file($twitter_json_file)) {
$consumer_key = 'YOUR-CONSUMER-KEY';
$consumer_secret = 'YOUR-CONSUMER-SECRET';
$screen_name = 'yalamber';
$authorization_key = $consumer_key . ':' . $consumer_secret;
$authorization_header = base64_encode($authorization_key);
$response = wp_remote_post('https://api.twitter.com/oauth2/token', array(
'method' => 'POST',
'httpversion' => '1.1',
'headers' => array('Authorization' => 'Basic ' . $authorization_header, 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'),
'body' => array('grant_type' => 'client_credentials')
));
if (isset($response['body'])) {
$token_body = json_decode($response['body']);
if (isset($token_body->access_token)) {
$access_token = $token_body->access_token;
$response = wp_remote_get("https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" .$screen_name. "&count=5", array(
'httpversion' => '1.1',
'headers' => array('Authorization' => 'Bearer '. $access_token)
));
if (is_wp_error($response)) {
$error_message = $response->get_error_message();
}
else{
file_put_contents($twitter_json_file, $response['body']);
}
}
}
}
$results = file_get_contents($twitter_json_file);
$tweets = json_decode($results, true);
Whynode.com
I just completed development of whynode.com. It is entirely developed in nodejs.
Source code is available in github.com/yalamber/whynode
Contact form 7 useful hook
function wpcf7_mail_users_custom($cfdata) {
$formtitle = $cfdata->title;
$formdata = $cfdata->posted_data;
//logic code here
}
add_action('wpcf7_mail_sent', 'wpcf7_mail_users_custom', 1);
Inotify in nodejs
I recently used nodejs for a part of web app I have been working on. We have to connect to a ftp server and check for new files in that ftp server and process the new files and pull them to our web app server for processing. First we used ftp functions in php and checked file modified time and then ftp get the file. But this process was taking to much of time and as the ftp directory grew it was near impossible to withstand the processing time of that through php script. I searched web for some methods in php that could send in response when there is change in file in specific directory or watch a directory for changes. I came to know about inotify in linux. Wonderful that was what I needed. Inotify was available in php as well.
But as I was interested in learning the nodejs I just thought of why not use nodejs for this part of the web app and searched for if modules were available for nodejs and found this nodejs inotify. It was exactly what I needed. I installed nodejs in the ftp server and added following modules request, forever, inotify
Here is the code that will watch the directory mentioned
'use strict';
var request = require('request');
var fs = require('fs');
var Inotify = require('inotify').Inotify;
var inotify = new Inotify();
var return_watch_dir = function (dir_path) {
var return_data;
return_data = {
path: dir_path,
watch_for: Inotify.IN_CLOSE_WRITE,
callback: function (event) {
var request_url, mask, file_loc, r, str;
request_url = 'http://example.com/call';
mask = event.mask;
file_loc = dir_path + '/' + event.name;
if (mask & Inotify.IN_CLOSE_WRITE) {
r = request.put(request_url + '?file_name=' + event.name);
fs.createReadStream(file_loc).pipe(r);
str = '';
r.on('data', function (chunk) {
str += chunk;
});
r.on('end', function () {
console.log(str);
});
}
}
};
return return_data;
};
//watcher
inotify.addWatch(return_watch_dir('/home/ftpuser/folder_to_watch1'));
inotify.addWatch(return_watch_dir('/home/ftpuser/folder_to_watch2'));
Now I saved it as watch_folder.js and called it using forever.
forever start watch_folder.js
What this script does is watch two folders for inotify in Inotify.IN_CLOSE_WRITE(this means notify when file write is complete.)
In notify callback function I made http put request to the remote server at http://example.com/call which can handle rest.
So this just worked as expected and was fast enough than ftp from php.
AWS SDK php 2 in codeigniter application
I got a change to work on a interesting project where we needed to integrate AWS services like cloudfront and s3 to our application. we started out with using a class from tpyo @ https://github.com/tpyo/amazon-s3-php-class/ but soon found limitations so I decided to use latest AWS SDK for php from amazon available at http://aws.amazon.com/sdkforphp/. I got to try out composer aswell, it is dependency management tool for php and aws sdk was available on it. So today I will be writing up a short tutorial on how to make use of aws sdk on your codeigniter application using composer and will also provide a wrapper library for some methods for services like cloudfront and s3.
You can find this instructions here as well
1. First we need to prepare a composer.json file which will contain aws sdk as dependency in our project root path.
composer.json
{
"require": {
"aws/aws-sdk-php": "*"
}
}
2. Then download and install composer
In terminal do following
curl -s "http://getcomposer.org/installer" | php
php composer.phar install
Above codes will download required files and libraries to vendor directory in our project.
Now we will create a new library called Myaws that will act as wrapper for our methods we will be using exclusively in our app.
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
//composer auto load
include_once FCPATH.'/vendor/autoload.php';
use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Aws\CloudFront\Enum\OriginProtocolPolicy;
use Aws\CloudFront\Enum\ViewerProtocolPolicy;
use Aws\CloudFront\Exception\CloudFrontException;
class Myaws {
private $aws;
private $s3Client;
private $cfClient;
private $cfIdentity;
public $debug=false;
function __construct(){
$CI =& get_instance();
$this->aws = Aws::factory(array(
'key' => $CI->config->item('s3_access_key_id'),
'secret' => $CI->config->item('s3_secret_key')
));
$this->cfIdentity = $CI->config->item('cf_identity');
$this->s3Client = $this->aws->get('s3');
$this->cfClient = $this->aws->get('cloudfront');
}
function isValidBucketName($bucket_name){
try {
if($this->s3Client->isValidBucketName($bucket_name)){
return true;
}
return false;
} catch (S3Exception $e) {
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function doesBucketExist($bucket_name){
try {
if($this->s3Client->doesBucketExist($bucket_name)){
return true;
}
return false;
} catch (S3Exception $e) {
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function createBucket($bucket_name){
if($this->isValidBucketName($bucket_name)){
if($this->doesBucketExist($bucket_name)){
return false;
}
else{
try{
$this->s3Client->createBucket(
array(
'Bucket'=>$bucket_name,
'ACL' => CannedAcl::PUBLIC_READ
//add more items if required here
));
return true;
} catch(S3Exception $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
}
else{
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function _return_bucket_policy($bucket_name = ''){
return '{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity '.$this->cfIdentity.'"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::'.$bucket_name.'/*"
}
]
}';
}
function putBucketPolicy($bucket_name){
if($this->doesBucketExist($bucket_name)){
try{
$this->s3Client->putBucketPolicy(
array(
'Bucket'=>$bucket_name,
'Policy'=>$this->_return_bucket_policy($bucket_name)
));
return true;
} catch(S3Exception $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
else{
return false;
}
}
function deleteBucket($bucket_name){
try {
$this->s3Client->clearBucket($bucket_name);
$this->s3Client->deleteBucket(array(
'Bucket' => $bucket_name
));
return true;
} catch (S3Exception $e) {
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function doesObjectExist($bucket_name, $key){
try {
if($this->s3Client->doesObjectExist($bucket_name, $key)){
return true;
}
return false;
} catch(S3Exception $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function putObject($bucket_name, $key, $body){
try {
$this->s3Client->putObject(array(
'Bucket'=> $bucket_name,
'Key' => $key,
'Body' => $body,
'ACL' => CannedAcl::PUBLIC_READ
));
return true;
} catch(S3Exception $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function deleteObject($bucket_name, $objects){
try {
$this->s3Client->deleteObject(array(
'Bucket' =>$bucket_name,
'Objects' =>$objects
));
return true;
} catch (S3Exception $e) {
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
// $objects should be array(array('Key'=>$key), array('Key'=>$key2)); testing needed here before implementation
function deleteObjects($bucket_name, $keys){
try {
$this->s3Client->deleteObjects(array(
'Bucket' => $bucket_name,
'Key'=> $keys
));
return true;
} catch (S3Exception $e) {
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function createDistribution($bucket_name, $domain_name){
try{
$return = $this->cfClient->createDistribution($this->_return_distribution_config_array($bucket_name, $domain_name, true));
return $return->toArray();
} catch(CloudFrontException $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function _return_distribution_config_array($bucket_name= '', $domain_name = '', $enabled = true){
$origin_id = 'S3-'.$bucket_name;
return array(
'CallerReference' => md5(time()),
'Aliases' => array(
'Quantity'=>1,
'Items'=> array($domain_name)
),
'DefaultRootObject' => 'index.html',
'Origins' => array(
'Quantity' => 1,
'Items' => array(
array(
'Id' => $origin_id,
'DomainName' => strtolower($bucket_name.'.s3.amazonaws.com'),
'S3OriginConfig' => array(
'OriginAccessIdentity' => 'origin-access-identity/cloudfront/'.$this->cfIdentity
)
)
)
),
'DefaultCacheBehavior' => array(
'TargetOriginId' => $origin_id,
'ForwardedValues' => array(
'QueryString' => false
),
'TrustedSigners' => array(
'Enabled' => false,
'Quantity' => 0,
'Items' => array()
),
'ViewerProtocolPolicy' => ViewerProtocolPolicy::ALLOW_ALL,
'MinTTL' => 0
),
'CacheBehaviors' => array('Quantity' => 0, 'Items' => array()),
'Comment' => 'Distribution for '.$bucket_name,
'Logging' => array(
'Enabled' => false,
'Bucket' => '',
'Prefix' => ''
),
'Enabled' => $enabled
);
}
function disableDistribution($cfID){
try{
$getConfig = $this->cfClient->getDistributionConfig(array('Id' => $cfID));
$got_config_array = $getConfig->toArray();
try{
$config_array = $got_config_array;
$config_array['Enabled'] = false;
$config_array['Id'] = $cfID;
$config_array['IfMatch'] = $got_config_array['ETag'];
$config_array['Logging'] = array(
'Enabled' => false,
'Bucket' => '',
'Prefix' => ''
);
unset($config_array['ETag']);
unset($config_array['RequestId']);
$this->cfClient->updateDistribution($config_array);
} catch(CloudFrontException $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
} catch(CloudFrontException $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
function deleteDistribution($cfID){
try{
$getDistribution = $this->cfClient->getDistribution(array('Id' => $cfID));
$got_distribution_array = $getDistribution->toArray();
if($got_distribution_array['Status'] == 'Deployed' and $got_distribution_array['DistributionConfig']['Enabled'] == false){
try{
$this->cfClient->deleteDistribution(array('Id' => $cfID, 'IfMatch' => $got_distribution_array['ETag']));
return true;
} catch(CloudFrontException $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
else{
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
} catch(CloudFrontException $e){
if($this->debug){
return $e->getMessage();
}
else{
return false;
}
}
}
}
This library includes the vendor auto load file from composer and uses required namespaces for the library. The methods in this library are itself self explanatory. I have set some config items in constructer. You can add them in your codeigniter config file as follows:
$config['aws_access_key_id'] = ''; $config['aws_secret_key'] = ''; $config['cf_identity'] = '';
You can get these values from your aws management panel.
Now to use this library simply load the library and call the required methods in your controller:
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Testaws extends MY_Controller
{
function __construct() {
parent::__construct();
$this->load->library('myaws');
}
function index() {
$this->myaws->createBucket('bucketname');
$this->myaws->putBucketPolicy('bucketname', 'Bucket Policy in Json format here');
$this->myaws->putObject('bucketname', 'keyname.txt', 'body content');
$this->myaws->createDistribution('bucketname', 'domain');
$this->myaws->disableDistribution('distribution ID');
$this->myaws->deleteDistribution('distribution ID');
}
That’s it you can add more methods as required. You can find detailed API documentation here. If you need any help regarding the use of sdk and api let me know in comments I will try to help you out.
Get the latest version number of WordPress Using API
I am going to show you how to check for the latest version of WordPress using API provided by WordPress.
Below is the code to get the latest version of WordPress from api at http://api.wordpress.org/core/version-check/1.6/ [I did not know it existed. but there are several API provided by WordPress, go to http://codex.wordpress.org/WordPress.org_API]
You will have to create a cache folder which will save the response in a file so that we do not ping the WordPress server often. You can use this code in your website to show latest version number as I have done in wpambulance.com
<?php
function getData($url) {
if(is_callable('curl_init')){
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}else{
return file_get_contents($url);
}
}
//check for latest WordPress version
$apiUrl = 'http://api.wordpress.org/core/version-check/1.6/';
$apiFile = 'cache/api.json';
if((is_file($apiFile) and filemtime($apiFile)< time()-3600) OR !is_file($apiFile))
{
$apiContent = getData($apiUrl);
if($apiContent!=''){
file_put_contents($apiFile, $apiContent);
}
}
$apiContent = file_get_contents($apiFile);
$apiReturn = unserialize($apiContent);
$current_version = $apiReturn['offers'][0]['current'];
?>
Making .svn directory not show up in apache
In your virtual host entry add following:
<DirectoryMatch \.svn> Order allow,deny Deny from all </DirectoryMatch>
Listing chmod status in linux
stat -c '%A %a %n' *
Auto updating your dev ec2 environment with svn on codebasehq
I wanted to auto update my dev environment whenever commit happens on my codebasehq Repo. Below is my solution based on php, ssh using phpseclib.
Below is my php script that uses ssh to run svn update command, we can name it as updater.php and place it in root folder.
<?php
@set_time_limit( 0 );
set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include('Net/SSH2.php');
include('Crypt/RSA.php');
$ssh = new Net_SSH2('devserver.com');
$key = new Crypt_RSA();
$key->setPassword('passphrase');
$key->loadKey('your key here');
if (!$ssh->login('username', $key)) {
exit('Login Failed');
}
echo $ssh->exec('svn update /var/www');
In your codebasehq repo setting place url in post-receive hook to your updater script written in php. http://yourdevserver.com/updater.php
you need to checkout repo in your dev server then after each commit it will get auto updated by this script.