Posted under World of Warcraft
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.
Posted under Cakephp & Snippets
EDIT: DerEuroMark wrote an excellent replacement for this helper.
After the Flattr MOD for phpBB3 release 2 days ago I wrote this simple flattr cakephp helper (basic cakephp helper knowledge is required) to aid cakephp developers integrate flattr quick and easy into their websites. The helper has only 1 function and is very simple in use.
Basic usage
1 2 3 4 | <!--?php echo $flattr--->badge(array( 'uid' => 4080, 'tle' => 'test', )); ?> |
As you can see this is the bare minimum in options you need to use to get it to work.
- uid The Flattr User ID as found on the Flattr dashboard (in the example I used mine).
- tle The title for the link to be submitted.
Since the helper supports the full range of options below are the other options:
- dsc A description for the link.
- cat The category for the link. This can be any of the following: text, images, video, audio, software, rest. The default if this option isn’t specified is text.
- lng The language of the link. Any of the languages on this list and defaults to en_GB.
- tags Any tags matching the link. This field must be an array!
- url The URL of the link.
- btn The badge to use. Currently the only option is compact but if not specified or set to something else it defaults to the standard larger badge
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 | <!--?php<br /--> class FlattrHelper extends Helper { public $helpers = array('Javascript'); function badge($options=array()) { App::import('Sanitize'); $vars = ''; $vars .= "var flattr_uid = '" . intval($options['uid']) . "';\r\n"; $vars .= "var flattr_tle = '" . $options['tle'] . "';\r\n"; if(!isset($options['dsc'])) { $options['dsc'] = ''; } $vars .= "var flattr_dsc = '" . $options['dsc'] . "';\r\n"; if(!isset($options['cat'])) { $options['cat'] = 'text'; } $vars .= "var flattr_cat = '" . $options['cat'] . "';\r\n"; if(!isset($options['lng'])) { $options['lng'] = 'en_GB'; } $vars .= "var flattr_lng = '" . $options['lng'] . "';\r\n"; if(isset($options['tags']) && count($options['tags'])>0) { array_walk($options['tags'],'Sanitize::paranoid'); $vars .= "var flattr_tag = '" . implode(', ',$options['tags']) . "';\r\n"; } if(isset($options['url']) && ((version_compare(phpversion(), '5.2.0', '>=') && function_exists('filter_var')) ? filter_var($options['url'], FILTER_VALIDATE_URL) : true)) { $vars .= "var flattr_url = '" . $options['url'] . "';\r\n"; } if(isset($options['btn']) && $options['btn']=='compact') { $vars .= "var flattr_btn = 'compact';\r\n"; } $code = $this->Javascript->codeBlock($vars, array('inline' => true)); $code .= $this->Javascript->link('http://api.flattr.com/button/load.js', array('inline' => true)); return $code; } } |
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.
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
- Fixed: GD Images Preview showing wrong images
- Fixed: Wrong caption on submit button edit site
- Fixed: Only admins can for code check for site
- Fixed: GD Images cache check to late
- Added: Enduser Documentation
- Fixed: Score not showing
- Improved: Priority ranking
- Fixed: Edit/Add site tab index fucked
- Fixed: Double $phpbb_root_path’s causing & not parsed properly by firefox
- Fixed: No email send after adding toplist
- Fixed: Upgrade version updating not properly
- Fixed: Lang strings in templates aren’t all place into lang file
- Fixed: Check code link not working
- Improved: Version check by hooking it also into the cron and let it send out an email to all board admins.
- Improved: Language system support improved by migrating language indexes into their own file. Also added email support that was intended to be in all along.
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
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; } } |
Posted under Site News
Last night I ported all my 239 blog posts to wordpress. One reason for this dicision is that I want to have more time to spend on bAdaptive, WyriMaps.net, my phpBB3 mods and my other projects. Also having to develope a blog slowed those projects down and I went for a fully function blog application to speed it up and be able to publish new posts, articles and thougths easy and fast. The day before yesterday I already ported the WyriMaps.net blog for the same reason. Comments on this blog should follow fast
. Stay tuned for more articles, project updates and more!
Posted under Uncategorized
With Google Wave mods created for most major open source project but none for phpBB I decided to start one. An easy start with a wave bbcode to embed a wave inside a post/PM. The BBCode part of the mod has almost been finished and needs a few more tweaks and a button in the post window but it can be used to embed waves. You need to be login wave to see the actual wave altho I made it public by adding public@a.gwave.com. So I made this screencast with the help of beeman.The screencast shows the creation of a wave in Google Wave, then the embedding of the wave using the [gwave][/gwave] bbcode tag.
Other features I'm going to build is adding a wave on a profile field and adding wave using template tags anywhere on the board. Altho those 2 are still in the concept phase I'm sure they will be as easy to implement as the bbcode.
WyriHaximus
Posted under World of Warcraft
Between all the coding, testing and sleeping I like to do something graphic once in a while. This time I tried out some idea's for panorama's. I went for Thunderfall in World of Warcraft. Below is the result of this.

Now I have this idea spinning in my mind to create mare of these (higher detail and worked out better tho since this once contains some glitches) and add them to WyriMaps.net. What places should I do before Cataclysm strikes. Lemme know,
WyriHaximus
Posted under World of Warcraft
Just like I did with the WoW Trans logo here is the new logo for World of Warcraft: Cataclysm
Original Size:
1024x 441:








































































































