Wednesday, April 23, 2008

Xataface - How to unset tabs in the table view

Inside of a delegate class' fields.ini file, you can specify the notion of "tabs" and actually put separate fields into their tabs.

Sometimes you don't want a tab to appear in the view of a record. You can set the permissions of this like this:



function __tabs__(&$record){
$user =& getUser();

$t =& $record->_table;
$tabs = $t->_tabs;
if ( $record and !isAdmin() ){

if ( !$record->val('people_approval_status') )
unset($tabs['__people__']);
if ( !$record->val('researcher_approval_status') )
unset($tabs['__gcms__']);
}
return $tabs;
}


Here we call the __tabs__ function to actually process the tabs before they are run. And then we unset the tabs that we don't want the user to see.

Saturday, April 12, 2008

Creating multiple drupal sites on the local machine

This is supplementary information on the article listed at: http://drupal.org/node/120647

So there were a few things that I had trouble with:


  1. Copy the database to a new database.
    This step kept failing saying that I was failing a constraint test (it said I had a duplicate key). I don't really really see why it failing considering that my users table only had 2 users. The first user was actually a blank row, that had only the default values. This seemed to have been the initialize drupal installation.

    So to solve this, I went into the database and literally just deleted that row. And when I now tried to copy the database to a new database, it worked.

  2. Modifying the httpd-vhosts.conf and hosts file
    It says to comment out existing lines, but I was using the Apache 2.2.6 which had them uncommented anyways. This file is not used anyways unless you tell it to be used in the httpd.conf file which is configured in an early step.

    For each new site, you need to add this:

    <VirtualHost *:80>
    DocumentRoot /www/drupal/
    ServerName databasename
    </VirtualHost>


    What this actually does it set the location of the files to be accessed when someone tries to access the server name. This actually is in relationship with the hosts file in the /windows/system32/drivers/etc directory.

    I had this annoying problem with vista where I couldn't edit the file because I didn't have permissions. So I just copied and pasted the file on my desktop. Opened it, edited it and the pasting it back in the same directory effectively overwriting it


    If you look at this file you should see some lines like this:


    127.0.0.1 localhost
    ::1 localhost
    127.0.0.1 how_far_are_you
    127.0.0.1 drupal_test_database


    This maps IP address to host names (Servers). The number 127.0.0.1 means localhost, and then we say that this IP address can map to three servers: localhost, how_far_are_you, and drupal_test_database.

    Where are these locations/Servers? Well they are actually on your machine!!! These are specified in your httpd-vhosts.conf file above. Each server must be listed with:


    <VirtualHost *:80>
    DocumentRoot /www/drupal/
    ServerName databasename
    </VirtualHost>


    So for example:


    <VirtualHost *:80>
    DocumentRoot ""D:\web\webserver\htdocs\drupal-6.2"
    ServerName how_far_are_you
    </VirtualHost>


    This says that this server "how_far_are_you" is located at the file location specified under document root. For another drupal site, we do exactly the same thing, expect the servername is just different (it is the database name)

    So the interesting thing is that they both point to the same document root. In order to differentiate the two different sites, we use the database names.

    Actually now that I think about it. I think it just matches the name of the site folder (ie .drupal/sites/site_name). Because the settings.php file handles the database name connection. Haven't confirmed this yet though.


    One thing I want to mention is that because turn this virtual host thingy on, typing in http://localhost no longer works. You actually have to add the line:


    <VirtualHost *:80>
    DocumentRoot ""D:\web\webserver\htdocs"
    ServerName localhost
    </VirtualHost>


    For it to work. I think this was taking care of when the virtual host feature wasn't turned on.



This is a pretty interesting thing, and it also allows to just declare like domain names to point to different document roots on the local computer. This is essentially how virtual servers work (where one machine hosts multiple sites!)

One interesting thing I tried to do was skip the part about editing the host file, and see what happened if I just typed in http://name_of_servername. It didn't worked and it searched the web actually. I suspect that part is necessary, because typing in http://... causes it to first search your local machine for valid servername. So the host file is necessary

Friday, April 11, 2008

Drupal - Getting Started

Once I followed the video to install Drupal, I ran into this problem where when I tried to click on any link in the index.php file in the drupal directory it would lead me right back to a view of the directory.

I suspected this has something to do with the fact that I didn't my local installation of apache to serve the index.php file if it was present (similar to how index.html is the file to be served when the user first enters that directory.

So going into my httpd.conf file, I searched for the line "DirectoryIndex", and then modified it to include index.php:

DirectoryIndex index.html index.php


Note how index.html was already being served. And when I went back to my drupal directory and tried a link, it worked!

GD Library Not Found
Upon entering the administrator page, I found that I had some status errors right off the bat. Clicking on the link to see what status errors there were, I found one to say that my "GD Library" was not found. This is an image library that is required for drupal to do some image manipulation for some themes or maybe so content. Anyways, the version of PHP 5.2.5 that I am using actually has this library but it is turned off by default.

So go to the php.ini file, and search for the line "extension=php_gd2.dll" and then there should be a semicolon right before it. Just remove the semicolon and then try it again and that should fix the problem.

Wednesday, April 9, 2008

functions.inc.php

If you create this file in a folder called include, this file will be included in every page and the functions will be available. I've included like an example of this file with some functions that serve as an example of what it can be used for:


error_reporting(E_ALL);
ini_set('display_errors','On');
define('APPROVAL_LEVEL_APPROVED',2);
define('APPROVAL_LEVEL_CONDITIONAL',1);
define('APPROVAL_LEVEL_NOT_APPROVED',0);

define('APPROVAL_STATUS_APPROVED',2);
define('APPROVAL_STATUS_NOT_APPROVED',0);

function isLoggedIn(){
static $loggedIn = 0;
if ( $loggedIn === 0 ){
$user =& getUser();
if ( $user ) $loggedIn = true;
else $loggedIn = false;
}
return $loggedIn;
}

function &getUser(){
static $user = 0;
if ( $user === 0 ){
$auth =& Dataface_AuthenticationTool::getInstance();
$user = $auth->getLoggedInUser();
}
return $user;
}

// Checks whether the current user is an admin or not.
function isAdmin(){
$user =& getUser();
if ( !$user ) return false;
return ($user->val('role') == 'ADMIN');
}

function isBrokerCustomer(){
$user =& getUser();
if ( !$user ) return false;
return ($user->val('cookedRole') == 'BROKER CUSTOMER');
}

function getDealerID(){
static $dealer_id = -1;
$user =& getUser();
if ( !$user){
if ( $dealer_id == -1 ){
$res = mysql_query("select company_id from companies where host_name='".addslashes($_SERVER['HTTP_HOST'])."' limit 1", df_db());
if ( mysql_num_rows($res) == 0 ) $dealer_id = null;
else list($dealer_id) = mysql_fetch_row($res);
}
return $dealer_id;
}
return $user->val('dealerID');
}

function &getBrokerDealer(){
static $bd = 0;
if ( $bd === 0 ){
$id = getDealerID();
if ( $id ){
$bd = df_get_record('companies', array('company_id'=>$id));
}
}
return $bd;
}

function isBrokerDealer(){
$user =& getUser();
if ( !$user ) return false;
return ($user->val('cookedRole') == 'BROKER DEALER');
}

function isCompanyOwner(){
$user =& getUser();
if ( !$user ) return false;
return ($user->val('cookedRole') == 'COMPANY OWNER');
}

function isCompanyRep(){
$user =& getUser();
if ( !$user ) return false;
return ($user->val('cookedRole') == 'COMPANY REP');
}

function getCompanyID(){
$user =& getUser();
if ( !$user ) return null;
return $user->val('companyID');
}

function &getCompany(){
static $company = 0;
if ($company === 0 ){
$id = getCompanyID();
if ( $id ){
$company = df_get_record('companies', array('company_id'=>$id));
}
}
return $company;
}


function off($date){
$date = strtotime($date);
$offset = (strftime("%j")+strftime("%Y")*365)-
(strftime("%j",$date)+strftime("%Y",$date)*365);
if ($offset>7){
$offset = (strftime("%V")+strftime("%Y")*52)-
(strftime("%V",$date)+strftime("%Y",$date)*52);
$end=($offset!=0?($offset>1?$offset . " weeks ago":"a week ago"):"Today");
} else
$end=($offset!=0?($offset>1?"$offset days ago":"Yesterday"):"Today");
return strftime("%A, %B %e, %Y",$date)." - ". $end;
}


Here we have some common functions to help figure out what type of user is logged in.

Actions: Adding new actions at specific locations

One thing that seemed to escape me for the longest time was the fact that when I included an actions.ini, or like a permissions.ini file in my website's directory. I was actually overriding the actions and permissons.ini files in the main dataface directory.

My point of stating this was I wanted to figure out how to like add new actions to specific blocks/spaces in my website. Like for example, where the "list", "detail", "find" buttons are. In the actions.ini file, each action has an attribute called category and you can assign this a value. And then templates will uses these categories to figure out which actions to place where.

So my problem was trying to find out what categories were available. All this information is available in the dataface directory's actions.ini file.

Thursday, April 3, 2008

Permissions

So I've been doing a lot of research into the permission in dataface and I think I have a pretty good understanding.

There is a global permission setting you can set for all tables in the conf/ApplicationDelegate.php class. So you can grant a particular user to say all the tables, or block them from all tables in this class. This is accomplished through the function getPermission() in the ApplicationDelegate.php class.


function getPermissions(&$record){
$auth =& Dataface_AuthenticationTool::getInstance();
$user =& $auth->getLoggedInUser(); //grabs the logged in user
if ( !isset($user) ) return Dataface_PermissionsTool::NO_ACCESS(); //if there is no user logged in, then they should not have access to anything.
$role = $user->val('role'); //grab the role of the user. the val function just returns the value of the parameter
if ( !$role ) return Dataface_PermissionsTool::NO_ACCESS(); //if no role, then they should get no permissions
return Dataface_PermissionsTool::getRolePermissions($role); //return the permissions of that role.
}


Now if you want to block them for specific tables, these permission settings are to be set at the delegate class table level. For example,


$auth =& Dataface_AuthenticationTool::getInstance();

$user =& $auth->getLoggedInUser();

//if user is not set and (no record OR no memberID) and action is new
//give them person to edit. Enter information into the fields
if ( !$user and ( !$record || !$record->val('memberid') ) and @$_GET['-action'] == 'new' ){

return Dataface_PermissionsTool::getRolePermissions('EDIT');

//if there is just no user then they should have no acess
} else if (!$user ) {

return Dataface_PermissionsTool::NO_ACCESS();

//if there is a user, then return the role permissions of that user
} else {

return Dataface_PermissionsTool::getRolePermissions($user->val('role'));

//return PEAR::raiseError('Let the app delegate class handle it', DATAFACE_E_REQUEST_NOT_HANDLED);

}


And if we want even more fine grained, then we can do it was the field level. The field level is a little more tricky thou. To provide permissions for a given field, it must follow this syntax:

function FIELDNAME__permissions(&$record)


The record represents the given record object in question (not 100% how this works...but it could mean a row in the database...but if it is a submission form is the row empty?).

The function body could be:


$auth =& Dataface_AuthenticationTool::getInstance();

$user =& $auth->getLoggedInUser();

if ( !$user or $user->val('role') != 'ADMIN'){

return Dataface_PermissionsTool::NO_ACCESS();

}


Here we are getting the logged in user, and it doesn't exist, or if it does exist, but role is NOT admin, then they should have no access and thus it will not appear in the form.

Installation

I've decided to update this post (done on Nov 29th) to add all the problems I've had with the installation of dataface and following that "Getting Started" tutorial. So below is a list of them:

Nothing shows up in the dataface_info.php file
So I followed the instruction on the dataface site (the getting started article), but nothing even shows up! What the? Turns out the actual file relies on short tags (ie.

session_save_path is not set
So when first setting up Dataface, I always ran into this stupid problem that it says that my session_save_path is never set...
And then it refers you to line 531 of the Application class. Here you see the code:

$sessdir = ini_get('session.save_path');
if ( !$sessdir ) $sessdir = '/tmp';
$sessdir .= "/dataface";

So basically it tries to grab the ini config value session.save_path from the php.ini file...and if it isn't set then it sets it to /tmp/dataface.

Now the thing is on windows, the session.save_path value is not set by default, so it attempts to set this to /tmp/dataface...only we are using windows and not linux (windows has paritions where linux treats the /tmp to be the root directory)

So the solution is basically just make some folder location on your windows hard drive and then in the php.ini file look for the variable session.save_path and set it to that location.

This should solve the problem.

Unable to insert a new record
So after getting past the initial steps of installing and having dataface create the front end. You can then start adding some records. But when you try to add a new record into the course table, I ended up with this sql error saying that the PDF outline column has no default value. I went into phpmyadmin and looked up the column and sure enough the column was set to not allow NULL. I guess this might have been an intended feature, but in the form no red box is beside that field to even indicate that. Maybe a bug? In any case, the solution is to simply make that column NULLABLE.

Complaining about invalid character (eg. /) in a file when it doesn't exis
I was on the trigger part of the tutorial making a course.php delegate file. But when I made the file, I originally set it as a Rich Text Document. I didn't think this would be a problem as I just renamed it into a .php extension. So did all my work and then tried to reload my wwebapp. Bam! These errors about invalid characters in my course.php. Odd...I was looked inside to find nothing and I even got rid of everything and had the basic:

class tables_Course {
}
?>


And still errors!!! And then it occurred to me that maybe when I made it as a rich text document it added some additional crap in the file that I can see. So I deleted the entire file and remade it as a plain text document (.txt) and everything worked!