September
8th 2011
Shortcode in Feedburner Email Widget 1.1.3 for wordpress

Posted under Feedburner Email Widget & JavaScript & Releases & Wordpress

In the just released Feedburner Email Widget 1.1.3 a shortcode has been added by request. The shortcode can be used in 2 different ways in posts you use

1
[feedburner_email_widget uri="http://feedburner.url.here"]

and in php you use

1
<?php echo feedburner_email_widget_shortcode_func(array('uri'=>"http://feedburner.url.here")); ?>

Both methods make a call to the same function and the arguments reflect the available settings for the widget through the wp-admin.

  • Title -> title
  • Feedburner feed URL -> uri
  • Above input text -> above_email
  • Below input text -> below_email
  • Input placeholder text -> email_text_input
  • Submit button caption -> subscribe_btn
  • Show feedburner link -> show_link
  • Form CSS ID -> form_id
  • CSS Styling -> css_style_code
  • Analytics Category -> analytics_cat
  • Analytics Action -> analytics_act
  • Analytics Label -> analytics_lab
  • Analytics Value -> analytics_val

3 Comments »

October
31st 2010
A styling guide for @predominant cakephp tags plugin article

Posted under Cakephp & Snippets

This post assumes you’ve completed reading Graham Weldon (@predominant) article on using the plugin, the plugin pages them self and in specific the the tag cloud helper page. The helper example sets a size attribute  on the li tag. A way to utilize this would be writing a piece of jQuery (or javascript in general) that would take it and apply some styling to it. This would mean a lot more resource usage compared to pure CSS.

The PHP

At the PHP side we need to change a few things currently this is the code:

1
2
3
echo $this->TagCloud->display($tags, array(
    'before' => '<li size="%size%" class="tag">',
    'after' => '</li>'));

We’ll be change that into this:

1
2
3
4
5
echo $this->TagCloud->display($tags, array(
    'before' => '<li class="fs%size% tag">',
    'after' => '</li>',
    'maxSize' => 50,
    'minSize' => 1));

As you can see a few things change. First off we also supply the min and maxSize options. The helper uses these and calculates a number in between those values, we’ll use those numbers for the CSS classes later on. A option that change is before as you can see %size% is now used for a class, this class will contain it’s font-size and any options you might want to add yourself.

Generating the CSS

If your lazy and just want a working example you can skip this bit and skip to The CSS. Since the example requires 50 css class and it takes alot of time to calculate the required values by hand I’ve a little script to do it for me/us.

1
2
3
4
5
6
7
8
9
10
11
<?php
$css = '';
$class = 'fs';
$start_size = 0.75;
$stop_size = 2.5;
$count = 50;
$precision = 4;
for($i=1;$i<=$count;$i++) {
        $css .= '.' . $class . $i . '{font-size:' . round((((($stop_size - $start_size) / ($count - 1)) * ($i - 1)) + $start_size),$precision) . "em;}\r\n";
}
echo $css;

The script has a few configuration values.

  • class – the prefix to the %size% value
  • start_size – the smallest possible tag size in em
  • stop_size – the biggest possible tag size in em
  • count – The number of classes and for now 50 :)
  • precision – the maximum of digest behind the dot

The CSS

1
2
3
.fs1{font-size:0.75em;}
...
.fs50{font-size:2.5em;}

(Click here for the complete list.)

The Result

1 Comment »

May
19th 2010
Feedburner email widget for WordPress

Posted under Feedburner Email Widget & Releases & Wordpress

Since I started using WordPress a few weeks ago 1 thing been nagging me. No Feedburner email subscription widget that suits my needs, so decided to make one myself. The result is a simple widget for your themes sidebar that lets your visitors subscribe to you feed in a breeze. Feedburner email widget has been accepted as a plugin bij WordPress yesterday and the first release was pushed today.

The Widget:

Widget control:

For more information please consult the project page.

No Comments »

May
15th 2010
Flattr MOD for phpBB3

Posted under Flattr MOD & phpBB3

A few days ago Flattr send me a beta invite to their website. Checking around their site on the plugin page I noticed there wasn’t a phpBB3 mod for it. Decided to write one and the first RC is read for download. The mod adds badges to the forum on 2 different places viewtopic and viewforum depending on the settings in the ACP.

Viewtopic:

Viewforum:

For more information check the project page.

3 Comments »

May
3rd 2010
phpBB3 Toplist MOD 2.0RC3 released

Posted under phpBB3 & Toplist MOD

After months of work RC3 is finished. It comes with a brand new UMIL installer, 2 extra designs and a new security update warning system. This RC took a whole lot longer then I wanted, heck closing into a year since RC2. Not happy with it but I think this release is worth it below you find all changes, additions and fixes. You can download the mod from the forums in the 2.0RC3 Download topic.

Change log

No Comments »

April
28th 2010
Cakephp url shorten behavior (0x.tc, bit.ly, is.gd and u.nu)

Posted under Cakephp & Snippets

A while ago I started working on some twitter services and I needed an automatic urlshortner. This first started as a model that would shorten en url and save the result in a table for caching purposes. After a good chat with a friend (beeman) it turned into a behavior with the model only using the behavior to act like it did before. One of the reasons for a behavior was to create a simple interface for the developer without the need to poll the caching model but at the same time be able to use the cache model when the resulting short url wouldn’t be stored anywhere else (like an autmatic tweet). The model currently supports 4 different services (I want to add more in the future tho so any suggestions are welcome): 0x.tc, is.gd, bit.ly and u.nu.

Configuration

mode has 2 possible options ordered (default) or randomize. ordered checks the order in order while randomize uses shuffle to randomize the order.
Example:

1
'mode' => 'ordered',

fields is an array with fields that the behavior should send to the services to shorten the url (note that the value in the field MUST be an url). This option has no default value!
Example:

1
2
3
'fields' => array(
    'short'
),

order is an array with the services listed in the order to use. This option wil only be used is mode is set to ordered else if mode is set to randomize it will grab the default order array and overwrite what you place in order.
Example:

1
2
3
4
5
6
'order' => array(
                'zero_xtc',
                'bit_ly'
                'u_nu',
                'is_gd',
),

retries number of times it loops through the list of shortners before giving up. Default value is 5.
Example:

1
'retries' => 10,

shortners list with shortners and their options. All the shortners have an enable option. Shortners that require an API key also have key option to store the needed API key.
Example:

1
2
3
4
5
6
7
8
9
10
            'shortners' => array(
                'bit_ly' => array(
                    'enable' => true,
                    // Go to http://bit.ly/account/your_api_key to get yours
                    'key' => array(
                        'login' => 'YOUR_BITLY_API_LOGIN_HERE',
                        'key' => 'YOUR_BITLY_API_KEY_HERE'
                    ),
                ),
            ),

http_config is an array for the Cakephp HttpSocket class. An example an option is the time out, you can find all possible at the 1.2 API (or 1.3 ofcourse ;) ). The default configuration is shown in the example below.
Example:

1
2
3
            'http_config' => array(
                            'timeout' => 10
            ),

http_headers is an array for additional HTTP headers like the User-Agent. The default configuration is shown in the example below.
Example:

1
2
3
            'http_headers' => array(
                            'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1'
            ),

Files

Following are the mode and behavior. The model also shows the basic configuration for the behavior tell it what field in the database to shorten urls for. It also

app/models/shorturl.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Shorturl extends AppModel {
    public $actsAs = array(
        'Shorturl' => array(
            'fields' => array(
                'short'
            ),
        ),
    );
    public function shorten($long_url) {
        $url = $this->findByLong($long_url);
        if(!$url) {
            $data = array();
            $data['long'] = $long_url;
            $data['short'] = $long_url;
            $this->create();
            $this->save($data);
            $url = $this->findByLong($long_url);
        }
        return $url['Shorturl']['short'];
    }
}

The models database table (as a (My)SQL query)

1
2
3
4
5
6
CREATE TABLE IF NOT EXISTS `shorturls` (
  `id` INT(32) NOT NULL AUTO_INCREMENT,
  `long` VARCHAR(1024) NOT NULL,
  `short` VARCHAR(255) NOT NULL,
  PRIMARY KEY  (`id`)
) TYPE=MyISAM  AUTO_INCREMENT=1 ;

app/models/behaviors/shorturl.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
class ShorturlBehavior extends ModelBehavior {
    private $defaults = array(
            'fields' => array(),
            'shortners' => array(
                            'zero_xtc' => array(
                                            'enable' => true,
                            ),
                            'is_gd' => array(
                                            'enable' => true,
                            ),
                            'bit_ly' => array(
                                            'enable' => true,
                                            // Go to http://bit.ly/account/your_api_key to get yours
                                            'key' => array(
                                                            'login' => '',
                                                            'key' => ''
                                            ),
                            ),
                            'u_nu' => array(
                                            'enable' => true,
                            ),
            ),
            'order' => array(
                            'zero_xtc',
                            'is_gd',
                            'bit_ly',
                            'u_nu',
            ),
            'http_config' => array(
                            'timeout' => 10
            ),
            'http_headers' => array(
                            'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1'
            ),
            'retries' => 5,
            'mode' => 'ordered',
    );
    public $settings = array();
    public function setup(&$model,$config = array()) {
        $this->settings[$model->alias] = $this->defaults;
        $this->settings[$model->alias] = $this->array_merge_recursive_distinct($this->settings[$model->alias],(array) $config);
    }
    public function beforeSave(&$model) {
        if(isset($this->settings[$model->alias]['fields'])) {
            foreach($this->settings[$model->alias]['fields'] as $void => $field) {
                if(isset($model->data[$model->alias][$field]) && !empty($model->data[$model->alias][$field]) && ((version_compare(phpversion(), '5.2.0', '>=') && function_exists('filter_var')) ? filter_var($model->data[$model->alias][$field], FILTER_VALIDATE_URL) : true)) {
                    $model->data[$model->alias][$field] = $this->shorten($model,$model->data[$model->alias][$field]);
                }
            }
        }
        return true;
    }
    private function shorten(&$model,$long_url) {
        App::import('Core', 'Set');
        App::import('Core', 'Xml');
        App::import('Core', 'HttpSocket');
        if($this->settings[$model->alias]['mode']=='randomize') {
            $this->settings[$model->alias]['order'] = $this->defaults['order'];
            shuffle($this->settings[$model->alias]['order']);
        }
        for($j=0;$j<($this->settings[$model->alias]['retries'] + 1);$j++) {
            foreach($this->settings[$model->alias]['order'] as $shortner) {
                if($this->settings[$model->alias]['shortners'][$shortner]['enable']) {
                    $short_url = $this->{$shortner}($model,$long_url);
                    if($short_url && !empty($short_url) && !is_null($short_url) && ((version_compare(phpversion(), '5.2.0', '>=') && function_exists('filter_var')) ? filter_var($short_url, FILTER_VALIDATE_URL) : true)) {
                        return $short_url;
                    }
                }
            }
        }
        return $long_url;
    }

    private function zero_xtc(&$model,$long_url) {
        $this->Http = new HttpSocket($this->settings[$model->alias]['http_config']);
        $request = 'http://0x.tc/x?go=' . rawurlencode($long_url) . '&t=' . time();
        $response = $this->Http->get(
                $request,
                array(),
                array('header' => $this->settings[$model->alias]['http_headers'])
        );
        $response = Set::reverse(new Xml($response));
        if(is_array($response['Taken']['xUrl'])) {
            return false;
        }
        elseif(substr($response['Taken']['xUrl'], 0, 4) == 'http') {
            return $response['Taken']['xUrl'];
        }
        else {
            return false;
        }
    }

    private function is_gd(&$model,$long_url) {
        $this->Http = new HttpSocket($this->settings[$model->alias]['http_config']);
        $request = 'http://is.gd/api.php?longurl=' . urlencode($long_url);
        $response = $this->Http->get(
                $request,
                array(),
                array('header' => $this->settings[$model->alias]['http_headers'])
        );
        if (substr($request, 0, 4) == 'http') {
            return $response;
        }
        else {
            return false;
        }
    }

    private function bit_ly(&$model,$long_url) {
        if(isset($this->settings[$model->alias]['shortners']['bit_ly']['key']['login']) && !empty($this->settings[$model->alias]['shortners']['bit_ly']['key']['login']) && isset($this->settings[$model->alias]['shortners']['bit_ly']['key']['key']) && !empty($this->settings[$model->alias]['shortners']['bit_ly']['key']['key'])) {
            $this->Http = new HttpSocket($this->settings[$model->alias]['http_config']);
            $request = 'http://api.bit.ly/shorten?version=2.0.1&longUrl=' . urlencode($long_url) . '&login=' . $this->settings[$model->alias]['shortners']['bit_ly']['key']['login'] . '&apiKey=' . $this->settings[$model->alias]['shortners']['bit_ly']['key']['key'];
            $response = $this->Http->get(
                    $request,
                    array(),
                    array('header' => $this->settings[$model->alias]['http_headers'])
            );
            $response = json_decode($response);
            if ($response->errorCode==0 && $response->statusCode=='OK' && isset($response->results->{$long_url}->shortUrl)) {
                return $response->results->{$long_url}->shortUrl;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    private function u_nu(&$model,$long_url) {
        $this->Http = new HttpSocket($this->settings[$model->alias]['http_config']);
        $request = 'http://u.nu/unu-api-simple?url=' . urlencode($long_url);
        $response = $this->Http->get(
                $request,
                array(),
                array('header' => $this->settings[$model->alias]['http_headers'])
        );
        if (substr($request, 0, 4) == 'http') {
            return $response;
        }
        else {
            return false;
        }
    }

    // Taken from: http://www.php.net/manual/en/function.array-merge-recursive.php#96201
    /**
     * Merges any number of arrays / parameters recursively, replacing
     * entries with string keys with values from latter arrays.
     * If the entry or the next value to be assigned is an array, then it
     * automagically treats both arguments as an array.
     * Numeric entries are appended, not replaced, but only if they are
     * unique
     *
     * calling: result = array_merge_recursive_distinct(a1, a2, ... aN)
     **/


    private function array_merge_recursive_distinct () {
        $arrays = func_get_args();
        $base = array_shift($arrays);
        if(!is_array($base)) $base = empty($base) ? array() : array($base);
        foreach($arrays as $append) {
            if(!is_array($append)) $append = array($append);
            foreach($append as $key => $value) {
                if(!array_key_exists($key, $base) && !is_numeric($key)) {
                    $base[$key] = $append[$key];
                    continue;
                }
                if(is_array($value) || (isset($base[$key]) && is_array($base[$key]))) {
                    $base[$key] = $this->array_merge_recursive_distinct($base[$key], $append[$key]);
                } else if(is_numeric($key)) {
                    if(!in_array($value, $base)) $base[] = $value;
                } else {
                    $base[$key] = $value;
                }
            }
        }
        return $base;
    }
}

2 Comments »