This is a continuation from a previous post – php-in-universe

Well, I have been going mad with the PHP stuff.

I have installed the Zend framework library on my system and I can now use all the components within the library to perform all sorts of exciting stuff.

For example, the framework has a component for common validations.

I decided to write a PHP script/program to use the email address validator.

It is a simple script which accepts an email address as an option on the command line and checks to see if it is valid:

#!/usr/local/bin/php

// Email address format check using Zend Framework
// Copyright 2008 David J Murray

// Get Zend library code
require_once 'Zend/Validate/EmailAddress.php';

//Define exit constants which can be used from UniBasic PERFORM
define('OK',0);
define('BAD',1);

// Get email address argument from command line
$email = $argv[1];

// Validate
$validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS, true);

// Check validate result
if ($validator->isValid($email)) {
// email appears to be valid

    echo "email ok";
    exit(OK);

} else {
// email is invalid; print the reasons

    foreach ($validator->getMessages() as $message) {
        echo "$message";
    }
    exit(BAD);
}
?>

As I set the exit codes within the PHP script, these should be transferred through and be readable in UniBasic after a PERFORM from the @SYSTEM.RETURN.CODE.

Now, how do I run this PHP script in UniVerse? Well, I can create a VERB in the VOC which runs this script:

VALIDATE.EMAIL
0001 V
0002 /usr/ibm/WLA/PHP.BP/VALIDATE.EMAIL.PHP
0003 U
0004 TICGR

And if I now run it:

>VALIDATE.EMAIL davidjmurray@u2blog.org
email ok
>

I get the expected answer. If I enter in an incorrect email address:

>VALIDATE.EMAIL davidjmurray@u2blog
'u2blog' is not a valid hostname for email address 'davidjmurray@u2blog'
'u2blog' does not match the expected structure for a DNS hostname
'u2blog' appears to be a local network name but local network names are not allowed
'u2blog' does not appear to have a valid MX record for the email address 'davidjmurray@u2blog'
>

And I get the expected answer. In this case it is a bad email address. You will see that the PHP script actually checks to see it a valid MX record exists!

And in UniBasic:

EMAIL.ADDR = "davidjmurray@u2blog.org"
perform "VALIDATE.EMAIL " : EMAIL.ADDR
if @SYSTEM.RETURN.CODE ne 0 then

    * error
end

And similar in an SB+ paragraph process, except that SB+ uses the EXECUTE so the @SYSTEM.RETURN.CODE will not be available and you will have to capture and check the returned text message.

All good stuff, but I found that it is going to be a bit laborious adding all the entries to the VOC for the new PHP scripts. There are quite a lot of code snippets and libraries out there. Wouldn’t it be nice if it was possible to catalog a PHP script/program the same way a UniBasic program can be?

Well, this got me thinking…

As I want to use a UniVerse file to store the PHP scripts and also edit them from ECL, and after some thought on the matter, I ended up with this:

program PHP.CATALOG
*************************
*
* Program to 'catalog' a PHP program
* A verb entry is added to the VOC PICK or LOCAL catalog style
*
* The first line of the PHP source code must have a shebang - #!/usr/local/bin/php
* or where ever php is.
*
* Uses the php verb in the VOC as a template for the new verb.
*
*
*************************
*
$COPYRIGHT DAVID J MURRAY 2008

* Created by David J Murray 20 Jan 2008.

* Include for FILEINFO statement - may need to add q-pointer to uv account for include file
$INCLUDE INCLUDE FILEINFO.INS.IBAS

* Constants
equate EMPTY.STR TO ""
eqaute SPACE1 TO space(1)

* Get options from command line and extract
OPTIONS = @SENTENCE

* Syntac is similar to real CATALOG verb - CATALOG filename catalogname [programname]
FILE.NAME = field(OPTIONS, SPACE1, 2)
CATALOG.NAME = field(OPTIONS, " ", 3)
PROGRAM.NAME = field(OPTIONS, " ", 4)

*Must have a source file name
if FILE.NAME eq EMPTY.STR then

  stopm "Must supply source file name. ABORTING."
end

* Must have a name for the catalog or VOC entry
if CATALOG.NAME eq EMPTY.STR then

  stopm "Must supply catalog name. ABORTING."
end

* The program name is optional and assumed to be the same as the catalog name.
if PROGRAM.NAME eq EMPTY.STR then

  PROGRAM.NAME = CATALOG.NAME
end

* Open VOC and check to see if catalog name exists
open "VOC" to VOC.FV else

  abort "Can not open VOC. ABORTING."
end

readu VOC.REC from VOC.FV, CATALOG.NAME then

  stopm "Catalog name already exists in VOC. ABORTING."
end

* Open source file and check for php source
open FILE.NAME to FILE.FV else

  stopm "Can not open file - " : FILE.NAME : ". ABORTING."
end

* Check that source file is a directory type
FILE.TYPE = fileinfo(FILE.FV, FINFO$TYPE)
if FILE.TYPE ne 4 then

  stopm "Source file type is not 1 or 19. ABORTING."
end

* Check that php program exists
read PROGRAM.REC from FILE.FV, PROGRAM.NAME else

  stopm "Can not read php program - " : PROGRAM.NAME : " -  FROM FILE - " : FILE.NAME : ". ABORTING."
end

* Use the php verb in the VOC as a template
read TEMPLATE.REC from VOC.FV, "PHP" else

  stopm "Can not read PHP verb from VOC. ABORTING."
end

* First line of php source code must have be a shebang line
SHEBANG = "#!" : TEMPLATE.REC<2>

if PROGRAM.REC<1> ne SHEBANG then

  stopm "First line of php source code is not " : SHEBANG : ". ABORTING."
end

* Create new verb
VOC.REC = TEMPLATE.REC
VOC.REC<1> = "V"

* Use the FILEINFO function to return the full path of the source code file and then add the source code program
* name at the end. Using a '/' here as in Linux.
PROGRAM.FULLPATH = FILEINFO(FILE.FV, FINFO$PATHNAME) : "/" : PROGRAM.NAME
VOC.REC<2> = PROGRAM.FULLPATH

* Write away with catalog name
write VOC.REC on VOC.FV, CATALOG.NAME

stopm CATALOG.NAME : " cataloged."

end

The above program is in a very simple top-down structure for a Linux environment, but it does prove the concept.

And I can catalog a PHP script:

>PHP.CATALOG PHP.BP VALIDATE.EMAIL VALIDATE.EMAIL.PHP
VALIDATE.EMAIL cataloged.
>

OK!

Now, based on the same principle, it should be possible to write a PHP.DECATALOG program (PICK/LOCAL style) or how about a PHP.COMPILE?

Well, a PHP script is never truly compiled as it is interpreted during the runtime – hence the name of a PHP procedure is a script not a program. But there is a PHP syntax checker available and can be run with the php -l command.

Well, thats about it. There is an option during the compiling/building of PHP for embedding (-enable-embed) which produces a c+ file called libphp5.so. I can find very little information on this, but it would be the next logical step if you wanted to use the CGI functionality of U2 to embed PHP as a series of function calls.