Friday, January 31, 2014

CakePHP 2.4: Saving paging data in the session


Quite some time ago I wrote a blog post about saving CakePHP 1.x paging data in the session so that they can be available at next page visit. The basic idea was that you could store the page, sort and direction named parameters in the session and restore them back when no paging parameters were available.



When I tried applying the same technique in CakePHP 2.4, I run into a very serious obstacle and that was the fact that the Paginator::numbers() function does not anymore include the page:1 named parameter when creating the link for the first (or previous) page. This created a phenomenon that when someone visited a page without any paging parameters, it was impossible to know whether they were there because of a link to the first page or as a result of a redirect from somewhere else, in which case the session had to be checked and paging data to be restored.




The thing had been puzzling me for some days now. I tried different remedies without any luck or results until I cried for help at stackoverflow.com. It was there that Ilie Pandia shook things a bit and then I managed, thanks to his advice, to create the following component that mimics the original Cake 1.x PaginationRecallComponent by mattc found in the Bakery, from which I borrowed the name and structure.



<?php
App::uses('Component', 'Controller');

/**
* Pagination Recall CakePHP Component
* CakePHP 2.x version Copyright (c) 2014 Thanassis Bakalidis abakalidis.blogspot.com=
*
* @author thanassis
* @version 2.0
* @license MIT
*/
class PaginationRecallComponent extends Component {
const PREV_DATA_KEY = 'Pafinaion-PrevData';

public $components = array('Session');
private $_controller = NULL;
private $_previousUrl;

public function startup(Controller $controller)
{
$this->_controller = $controller;
$sessionKey = "Pagination.{$this->_controller->modelClass}.options";

// extract paging data from the request parameters
$pagingParams = $this->_extractPagingParams();

// if paging data exist write them in the session
if (!empty($pagingParams)) {
$this->Session->write( $sessionKey, $pagingParams);
return;
}


// no paging data.
// construct the previous URL
$this->_previousUrl = $this->Session->check(self::PREV_DATA_KEY)
? $this->Session->read(self::PREV_DATA_KEY)
: array(
'controller' => '',
'action' => ''
);

// and check if the current page is the same as the previous
if ($this->_previousUrl['controller'] === $this->_controller->name &&
$this->_previousUrl['action'] === $this->_controller->params['action']) {
// in this case we have a link from our own paging::numbers() function
// to move to page 1 pf the current page
return;
}

// we are comming from a different page so if we have any session data
if ($this->Session->check($sessionKey))
// then restore and use them
$this->_controller->request->params['named'] = array_merge(
$this->_controller->request->params['named'],
$this->Session->read($sessionKey)
);
}

public function shutdown(\Controller $controller)
{
// save the current controller and action for the next time
$this->Session->write(
self::PREV_DATA_KEY,
array(
'controller' => $this->_controller->name,
'action' => $this->_controller->request->params['action']
)
);
}

private function _extractPagingParams()
{
$pagingParams = $this->_controller->request->params['named'];
$vars = array('page', 'sort', 'direction');
$keys = array_keys($pagingParams);
$count = count($keys);

for ($i = 0; $i < $count; $i++)
if (!in_array($keys[$i], $vars))
unset($pagingParams[$keys[$i]]);

return $pagingParams;
}
}

Sunday, January 12, 2014

Enable MP3 on Fedora 20


A very short how to enable mp3 playback on your brand new fedora installation.




  1. Enable PRM Fusion repository.


  2. Install the vlc phonon-backend. (Fedora comes with GStreamer).
    .
    yum install phonon-backend-vlc


  3. Goto system settings → Multimedia → Audio and Video Settings. Select the backend tab.
    There should be two entries there: GStreamer and VLC. Select the VLC entry and click the Prefer buttom below the list.
    Finally click Apply. The final result should be something like this:



  4. Log out and back in for the changes to take effect.




After that you can play and kind of context directly from Dolphin, you can install additional music players like amarok, or vlc and enjoy the full music, audio and video experence.




yum install vlc
yum install amarok amarok-doc

Thursday, November 7, 2013

CakePHP New application database config (never forget the enconding)


Today I will put down the way to begin a new web application project using CakePHP.



The first part is database creation. Database charset must be utf-8 and collation: utf8_unicode_ci. The difference between general and unicode collations is explained in an excellent manner in this post on stackoverlow.com



Next, when you start a new CakePHP project the database config class looks like this




public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'test_database_name',
'prefix' => '',
// 'encoding' => 'utf8',
);


My lesson today is: Before changing anything else, uncomment the last line!.



... in case you do not then Unicode (Greek in my case) text will still appear correctly in the web application, but phpMyAdmin and sqldump will display garbage. In addition searches with non-latin text will always fail. To make matters worse when I discovered the case of the problem, I realised that I would have to re-enter all my test data.

Friday, November 1, 2013

SchemaSync: An effective and simple way to synchronize MySQL databases


I have spend the last couple of days trying to find out a solution for migrating changes from a development database to the productive. I was looking for a clean, simple and reliable solution that (ideally) runs on Linux.



My first attempt was to to use the official MySQL mysqldiff command. It turned out that in my case, the only suggestion I got was to recreate indexes and drop primary keys every time there was a record number mismatch between tables. I also run into Windows GUI's with a 30 day evaluation period and a cost ranging from $90-$150.



My lack changes when I run into Schema Sync written in Python by Mitch Matuson. The page has everything you need and the setup (if you already have python) takes less that a minute.



Quoting from the utility's examples page,
Sync the production db with the changes from the development db



schemasync mysql://user:pass@dev-host:3306/dev_db mysql://user:pass@prod-host:3306/production_db


This will give you two files in your home directory, one to do the patching and one to revert back the changes if requested. A excellent piece of work, that I am very happy to use. Thumbs up for mr Matuson.



Saturday, October 19, 2013

Netbeans 7.x and Debian


Switched my laptop from Fedora 19 to Debian 7.1 for some peace, quiet and stability. It appears that the latest transitions to kernel 3.11 and the issues with the nvidia drivers were too much for it. So here I am, enjoying the Debian way of life without yum and gstreamer.



A goodie available only to Debian and Ubuntu users is the Oracle Java PPA available through this link. Andrew at webupd8,org has set up a PPA that downloads and installs the latest Oracle Java packages keeping your computer up to date along with the rest of normal updates.



So now it's Netbeans turn to get installed. I prefer to download the Java SE version and then manually add the PHP and CakePHP plugins that I require for my everyday use.



The first time I tried to install the normal way I ended up with an Exception: java.lang.NoClassDefFoundError thrown from the UncaughtExceptionHandler in thread "main". A little bit of digging revealed that that one way to install netbeans is to use the --silent installer option. The will install netbeans to the default /usr/local/netbeans-7.x location which is perfectly all right. After that you can run it from your desktop Development menu. So to start the installer just become root and type:



root@nb-thanassis:/home/thanassis/Downloads/Netbeans# ./netbeans-7.4-javase-linux.sh --silent


in a similar manner, in order to uninstall netbeans from your system, go to the installation directory and type



root@nb-thanassis:/usr/local/netbeans-7.4# ./uninstall.sh --slinent


There is one small thing that I noticed. in order for all this to work you must cd to the same directory as the installer script before issueing any commands. In my case -- hence the blog post -- all other attempts failed.

.

Monday, October 7, 2013

CakePHP locking tables


Here are my two cents on the issue.



The code below is a function from a behaviour that tries to create an additional unique key on
a field named code, by counting the number of records created this year. The important part
in the locking procedure is that we must specify the AS clause in the LOCK TABLES
statement or otherwise the $model->find() function will not work complaining that the table is locked.



public function getNextCode(&$model)
{
$thisYear = date('Y');
$dbo = $model->getDataSource();
$dbo->execute(
sprintf('LOCK TABLES %s AS %s WRITE;',
$model->table,
$model->alias
)
);
$recordsThisYear = $model->find(
'count',
array(
'recursive' => -1,
'conditions' => array(
$model->alias .'.code LIKE' => $thisYear.'%'
)
)
);
$dbo->execute('UNLOCK TABLES');
return sprintf('%d-%06d', $thisYear, $recordsThisYear + 1);
}


The original idea for the post and function cake from a doWeb posting available through here.

Friday, June 14, 2013

Using a raspberrypi as an sftp server


Following a previous post regarding how to use your raspberry-pi device as a file server, we are going to continue amd set up sftp service on the same pi device, so that it may be accessible over WAN.



The complete guide comes from a Mark Van den Borre posting available through this link.In our case however the steps are fewer, since raspberry has already the openssh server set up and running and if you have followed from the previous port we already have a user (bill) and a group (microsoft) to use for sftp service.



To get started let;s give our friend Bill a password:



pi@xena ~ $ sudo passwd bill
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully


Next step will be to prevent Bill from interactively logging in. The usual remedy to this problem to use the sftp server as a login shell. After the post is over bill will not be able to access our pi from ssh either



pi@xena ~ $ sudo chsh bill
Changing the login shell for bill
Enter the new value, or press ENTER for the default
Login Shell [/usr/lib/tftp-server]: /usr/lib/sftp-server
pi@xena ~ $


Now for the sftp configuration itself. (Copying, pasting and adjusting from Mark's post we have something like this:) Open the default OpenSSH server configuration for editing:



pi@xena ~ $ sudo vi /etc/ssh/sshd_config

:
and change the default sftp server from:


Subsystem sftp /usr/lib/openssh/sftp-server


to



Subsystem sftp internal-sftp


Some users can only use sftp, but not other OpenSSH features like remote login. Let's create a rule for that group of users. Add the following section to the bottom of /etc/ssh/sshd_config:



Match group microsoft
ChrootDirectory /mnt/SFTP-Data
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp


Reboot...