Update to the parse_ini_advanced…

19 07 2015

Here’s an update to the previous post on the subject, adding the functionality to write such ini files from an existing array.

<?php
// (C) 2015 Chris Sprucefield
// Licensed under Createive Commons - "CC BY-SA 4.0"
// License deed: http://creativecommons.org/licenses/by-sa/4.0/
// Legal code:   http://creativecommons.org/licenses/by-sa/4.0/legalcode
//
// Advanced PHP .INI file reader / creator. 
// 
// Sections such as [ abc:def ] will be put into $var['abc']['def'] = values
// Names such as a.b.c and a:b:c will be expanded into sublevels. 
// See reference at the end of the file. 

class Inifile
{
    private $ini = "" ; 

    // Write an array to an ini file. 
    public static function write($filename,$arr)
    {
        self::array_to_ini($arr) ;
        file_put_contents($filename,self::$ini) ;
    }
    
    // Convert an array to an advanced ini file. 
    public static function array_to_ini($a,$level = 0,$str="")
    {
        if ($level == 0) self:$ini = "" ; 

        foreach($a as $key => $val)
        {
            if ($level == 0) $arr=array() ; 
            if (is_array($val))
            {
                $str .= $level == 0 ? "{$key}" : ".{$key}" ;
                self::array_to_ini($val,$level+1,$str) ;
            } else
            {
                if (is_numeric($key))
                {
                    self::$ini .= $level == 0 ? "{$key}[] = {$val}\n"  : "{$str}[] = \"{$val}\"\n" ;
                } else
                {
                    self::$ini .= $level == 0 ? "{$key} = {$val}\n"  : "{$str}.{$key} = \"{$val}\"\n" ;
                }
            }
            $str = $level == 0 ? "" : $str ;
        }
    }

    // Parse an advanced ini file. 
    public static function parse($file, $conf=array())
    {
        if ($conf===array() && $file != "") { $conf = parse_ini_file ($file,true) ; }

        // Walk the list of first-level vars. 
        foreach($conf as $key => $val)
        {
            // Match : and . as level separators. 
            if (preg_match('/[:.]+/',$key))
            {
                $list = preg_split('/[:.]+/',$key) ;
                $ptr = &$conf ;
                foreach($list as $name)
                {
                    $name = trim($name) ; 
                    // Attempting to put in in same var as two data types, is not gonna happen. 
                    // Cause the already set string to become a recursion, but don't break execution.
                    // such as a.b = 1
                    //         a.b[] = ... will point to itself. 
                    if (isset($ptr[$name]) && !is_array($ptr[$name]))
                        { $ptr[$name] = array(&$ptr[$name]) ; }
                    // If not set, create it... 
                    if (!isset($ptr[$name]))
                        { $ptr[$name] = array() ; }

                    $ptr = &$ptr[$name] ;
                }
                // Leaf node 
                // If value is an array, insert as a repeated array (a.b[])
                if (isset($ptr) && !is_array($ptr))
                {
                    $ptr = array($ptr) ;
                    $ptr[] = $val ; 
                } else
                {
                    // If the value is an array, check up the names on that one for having dots. 
                    $ptr = (is_array($val)) ? array_merge($ptr,(array) self::parse("", $val)) : $val ;
                }

                unset($conf[$key]) ;
            } else
            {
                // Otherwise, test the subarray for the same things but for second-level. 
                if (is_array($conf[$key]))
                    { $conf[$key] = (array) self::parse("", $conf[$key]) ; }
            }
        }
        return($conf) ; 
    }
}

/*
    Advanced ini file creator.
    Input array: 
    ------------
    $conf['a'] = 1 ;
    $conf['x'][] = 1 ;
    $conf['x'][] = 1 ;
    $conf['x'][] = 1 ;
    $conf['x']['a'][] = 1 ;

    $conf['b']['a'] = 2 ;
    $conf['b']['b'] = 3 ;
    $conf['b']['c'] = 4 ;

    $conf['c']['a']['a'] = 5 ;
    $conf['c']['a']['b'] = 6 ;
    $conf['c']['a']['c'] = 7 ;

    $conf['c']['b']['a'] = 8 ;
    $conf['c']['b']['b'] = 9 ;
    $conf['c']['b']['c'] = 10 ;

    $conf['c']['b']['d'][] = 10 ;
    $conf['c']['b']['d'][] = 10 ;
    $conf['c']['b']['d'][] = 10 ;
    $conf['c']['b']['d'][] = 10 ;

    Inifile::array_to_ini($conf) returns:

    a = 1
    x[] = "1"
    x[] = "1"
    x[] = "1"
    x.a[] = "1"
    b.a = "2"
    b.b = "3"
    b.c = "4"
    c.a.a = "5"
    c.a.b = "6"
    c.a.c = "7"
    c.a.b.a = "8"
    c.a.b.b = "9"
    c.a.b.c = "10"
    c.a.b.d[] = "10"
    c.a.b.d[] = "10"
    c.a.b.d[] = "10"
    c.a.b.d[] = "10"
 
    Write the above to the file "somefile.ini"
    Inifile::write("somefile.ini",$conf) ; 
 

    Advanced ini file parser: 
    -------------------------
    Reference test.ini file. 

    root_a = 1
    root_b = 2

    [First : Second : Third]   
        fst_a = 1
        fst_b = 2 
        fst_sub1.sub2.sub3 = 3

    [First.Second]   
        fs_a = 99
        fs_b.c[] = 1 
        fs_b.c[] = 2 
        fs_b.c[] = 3 
        fs_b.c[] = 4 
        fs_b.c[] = 5 
        fs_d:e = 10
        fs_sub1.sub2.sub3 = 100

    [First]
        f_a = 1
        f_b = 2 
        f_sub1.sub2.sub3 = 3

    [SomeOther]
        so_a = 1
        so_b = 2
        so_sub1.sub2.sub3 = 3 


    $conf = Inifile::parse("test.ini")
    returns: 

    Array
    (
        [root_a] => 1
        [root_b] => 2
        [First] => Array
            (
                [f_a] => 1
                [f_b] => 2
                [Second] => Array
                    (
                        [Third] => Array
                            (
                                [fst_a] => 1
                                [fst_b] => 2
                                [fst_sub1] => Array
                                    (
                                        [sub2] => Array
                                            (
                                                [sub3] => 3
                                            )

                                    )

                            )

                        [fs_a] => 99
                        [fs_b] => Array
                            (
                                [c] => Array
                                    (
                                        [0] => 1
                                        [1] => 2
                                        [2] => 3
                                        [3] => 4
                                        [4] => 5
                                    )

                            )

                        [fs_d] => Array
                            (
                                [e] => 10
                            )

                        [fs_sub1] => Array
                            (
                                [sub2] => Array
                                    (
                                        [sub3] => 100
                                    )

                            )

                    )

                [f_sub1] => Array
                    (
                        [sub2] => Array
                            (
                                [sub3] => 3
                            )

                    )

            )

        [SomeOther] => Array
            (
                [so_a] => 1
                [so_b] => 2
                [so_sub1] => Array
                    (
                        [sub2] => Array
                            (
                                [sub3] => 3
                            )

                    )

            )

    )
*/




Using variables (constants) in Apache config.

7 04 2015

Sometimes, it is quite useful to use variables in configuration files to avoid duplication, allowing for easy changes.
Apache however, is not so willing participant to defining variables or constants in the config files, but there is a fairly easy way around it.

In the /etc/init.d/httpd startup script, there is a reference to the file /etc/sysconfig/httpd, wich it uses if existent, to source settings.
In this file, add a line at the end, pointing to your variable configuration file, such as “. /etc/httpd/conf/vars.sh”
Create this file, and chmod it to 755, to make it executable.

In this file, then add the constants you wish to become available in the Apache config files, such as:

export ROOTDIR=”/mnt/someplace/webdir”

In the Apache config, you will now be able to use this variable in the following way:

DocumentRoot ${ROOTDIR}/some_website

Of course, it can be used anywhere, as the ${NAME} will be substituted with the value.

As a little bonus, these variables can also be picked up by the applications, looking at the environment variables in whatever language you are using.

In php, this would be something like $root  = $_ENV[‘ROOTDIR’] ;
(or using the $var = getenv(“ROOTDIR”) ; )

Happy config hacking!





PHP parse_ini_advanced($filename)

22 03 2015

So, just to kick off.

I had this little problem with the parse_ini_file, in that it is a little limited.
It just doesn’t agree creating anything but first and second-level arrays, and I needed a bit more flexibility, so what does one do?

Go hunting, as you do.. Google is your friend, but this time, it was a bit of a let-down.
I wanted to be able to type

[some:sub]
a.b = 123

and have that turned into the equivalent of:

$conf[‘some’][‘sub’][‘a’][‘b’] = 123 ;

So, there were some stuff out there, but all involved multiple functions, classes, or were incomplete in function, or, using eval to get there.
It has to be simpler, methinked…
A little bit later, i got something that seems to do the trick, and does it in one go, and actually looks somewhat neat and tidy.

As I realized that there’s others having the same issue, I though, why not share the code…
If you use it, please give me some credit – a thank you would be nice, just to know it is being used =)

It’s a drop-in replacement for the parse_ini_file, just don’t feed it the “true” as second argument, or it won’t be happy.

<?php
// (C) 2015 Chris Sprucefield
// Advanced PHP .INI file reader. 
// 
// Sections such as [ abc:def ] will be put into $var['abc']['def'] = values
// Names such as a.b.c and a:b:c will be expanded into sublevels. 
// See reference at the end of the file. 

$conf = parse_ini_advanced("test.ini") ;
print_r($conf) ;

function parse_ini_advanced($file, $conf=array())
{
    if ($conf===array() && $file != "") { $conf = parse_ini_file ($file,true) ; }
    
    // Walk the list of first-level vars. 
    foreach($conf as $key => $val)
    {
        // Match : and . as level separators. 
        if (preg_match('/[:.]+/',$key))
        {
            $list = preg_split('/[:.]+/',$key) ;
            $ptr = &$conf ;
            foreach($list as $name)
            {
                $name = trim($name) ; 
                // Attempting to put in in same var as two data types, is not gonna happen. 
                // Cause the already set string to become a recursion, but don't break execution.
                // such as a.b = 1
                //         a.b[] = ... will point to itself. 
                if (isset($ptr[$name]) && !is_array($ptr[$name]))
                    { $ptr[$name] = array(&$ptr[$name]) ; }
                // If not set, create it... 
                if (!isset($ptr[$name]))
                    { $ptr[$name] = array() ; }

                $ptr = &$ptr[$name] ;
            }
            // Leaf node 
            // If value is an array, insert as a repeated array (a.b[])
            if (isset($ptr) && !is_array($ptr))
            {
                $ptr = array($ptr) ;
                $ptr[] = $val ; 
            } else
            {
                // If the value is an array, check up the names on that one for having dots. 
                $ptr = (is_array($val)) ? array_merge($ptr,(array) parse_ini_advanced("", $val)) : $val ;
            }
            
            unset($conf[$key]) ;
        } else
        {
            // Otherwise, test the subarray for the same things but for second-level. 
            if (is_array($conf[$key]))
                { $conf[$key] = (array) parse_ini_advanced("", $conf[$key]) ; }
        }
    }
    return($conf) ; 
}

/*
    Reference test.ini file. 
    
root_a = 1
root_b = 2

[First : Second : Third]   
    fst_a = 1
    fst_b = 2 
    fst_sub1.sub2.sub3 = 3

[First.Second]   
    fs_a = 99
    fs_b.c[] = 1 
    fs_b.c[] = 2 
    fs_b.c[] = 3 
    fs_b.c[] = 4 
    fs_b.c[] = 5 
    fs_d:e = 10
    fs_sub1.sub2.sub3 = 100

[First]
    f_a = 1
    f_b = 2 
    f_sub1.sub2.sub3 = 3


[SomeOther]
    so_a = 1
    so_b = 2
    so_sub1.sub2.sub3 = 3    
-------------------------------------------------------    
This is parsed as:
-------------------------------------------------------
 
Array
(
    [root_a] => 1
    [root_b] => 2
    [First] => Array
        (
            [f_a] => 1
            [f_b] => 2
            [Second] => Array
                (
                    [Third] => Array
                        (
                            [fst_a] => 1
                            [fst_b] => 2
                            [fst_sub1] => Array
                                (
                                    [sub2] => Array
                                        (
                                            [sub3] => 3
                                        )

                                )

                        )

                    [fs_a] => 99
                    [fs_b] => Array
                        (
                            [c] => Array
                                (
                                    [0] => 1
                                    [1] => 2
                                    [2] => 3
                                    [3] => 4
                                    [4] => 5
                                )

                        )

                    [fs_d] => Array
                        (
                            [e] => 10
                        )

                    [fs_sub1] => Array
                        (
                            [sub2] => Array
                                (
                                    [sub3] => 100
                                )

                        )

                )

            [f_sub1] => Array
                (
                    [sub2] => Array
                        (
                            [sub3] => 3
                        )

                )

        )

    [SomeOther] => Array
        (
            [so_a] => 1
            [so_b] => 2
            [so_sub1] => Array
                (
                    [sub2] => Array
                        (
                            [sub3] => 3
                        )

                )

        )

)

*/




Right, Time to start blogging again…

22 03 2015

It’s been some time now since I last wrote on the blog, but someone thought I should start again, so…

So, I will…

Let’s kick off with a bit of a useful stuff for PHP, that i had been looking for some time myself.

I’ll start writing about all and nothing again, from time to time, but i will try to keep it a bit more frequent this time.

 





Recession and ripoff.

30 04 2012

In a recession, I suppose that as people and business does get more and more desperate to make that extra buck, that will make the difference between a positive bottom line, or a break even or even a loss.

However, when you stoop as low as deliberately charging the wrong prices, and when called up on it, look at you as If you were some idiot with the audacity to ask them to correct it, and when pushed, fix half the problem, leaving you even more fuming, while demanding they fix the rest.
Sometimes, it’s not the money, but more the principle of the whole thing, and especially so after leaving a good tip.

I went in to this restaurant called “Made in Belfast” with my wife, had a lunch, for which they have a lunch menu with a lower price.
After we left, we realized that we had been overcharged, paying the dinner menu prices.
When challenging them, they only paid back half the difference and tried to keep the receipt, which I had to demand back, and I had to repeat the procedure.
After talking to others, others seems to have experienced this as well, but never bothered to challenge them on it.

Another day of making this extra buck, is to skimp on what you deliver.
We later went to Cafe Vaudeville in Belfast, and had a dinner.
My wife had a chicken with potato gratin, and I had a sirloin steak.
While there were nothing majorly wrong with the food itself, it was pretty bland and non-tasting.
The portion control had taken its severe toll, leaving little on the plate.
The £20 steak, was a relatively sad little skimpy bit of sirlion in the middle of the plank, with a tiny bowl of sauce, a small bowl containing a few decorative salad leafs, and 8 “triple fried” (whatever the the point is with that) fries in a small cup.
The chicken wasn’t any better, with a tiny amount of gratin on one edge of the plate, and some chicken on the other end, and some green cooked up goop in the middle.

Taken these experiences, i can only assume that it is now par for course to alienate your customers, taking as much as you can in one go, only to lose them as returning customers (and getting bad press about it, as a result…).

Made in Belfast and Cafe Vaudeville, I hope it was worth it, losing us as returning customers.
Made in Belfast – what’s worth more, the £4 you tried to scam off, and making noises about it when calling you up on it?
Cafe Vaudeville – Not serving value for money, is a costly mistake these days. Hope you too find it worthwile, and we were not the only ones unhappy with your offerings. for a £20 meal, I really don’t expect to leave hungry, that I have to go find something else as well.

I could have complained on location, yes, but that wouldnot have helped any of you, as after we’ve gone, it would have been business as usual, and none of you would have been none the wiser to the methods.

 

As to the proprietors?
Before you start screaming blue murder and telling me that I am telling porkies, and can not be…
This is something you should have thought about, before you tried it.
These are all genuine, first-hand experiences, on the 28th of April, 2012.





Who likes fireworks?

30 10 2011

Here’s a short snippet from the Belfast fireworks on the 30th of October 2011.

Enjoy!
http://www.youtube.com/watch?v=Z8EL_kRJcsI





Mozilla’s new rapid-release…

2 10 2011

Just having to vent some steam…

I never thought i’d say this, but this new rapid release scheme, is beginning to get to me, with what now feels like an update every other day, for what is in most cases, absolute trivial and minor updates, that would be far better off being gathered up in a bigger release.

In fact, it is getting so annoying now, that even me, one of the most avid FF fans, are considering alternatives.

If any of the guys at Mozilla came across this, which is extremely unlikely, and not that i think they would care anyway…

A release cycle of a year, is too long. what now feels like a few days inbetween, is just a major fail, and a quarterly update,  would be about right.

A lot of business users are moving away from Mozilla, and the reason for this, is one single reason – the rapid release scheme, as nobody has the time or stamina to keep up with mozilla, screening and deploying a new update all the time.

Even as a private user, very politely expressed, getting extremely annoyed with it, and trust me, this didn’t come easy.

Mozilla, change your ways, or you will have lost yet another user…
Do you really think that the recent drop in popularity and the introduction of your new rapid release scheme is a pure coincidence?

Think again.








Follow

Get every new post delivered to your Inbox.