<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8924822430815499389</id><updated>2011-10-30T23:14:25.718+04:00</updated><category term='Trac'/><category term='http://www.blogger.com/img/blank.gif'/><category term='tool'/><category term='free'/><category term='programming'/><category term='TracAdmin'/><category term='UI'/><category term='version control'/><category term='project'/><category term='freelance'/><category term='service'/><category term='vcs'/><category term='issue trackers'/><category term='repository'/><category term='management'/><category term='library'/><title type='text'>Freelance programer's notes</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-315060662249421847</id><published>2011-10-30T22:59:00.002+04:00</published><updated>2011-10-30T23:14:25.749+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='library'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='freelance'/><title type='text'>C# Line Numbering Control for RichTextBox</title><content type='html'>I have spent some free time to port a &lt;a href="http://www.codeproject.com/KB/cpp/linenumbers_for_rtb.aspx"&gt;control&lt;/a&gt; from VB.Net to &lt;span style="font-weight: bold;"&gt;C#&lt;/span&gt; and refactor it a little bit. This &lt;span style="font-weight: bold;"&gt;UI control&lt;/span&gt; attaches to &lt;span style="font-weight: bold;"&gt;RichTextBox &lt;/span&gt;and &lt;span style="font-weight: bold;"&gt;displays line numbers&lt;/span&gt; for the text. The control has many settings and re-paints quickly and exactly.&lt;br /&gt;You may get it here: &lt;a href="https://github.com/antgraf/C--Numbered-Lines-Control-for-RichTextBox--LineNumbersControlForRichTextBox-"&gt;https://github.com/antgraf/C--Numbered-Lines-Control-for-RichTextBox--LineNumbersControlForRichTextBox-&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-315060662249421847?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/315060662249421847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=315060662249421847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/315060662249421847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/315060662249421847'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2011/10/c-line-numbering-control-for.html' title='C# Line Numbering Control for RichTextBox'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-970982126305612184</id><published>2011-07-24T19:52:00.014+04:00</published><updated>2011-07-24T22:26:27.152+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http://www.blogger.com/img/blank.gif'/><title type='text'>Free embedded databases for C# (.Net) performance overview</title><content type='html'>I have tested several open-source embedded DB engines for .Net to find which one is the best for my purposes.&lt;br /&gt;My choice for testing was:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.firebirdsql.org/"&gt;FireBird 2.5 .Net Provider&lt;/a&gt; with &lt;a href="http://tracker.firebirdsql.org/browse/DNET-386"&gt;patch applied&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/sqlite-net/"&gt;sqlite-net&lt;/a&gt; r.71 with &lt;a href="http://code.google.com/p/sqlite-net/issues/list?can=2&amp;amp;q=stack&amp;amp;colspec=ID+Type+Status+Priority+Milestone+Owner+Summary&amp;amp;cells=tiles"&gt;patch applied&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://system.data.sqlite.org/index.html/doc/trunk/www/index.wiki"&gt;System.Data.SQLite 1.0.74.0 (3.7.7.1) x86&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;a href="https://github.com/antgraf/Embedded-DB-.Net-Performance-Test"&gt;Test application&lt;/a&gt; I wrote does following actions (and measure consumed time):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Prepare DB: Recreate DB &amp;amp; tables (3 tables, 2 non-PK indexes)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create DB: Insert ~500 records to the DB&lt;/li&gt;&lt;li&gt;Read All: sequentially read 400 records from the only table (no joins)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Read Random: read random 400 records from the only table (no joins)&lt;/li&gt;&lt;li&gt;Read / Write All: sequentially read &amp;amp; update 400 records from the only table (no joins)&lt;/li&gt;&lt;li&gt;Read / Write Random: read &amp;amp; update random 400 records from the only table (no joins)&lt;/li&gt;&lt;/ol&gt;Results you may &lt;a href="https://spreadsheets.google.com/spreadsheet/ccc?key=0Ajvnm_OA8KsCdEZQQktpV18zZzJrcGUzTV8zeFQ1UWc"&gt;see here&lt;/a&gt;. FireBird is ~30 times slower on read operations  than SQLite but 10-20 times faster on write operations. Overall time wins FireBird. It is 7 times faster.&lt;br /&gt;As for SQLite .Net adapters System.Data.DQLite is faster then sqlite-net for ~ 1.4 times.&lt;br /&gt;Final DB size: 912KB for FireBird, 40KB for SQLite.&lt;br /&gt;I like sqlite-net framework style but current version is slow and does not support blobs &amp;amp; nullable types. I hope it will improve.&lt;br /&gt;&lt;br /&gt;If you think I should test something else please comment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-970982126305612184?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/970982126305612184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=970982126305612184' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/970982126305612184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/970982126305612184'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2011/07/free-embedded-databases-for-c-net.html' title='Free embedded databases for C# (.Net) performance overview'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-7734469573331231028</id><published>2011-07-10T10:17:00.003+04:00</published><updated>2011-07-10T10:19:46.050+04:00</updated><title type='text'>Skype plugin for easy mute / unmute and PTT</title><content type='html'>&lt;a href="http://skype-push-to-talk.blogspot.com/2011/07/ezmute-ezptt-for-skype-10-released.html"&gt;EzMute &amp;amp; EzPTT for Skype 1.0&lt;/a&gt; is released. It creates visual button always on top of windows to mute Skype and allows to configure keyboard keys for mute and push to talk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-7734469573331231028?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/7734469573331231028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=7734469573331231028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/7734469573331231028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/7734469573331231028'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2011/07/skype-plugin-for-easy-mute-unmute-and.html' title='Skype plugin for easy mute / unmute and PTT'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-8910142099337203538</id><published>2009-08-27T17:09:00.005+04:00</published><updated>2009-08-28T15:23:28.692+04:00</updated><title type='text'>CakePHP: pagination &amp; sorting on deep associated models (for custom behaviors like Linkable or virtual / aggregated fields)</title><content type='html'>Using in &lt;span style="font-weight: bold;"&gt;CakePHP&lt;/span&gt; custom behavior (like &lt;span style="font-weight: bold;"&gt;LinkableBehavior&lt;/span&gt;) or &lt;span style="font-weight: bold;"&gt;aggregated fields&lt;/span&gt; (sql &lt;span style="font-weight: bold;"&gt;count, max, min&lt;/span&gt;, etc queries) or &lt;span style="font-weight: bold;"&gt;virtual fields&lt;/span&gt; in model breaks sorting with &lt;span style="font-weight: bold;"&gt;PaginationHelper&lt;/span&gt;. Trying to &lt;span style="font-weight: bold;"&gt;sort&lt;/span&gt; on field that does not explicitly defined in the model or directly associated models leads to loosing all sorting information. To fix this you need to correct &lt;span style="font-style: italic;"&gt;Controller-&gt;paginate()&lt;/span&gt; method. To do so create file &lt;em&gt;app/app_controller.php&lt;/em&gt; if it doesn't exist and define &lt;em&gt;AppController&lt;/em&gt; class there. Add &lt;span style="font-weight: bold; font-style: italic;"&gt;paginate()&lt;/span&gt; method to it and copy it's content from the same method from &lt;em&gt;cake/libs/controller/controller.php&lt;/em&gt; file. After that replace&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$value = $options['order'][$key];&lt;br /&gt;unset($options['order'][$key]);&lt;br /&gt;&lt;br /&gt;if (isset($object-&gt;{$alias}) &amp;amp;&amp;amp; $object-&gt;{$alias}-&gt;hasField($field)) {&lt;br /&gt;$options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;} elseif ($object-&gt;hasField($field)) {&lt;br /&gt;$options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;with&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$value = $options['order'][$key];&lt;br /&gt;&lt;br /&gt;if (isset($object-&gt;{$alias}) &amp;amp;&amp;amp; $object-&gt;{$alias}-&gt;hasField($field)) {&lt;br /&gt;unset($options['order'][$key]);&lt;br /&gt;$options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;} elseif ($object-&gt;hasField($field)) {&lt;br /&gt;unset($options['order'][$key]);&lt;br /&gt;$options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;full code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;class AppController extends Controller {&lt;br /&gt;&lt;br /&gt; function paginate($object = null, $scope = array(), $whitelist = array()) {&lt;br /&gt;  if (is_array($object)) {&lt;br /&gt;   $whitelist = $scope;&lt;br /&gt;   $scope = $object;&lt;br /&gt;   $object = null;&lt;br /&gt;  }&lt;br /&gt;  $assoc = null;&lt;br /&gt;&lt;br /&gt;  if (is_string($object)) {&lt;br /&gt;   $assoc = null;&lt;br /&gt;&lt;br /&gt;   if (strpos($object, '.') !== false) {&lt;br /&gt;    list($object, $assoc) = explode('.', $object);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if ($assoc &amp;amp;&amp;amp; isset($this-&gt;{$object}-&gt;{$assoc})) {&lt;br /&gt;    $object =&amp;amp; $this-&gt;{$object}-&gt;{$assoc};&lt;br /&gt;   } elseif ($assoc &amp;amp;&amp;amp; isset($this-&gt;{$this-&gt;modelClass}) &amp;amp;&amp;amp; isset($this-&gt;{$this-&gt;modelClass}-&gt;{$assoc})) {&lt;br /&gt;    $object =&amp;amp; $this-&gt;{$this-&gt;modelClass}-&gt;{$assoc};&lt;br /&gt;   } elseif (isset($this-&gt;{$object})) {&lt;br /&gt;    $object =&amp;amp; $this-&gt;{$object};&lt;br /&gt;   } elseif (isset($this-&gt;{$this-&gt;modelClass}) &amp;amp;&amp;amp; isset($this-&gt;{$this-&gt;modelClass}-&gt;{$object})) {&lt;br /&gt;    $object =&amp;amp; $this-&gt;{$this-&gt;modelClass}-&gt;{$object};&lt;br /&gt;   }&lt;br /&gt;  } elseif (empty($object) || $object === null) {&lt;br /&gt;   if (isset($this-&gt;{$this-&gt;modelClass})) {&lt;br /&gt;    $object =&amp;amp; $this-&gt;{$this-&gt;modelClass};&lt;br /&gt;   } else {&lt;br /&gt;    $className = null;&lt;br /&gt;    $name = $this-&gt;uses[0];&lt;br /&gt;    if (strpos($this-&gt;uses[0], '.') !== false) {&lt;br /&gt;     list($name, $className) = explode('.', $this-&gt;uses[0]);&lt;br /&gt;    }&lt;br /&gt;    if ($className) {&lt;br /&gt;     $object =&amp;amp; $this-&gt;{$className};&lt;br /&gt;    } else {&lt;br /&gt;     $object =&amp;amp; $this-&gt;{$name};&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!is_object($object)) {&lt;br /&gt;   trigger_error(sprintf(__('Controller::paginate() - can\'t find model %1$s in controller %2$sController', true), $object, $this-&gt;name), E_USER_WARNING);&lt;br /&gt;   return array();&lt;br /&gt;  }&lt;br /&gt;  $options = array_merge($this-&gt;params, $this-&gt;params['url'], $this-&gt;passedArgs);&lt;br /&gt;&lt;br /&gt;  if (isset($this-&gt;paginate[$object-&gt;alias])) {&lt;br /&gt;   $defaults = $this-&gt;paginate[$object-&gt;alias];&lt;br /&gt;  } else {&lt;br /&gt;   $defaults = $this-&gt;paginate;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (isset($options['show'])) {&lt;br /&gt;   $options['limit'] = $options['show'];&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (isset($options['sort'])) {&lt;br /&gt;   $direction = null;&lt;br /&gt;   if (isset($options['direction'])) {&lt;br /&gt;    $direction = strtolower($options['direction']);&lt;br /&gt;   }&lt;br /&gt;   if ($direction != 'asc' &amp;amp;&amp;amp; $direction != 'desc') {&lt;br /&gt;    $direction = 'asc';&lt;br /&gt;   }&lt;br /&gt;   $options['order'] = array($options['sort'] =&gt; $direction);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (!empty($options['order']) &amp;amp;&amp;amp; is_array($options['order'])) {&lt;br /&gt;   $alias = $object-&gt;alias ;&lt;br /&gt;   $key = $field = key($options['order']);&lt;br /&gt;&lt;br /&gt;   if (strpos($key, '.') !== false) {&lt;br /&gt;    list($alias, $field) = explode('.', $key);&lt;br /&gt;   }&lt;br /&gt;   $value = $options['order'][$key];&lt;br /&gt;&lt;br /&gt;   if (isset($object-&gt;{$alias}) &amp;amp;&amp;amp; $object-&gt;{$alias}-&gt;hasField($field)) {&lt;br /&gt;    unset($options['order'][$key]);&lt;br /&gt;    $options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;   } elseif ($object-&gt;hasField($field)) {&lt;br /&gt;    unset($options['order'][$key]);&lt;br /&gt;    $options['order'][$alias . '.' . $field] = $value;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  $vars = array('fields', 'order', 'limit', 'page', 'recursive');&lt;br /&gt;  $keys = array_keys($options);&lt;br /&gt;  $count = count($keys);&lt;br /&gt;&lt;br /&gt;  for ($i = 0; $i &lt; $count; $i++) {&lt;br /&gt;   if (!in_array($keys[$i], $vars, true)) {&lt;br /&gt;    unset($options[$keys[$i]]);&lt;br /&gt;   }&lt;br /&gt;   if (empty($whitelist) &amp;amp;&amp;amp; ($keys[$i] === 'fields' || $keys[$i] === 'recursive')) {&lt;br /&gt;    unset($options[$keys[$i]]);&lt;br /&gt;   } elseif (!empty($whitelist) &amp;amp;&amp;amp; !in_array($keys[$i], $whitelist)) {&lt;br /&gt;    unset($options[$keys[$i]]);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  $conditions = $fields = $order = $limit = $page = $recursive = null;&lt;br /&gt;&lt;br /&gt;  if (!isset($defaults['conditions'])) {&lt;br /&gt;   $defaults['conditions'] = array();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  $type = 'all';&lt;br /&gt;&lt;br /&gt;  if (isset($defaults[0])) {&lt;br /&gt;   $type = $defaults[0];&lt;br /&gt;   unset($defaults[0]);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  extract($options = array_merge(array('page' =&gt; 1, 'limit' =&gt; 20), $defaults, $options));&lt;br /&gt;&lt;br /&gt;  if (is_array($scope) &amp;amp;&amp;amp; !empty($scope)) {&lt;br /&gt;   $conditions = array_merge($conditions, $scope);&lt;br /&gt;  } elseif (is_string($scope)) {&lt;br /&gt;   $conditions = array($conditions, $scope);&lt;br /&gt;  }&lt;br /&gt;  if ($recursive === null) {&lt;br /&gt;   $recursive = $object-&gt;recursive;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  $extra = array_diff_key($defaults, compact(&lt;br /&gt;   'conditions', 'fields', 'order', 'limit', 'page', 'recursive'&lt;br /&gt;  ));&lt;br /&gt;  if ($type !== 'all') {&lt;br /&gt;   $extra['type'] = $type;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (method_exists($object, 'paginateCount')) {&lt;br /&gt;   $count = $object-&gt;paginateCount($conditions, $recursive, $extra);&lt;br /&gt;  } else {&lt;br /&gt;   $parameters = compact('conditions');&lt;br /&gt;   if ($recursive != $object-&gt;recursive) {&lt;br /&gt;    $parameters['recursive'] = $recursive;&lt;br /&gt;   }&lt;br /&gt;   $count = $object-&gt;find('count', array_merge($parameters, $extra));&lt;br /&gt;  }&lt;br /&gt;  $pageCount = intval(ceil($count / $limit));&lt;br /&gt;&lt;br /&gt;  if ($page === 'last' || $page &gt;= $pageCount) {&lt;br /&gt;   $options['page'] = $page = $pageCount;&lt;br /&gt;  } elseif (intval($page) &lt; 1) {&lt;br /&gt;   $options['page'] = $page = 1;&lt;br /&gt;  }&lt;br /&gt;  $page = $options['page'] = (integer)$page;&lt;br /&gt;&lt;br /&gt;  if (method_exists($object, 'paginate')) {&lt;br /&gt;   $results = $object-&gt;paginate($conditions, $fields, $order, $limit, $page, $recursive, $extra);&lt;br /&gt;  } else {&lt;br /&gt;   $parameters = compact('conditions', 'fields', 'order', 'limit', 'page');&lt;br /&gt;   if ($recursive != $object-&gt;recursive) {&lt;br /&gt;    $parameters['recursive'] = $recursive;&lt;br /&gt;   }&lt;br /&gt;   $results = $object-&gt;find($type, array_merge($parameters, $extra));&lt;br /&gt;  }&lt;br /&gt;  $paging = array(&lt;br /&gt;   'page'  =&gt; $page,&lt;br /&gt;   'current' =&gt; count($results),&lt;br /&gt;   'count'  =&gt; $count,&lt;br /&gt;   'prevPage' =&gt; ($page &gt; 1),&lt;br /&gt;   'nextPage' =&gt; ($count &gt; ($page * $limit)),&lt;br /&gt;   'pageCount' =&gt; $pageCount,&lt;br /&gt;   'defaults' =&gt; array_merge(array('limit' =&gt; 20, 'step' =&gt; 1), $defaults),&lt;br /&gt;   'options' =&gt; $options&lt;br /&gt;  );&lt;br /&gt;  $this-&gt;params['paging'][$object-&gt;alias] = $paging;&lt;br /&gt;&lt;br /&gt;  if (!in_array('Paginator', $this-&gt;helpers) &amp;amp;&amp;amp; !array_key_exists('Paginator', $this-&gt;helpers)) {&lt;br /&gt;   $this-&gt;helpers[] = 'Paginator';&lt;br /&gt;  }&lt;br /&gt;  return $results;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-8910142099337203538?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/8910142099337203538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=8910142099337203538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/8910142099337203538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/8910142099337203538'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2009/08/cakephp-pagination-sorting-on-deep.html' title='CakePHP: pagination &amp; sorting on deep associated models (for custom behaviors like Linkable or virtual / aggregated fields)'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-3098835266474829232</id><published>2008-11-28T18:02:00.003+03:00</published><updated>2008-11-28T18:43:42.195+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='issue trackers'/><category scheme='http://www.blogger.com/atom/ns#' term='freelance'/><title type='text'>Free issue and bug tracking online services review</title><content type='html'>To fulfill previous post I want to provide my research on &lt;span style="font-weight: bold;"&gt;free online issue and bug tracking systems&lt;/span&gt; available on the Internet. Surprisingly there are very few of them matching my criteria: 5 users minimum, 10000 tickets minimum, closed for public. Here they are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The only totally &lt;span style="font-weight: bold;"&gt;free&lt;/span&gt; &amp;amp; &lt;span style="font-weight: bold;"&gt;unlimited&lt;/span&gt; is &lt;a href="http://www.defectr.com/"&gt;defectr.com&lt;/a&gt;. It has limited functionality and funny UI but has no users nor projects limitations. My choice #1 for not complex projects.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.w3spt.com/?Content=WWWSupport&amp;amp;GR=1"&gt;w3spt.com&lt;/a&gt; offers 10000 messages/5 users/100Mb-limited complex integrated &lt;span style="font-weight: bold;"&gt;project tracking system&lt;/span&gt;. It has a lot of custom views and reports such as &lt;span style="font-weight: bold;"&gt;FAQ, Forum, Feedback zone, Knowledge base&lt;/span&gt;. I would recommend it for complex but not huge projects.&lt;/li&gt;&lt;li&gt;And the last one I want to mention is &lt;a href="https://www.teamatic.com/index.jsp"&gt;teamatic.com&lt;/a&gt;. It provides simple tracker for 5 persons with 5Mb attachments storage and &lt;span style="font-weight: bold;"&gt;nice interface&lt;/span&gt;. It may be used for small simple projects.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-3098835266474829232?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/3098835266474829232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=3098835266474829232' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/3098835266474829232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/3098835266474829232'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2008/11/free-issue-and-bug-tracking-online.html' title='Free issue and bug tracking online services review'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-8977570436760808807</id><published>2008-11-24T16:40:00.006+03:00</published><updated>2008-11-24T17:22:10.354+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='freelance'/><title type='text'>Choose free online software project tools</title><content type='html'>I spent a lot of time to choose high-quality &lt;span style="font-weight: bold;"&gt;online software project tools&lt;/span&gt; for &lt;span style="font-weight: bold;"&gt;free&lt;/span&gt;. Some of them are not so "free" other ones have a lot of ads or have low quality. Trying different solutions I chose following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Instant public chat&lt;/span&gt;: there is an options. You may create IRC channel on &lt;a href="http://www.efnet.org/"&gt;efnet.org&lt;/a&gt; or maintain public chat with &lt;a href="http://www.skype.com/allfeatures/publicchats/"&gt;Skype&lt;/a&gt; (BTW Skype supports up to 150 chat members now).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Collaborative documents authoring&lt;/span&gt;: &lt;a href="http://docs.google.com/"&gt;Google Docs&lt;/a&gt; have no competitors in this area.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;FAQ service&lt;/span&gt;: personally I prefer &lt;a href="http://www.bravenet.com/"&gt;bravenet&lt;/a&gt;'s one.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Mail list / discussion group&lt;/span&gt;: again &lt;a href="http://groups.google.com/"&gt;Google Groups&lt;/a&gt; is the best one.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Project management&lt;/span&gt;: unfortunately I was unable to find any wholly satisfactory project management online service. If you know one please let me know.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-8977570436760808807?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/8977570436760808807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=8977570436760808807' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/8977570436760808807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/8977570436760808807'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2008/11/choose-free-online-software-project.html' title='Choose free online software project tools'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-3448209644080418782</id><published>2008-11-16T17:09:00.002+03:00</published><updated>2008-11-24T17:21:56.045+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Trac'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='TracAdmin'/><category scheme='http://www.blogger.com/atom/ns#' term='freelance'/><title type='text'>Configuring TracAdmin for opensvn.csie.org</title><content type='html'>In previous post I called &lt;a style="font-weight: bold;" href="https://opensvn.csie.org/"&gt;opensvn.csie.org&lt;/a&gt; one of the best &lt;span style="font-weight: bold;"&gt;free SVN repositories for closed source&lt;/span&gt;. Now I want to show how to configure integrated &lt;span style="font-weight: bold;"&gt;Trac&lt;/span&gt; initially.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;First of all go to "Manage Your Project" tab and login.&lt;/li&gt;&lt;li&gt;Go to "trac" tab and click "interface to trac-admin" link.&lt;/li&gt;&lt;li&gt;Enter "&lt;span style="font-weight: bold;"&gt;permission add username TRAC_ADMIN&lt;/span&gt;", where "username" is your login, to text field and press "Execute" button.&lt;/li&gt;&lt;li&gt;After that you may visit your Trac (https://opensvn.csie.org/traccgi/username) and configure it using "&lt;a href="http://trac.edgewall.org/wiki/WebAdmin"&gt;Admin&lt;/a&gt;" web interface.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-3448209644080418782?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/3448209644080418782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=3448209644080418782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/3448209644080418782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/3448209644080418782'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2008/11/configuring-tracadmin-for.html' title='Configuring TracAdmin for opensvn.csie.org'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8924822430815499389.post-6390052264274542589</id><published>2008-11-12T19:37:00.002+03:00</published><updated>2008-11-24T17:22:48.769+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='service'/><category scheme='http://www.blogger.com/atom/ns#' term='tool'/><category scheme='http://www.blogger.com/atom/ns#' term='free'/><category scheme='http://www.blogger.com/atom/ns#' term='version control'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='repository'/><category scheme='http://www.blogger.com/atom/ns#' term='vcs'/><category scheme='http://www.blogger.com/atom/ns#' term='project'/><category scheme='http://www.blogger.com/atom/ns#' term='freelance'/><title type='text'>Free private unlimited SVN reposirories + Trac</title><content type='html'>For small non-profit or freelance projects I used free &lt;a href="http://www.assembla.com/"&gt;assembla&lt;/a&gt; SVN repository and admin page before. After it became paid for &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;closed-source&lt;/span&gt; projects I spent a lot of time to find the replacement. Here are my best findings:&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://opensvn.csie.org/"&gt;opensvn.csie.org&lt;/a&gt; - the best one. One repo, unlimited space, unlimited users, Trac &amp;amp; Trac admin.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://svn.xp-dev.com/app/"&gt;svn.xp-dev.com/app&lt;/a&gt; - another "the best" one. Unlimited repos (5 initially), unlimited space (300 Mb per repo initially), custom tracker (not very comfortable), unlimited users.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://unfuddle.com/"&gt;unfuddle.com&lt;/a&gt; - has both free &amp;amp; paid plans. Free one is 200Mb for 2 persons Git or Subversion repositories, tracker. Unfriendly interface.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codespaces.com/"&gt;codespaces.com&lt;/a&gt; - only 50 Mb for private repo for 2 users, wiki + tracker.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Hope this will be helpful.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8924822430815499389-6390052264274542589?l=antgraf-freelance.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antgraf-freelance.blogspot.com/feeds/6390052264274542589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8924822430815499389&amp;postID=6390052264274542589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/6390052264274542589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8924822430815499389/posts/default/6390052264274542589'/><link rel='alternate' type='text/html' href='http://antgraf-freelance.blogspot.com/2008/11/free-private-unlimited-svn-reposirories.html' title='Free private unlimited SVN reposirories + Trac'/><author><name>antgraf</name><uri>http://www.blogger.com/profile/11807003535381096170</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://3.bp.blogspot.com/_cQ_tvCCZ8N0/SpaFMt1YxRI/AAAAAAAAACo/Jh4YJNJAsQg/S220/antgraf_fullsize.JPG'/></author><thr:total>0</thr:total></entry></feed>
