Toggle display of an element with plain Javascript

24 Jan 2017 in Javascript

This little snippet shows how to toggle the display of a div element by toggling the state of a checkbox:

<input type="checkbox" id="my_checkbox"/>
<div id="my_div">
    <!-- with some content inside, you know, lorem ipsum and stuff -->
</div>
<script>
    (function () {
        var checkbox = document.getElementById("my_checkbox");
        var container = document.getElementById("my_div");
        var fn = function () {
            if (checkbox.checked) {
                 // or instead of "display" you may use
                 // "visibility" with hidden/visible values
                container.style.display = "block";
            } else {
                container.style.display = "none";
            }
        };
        // set onclick handler of checkbox to the fn
        checkbox.onclick = fn;
        // call fn with checkbox scope
        fn.apply(checkbox); // or fn.call(checkbox);
    }());
</script>

Simple vanilla js.

Performance tips for Vagrant

24 Jan 2017 in Vagrant

  • Set memory to 1/4 of the host.
  • Try setting more than 1 CPU core but measure what best works for you.
  • Also enable IOAPIC if using more than one CPU core.
  • Enable KVM virtualization if on a GNU/Linux host.

An example with these settings applied:

config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
    vb.cpus = 2
    vb.customize ["modifyvm", :id, "--ioapic", "on", "--paravirtprovider", "kvm"]
end

Using date in cron

23 Jan 2017 in Cron

A simple way to have a command log output to a file grouping by date is to do something like:

# writes to a file my-command-YYYYMMDD.log
my-command >> my-command-$(date +%Y%m%d).log

But in a cronjob you should escape the % character by prepending it with a backslash like this:

* 0 * * * my-command >> my-command-$(date +\%Y\%m\%d).log

To capture both stdout and stderr:

* 0 * * * my-command >> my-command-$(date +\%Y\%m\%d).log 2>&1

Output amount via Currency library in OpenCart

20 Jan 2017 in OpenCart

For those in a hurry, here is an example on how to output an amount via OpenCart's Currency library from inside a view file:

<?= $this->registry->get("currency")->format($amount) ?>

Eg a value of 200.50 is outputted as 250,50€ (assuming a Greek locale).

If you also need to do some math based on an existing number (formatted as a string with currency code), you may do something like this:

<?php
// in order to convert "200,50€" to 200.50
$convertToFloat = function($s) {
    // yeah I know... at least this gets the job done
    return (float)str_replace(",", ".", $s);
};
?>
<?= $this->registry->get("currency")->format($convertToFloat($price) * 1.24) ?>

Creating a Vagrant environment from scratch

18 Jan 2017 in Vagrant

In order to start, create a vagrant environment based on Ubuntu Trusty (of course you can start with something of your choice):

# create the machine
vagrant init ubuntu/trusty

# boot it
vagrant up

# get into
vagrant ssh

# configure it
sudo apt-get update

# install vim
sudo apt-get install vim

# more commands like eg
# - install apache
# - install mysql
# - configure something
# - etc

# create a swap file
sudo dd if=/dev/zero of=/swap bs=1M count=512
sudo chmod 600 /swap
sudo mkswap /swap
echo "/swap  none  swap  sw  0  0" | sudo tee -a /etc/fstab

# clear the box
sudo apt-get clean
# minimize packaged box size
sudo dd if=/dev/zero of=/EMPTY bs=1M
sudo rm -f /EMPTY
# clear history
cat /dev/null > ~/.bash_history && history -c && exit

When you are ready, logout and package the box

vagrant package --output my-box.box

and destroy the machine

vagrant destroy
rm Vagrantfile

Then you can either import the box like this

vagrant box add my/box my-box.box
vagrant init my/box

Or you can take advantage of box versioning:

At first calculate the sha1 (or sha256, sha512, your call) of the box

sha1sum my-box.box

And then create the file my-box.json with contents like

{
    "name": "my/box",
    "description": "This box contains My Box",
    "versions": [
        {
            "version": "1.0.0",
            "providers": [{
                    "name": "virtualbox",
                    "url": "file:///path/to/my/box.box",
                    "checksum_type": "sha1",
                    "checksum": "-->CHECKSUM-HERE<--"
            }]
        }
    ]   
}

after that, you can import the box with something like

vagrant box add path/to/my-box.json
vagrant init my/box

or by supplying it in the Vagrantfile:

config.vm.box = "my/box"
config.vm.box_url = "file://path/to/my-box.json"

By adjusting the above paths accordingly you can store the boxes along with the json file (the box metadata) on a personal server.

Of course, the preffered way to create a vagrant environement is to use something like chef, puppet, ansible, etc, but this is simpler in the essence that you don't have to deal with any provisioning tools.

Motherfucking Website

17 Jan 2017 in Web

I admit I love this: motherfuckingwebsite.com

It's dead simple: stop designing websites with 123456kB full of crap images and some javascript that halts your browser to the death.

I also have to admit I like this better: bestmotherfucking.website

Just look at the (reformatted) css:

body {
    margin: 1em auto;
    max-width: 40em;
    padding: 0 .62em;
    font: 1.2em/1.62em sans-serif;
}
h1, h2, h3 {
    line-height: 1.2em;
}
@media print {
    body {
        max-width: none;
    }
}

How awesome is that?

Side Note: Do you know you can use your own fonts and colors in your browser? Random examples at howtogeek.com and support.mozilla.org

Let's Encrypt with ISPConfig3

30 Sep 2016 in Let's Encrypt, ISPConfig

Note: This applies on Ubuntu Server 14.04 with Apache web server.

First setup Let's Encrypt client, Certbot:

# download client
wget https://dl.eff.org/certbot-auto

# make it executable
chmod a+x certbot-auto

# make it globally available
mv -iv certbot-auto /usr/bin

# first time setup
certbot-auto

Then, to request certificates for the domain EXAMPLE.DOMAIN, run:

certbot-auto certonly \
    --webroot \
    --webroot-path /var/www/EXAMPLE.DOMAIN/web/ \
    --domains EXAMPLE.DOMAIN \
    --email EXAMPLE@EMAIL

Certificate and chain are saved in directory /etc/letsencrypt/live/EXAMPLE.DOMAIN/.

After that, configure SSL in ISPConfig by enabling the SSL checkbox on EXAMPLE.DOMAIN and setting the keys on the SSL tab:

  • Copy the contents of /etc/letsencrypt/live/EXAMPLE.DOMAIN/privkey.pem into the SSL Key.
  • /etc/letsencrypt/live/EXAMPLE.DOMAIN/cert.pem to SSL Certificate.
  • /etc/letsencrypt/live/EXAMPLE.DOMAIN/chain.pem to SSL Bundle.

Also, don't forget to select "Save Certificate" on SSL Action.

Because Let’s Encrypt certificates are valid for a short period of time, they should be automatically renewed. To do this you have to setup a cronjob to run once or twice per day:

# the --post-hook is optional, and is used in this case to restart the apache webserver
echo '42 3 * * *  root  certbot-auto renew --post-hook "service apache2 restart"' > /etc/cron.d/certbot

Finally, to not break things with ISPConfig, link the certificates with Let's Encrypt:

ln -sf /etc/letsencrypt/live/EXAMPLE.DOMAIN/cert.pem    EXAMPLE.DOMAIN.crt
ln -sf /etc/letsencrypt/live/EXAMPLE.DOMAIN/privkey.pem EXAMPLE.DOMAIN.key
ln -sf /etc/letsencrypt/live/EXAMPLE.DOMAIN/chain.pem   EXAMPLE.DOMAIN.bundle

Note: To redirect HTTP to HTTPS, you may use the following .htaccess snippet:

RewriteEngine on
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301]

Counting products in a subtree in Prestashop

26 Sep 2016 in Prestashop

The problem

Customer wants to display the total number of products that belongs to a category and all subcategories - ie the subtree of category.

The solution

Prestashop uses Nested Sets to implement hierarchy in categories.

The nested set model is to number the nodes according to a tree traversal, which visits each node twice, assigning numbers in the order of visiting, and at both visits. This leaves two numbers for each node, which are stored as two attributes. (link)

Let's call those numbers nleft and nright. Assume category T' with nleft' and nright'. Any subcategory T'' which has nleft'' and nright'' between nleft' and nright' is contained in the subtree formed by T'.

So the code snippet is:

$count = (int)Db::getInstance()->getValue('
    SELECT SUM(count) FROM (
        SELECT COUNT(*) AS count FROM ' . _DB_PREFIX_ . 'category_product AS cp
        INNER JOIN ' . _DB_PREFIX_ . 'product_shop AS ps ON cp.id_product = ps.id_product
        INNER JOIN ' . _DB_PREFIX_ . 'category c ON cp.id_category = c.id_category
        WHERE c.nleft >= ' . (int)$nleft . ' AND c.nright <= ' . (int)$nright . '
        AND ps.active = 1
        AND ps.id_shop = ' . $id_shop . '
    ) AS c
')

Law of Demeter

22 Sep 2016 in Programming, PHP, Software Architecture

The Law of Demeter or principle of least knowledge is a style guideline for developing software.

According to Virtuous Code:

For all classes C. and for all methods M attached to C, all objects to which M sends a message must be instances of classes associated with the following classes:

The argument classes of M (including C). The instance variable classes of C.

(Objects created by M, or by functions or methods which M calls, and objects in global variables are considered as arguments of M.)

or in plain english:

  • Your method can call other methods in its class directly
  • Your method can call methods on its own fields directly (but not on the fields' fields)
  • When your method takes parameters, your method can call methods on those parameters directly.
  • When your method creates local objects, that method can call methods on the local objects.

This translates to not having a chain of method calls like $someObject->foo()->bar()->baz() somewhere in your code.

For a simple example, consider the following:

/**
 * Represent a {lat,lng} pair
 */
class LatLng {
    private $lat;
    private $lng;
    public function __construct($lat, $lng) {
        $this->lat = $lat;
        $this->lng = $lng;
    }
    public function lat() {
        return $this->lat;
    }
    public function lng() {
        return $this->lng;
    }
}

/**
 * Represent a Line/Pair of LatLng's
 */
class Line {
    private $start;
    private $end;
    public function __construct(LatLng $start, LatLng $end) {
        $this->start = $start;
        $this->end = $end;
    }
    public function start() {
        return $this->start;
    }
    public function end() {
        return $this->end;
    }
    public function distance() {
        // calculate and return the distance between start and end
    }
}

$start = new LatLng(...);
$end = new LatLng(...);
$line = new Line($start, $end);
// ...more code...
$startLat = $line->start()->lat();

Law of Demeter states that you should avoid the above chain of calls. This can be accomblished by rewriting the Line class like this:

/**
 * Represent a Line/Pair of LatLng's
 */
class Line {
    private $start;
    private $end;
    public function __construct(LatLng $start, LatLng $end) {
        $this->start = $start;
        $this->end = $end;
    }
    public function startLat() {
        return $this->start->lat();
    }
    public function startLng() {
        return $this->start->lng();
    }
    public function endLat() {
        return $this->end->lat();
    }
    public function endLng() {
        return $this->end->lng();
    }
    public function distance() {
        // calculate and return the distance between start and end
    }
}

// and now we can write
$start = new LatLng(...);
$end = new LatLng(...);
$line = new Line($start, $end);
// ...more code...
$startLat = $line->startLat();

But...

But, this example is not entirelly correct as outlined in this answer from stack overflow (How to obey Law of Demeter?):

You are not applying LoD at the appropriate level: both Band and Guitarist should be considered a part of the same module and the dilemma you have shall be decided on the grounds of maximum convenience.

Your question is an example of a much wider problem, which I have frequently met in books on design patterns and similar: they try to explain wide-reaching principles, which concern the design of a complex system, on ridiculously undersized problems. The result is just reader's confusion.

Where you'd actually see this principle in effect is something like this: you are using AsyncHttpClient, which is an abstraction built atop Netty, which is an abstraction built atop Java NIO. Now, if AsyncHttpClient's API forced you at some place to directly manage a Java NIO object, whose API is much more raw, and deals with concepts completely foreign to AsyncHttpClient, that would be an example of breaking LoD.

More links:

Mocking global PHP functions in phpunit

20 Jul 2016 in Programming, PHP, phpunit

In order to mock global php functions like date(), rand(), etc, I developed a simple solution utilizing phpunit's getMock() method.

For example, assuming you are trying to mock the date() function, replace the occurences of the function in your class with a call to a new protected method that calls this function and returns the result.

So, the following snippet:

class ExampleClass {
    public function foo() {
        $date = date('Y-m-d H:i:s');
        // do something
        // ...
        return $date;
    }
}

becomes:

class ExampleClass {
    public function foo() {
        $date = $this->date();
        // do something
        // ...
        return $date;
    }
    protected function date() {
        return date('Y-m-d H:i:s');
    }
}

Then, in your tests, instead of creating the actual class, create it via phpunit's getMock() method like this:

// The first parameter is the class name and the second the methods to mock
// Consult phpunit's manual for extra parameters like constructor arguments
$exampleClassInstance = $this->getMock(ExampleClass::class, ["date"]);

Finally, write your tests and set the return value of ExampleClass::date() on each test:

class ExampleClassTest extends PHPUnit_Framework_TestCase {
    protected $sut;
    protected function setUp() {
        $this->sut = $this->getMock(ExampleClass::class, ["date"]);
    }
    public function testFoo() {
        $expected = "2010-01-01 00:00:00";
        $this->sut->expects($this->any())
            ->willReturn($expected)
            ->method("date");
        $actual = $this->sut->foo();
        $this->assertEquals($expected, $actual);
    }
}

This will test the actual class, except mock methods, with code coverage.

Alternative solutions: