You are viewing a read-only archive of the Blogs.Harvard network. Learn more.

Documenting Documentation

I recently waded back into simple web application development (more on how that feels later), and one of the many aspects of coding that I’ve been refreshing myself on is how to best document what I’ve written so my future self doesn’t get too confused over what I implemented or why I implemented it in the way I did. The application is deadly simple, so simple that I hesitate to call it an application. The web page contacts a PHP script via an Ajax call, and the PHP script does its thing, sending back a JSON-encoded object. The client subsequently uses the object to display a message of success or failure.

As I said, deadly simple.

Nevertheless, as simple as the application is, I’ve been researching how best to document PHP and JavaScript. For PHP, the definitive answer appears to be phpDocumentor 2. For JavaScript, there is JSDoc. Here are some additional links that I found useful:

phpDocumentor

JSDOC

Note that I haven’t actually tried generating documentation with either toolset; that’s a completely different challenge. I’ve mostly been following the format so that my documentation can be printed/generated if somebody (aka me!) wishes. And what I’ve come to understand is that learning how to document a language feels almost as complicated as learning the language itself.

 

Posted in Development, Javascript, PHP, Uncategorized. Tags: , , , . Comments Off on Documenting Documentation »

Why PHP Tidy didn’t work for me

I have to fit most of my applications within the confines of an LMS that requires everything it gets from my application to be valid XHTML. This causes an issue when displaying code users input or (in this case) 3rd party libraries are whole hog html5.

I don’t want to say you should close your tags, even in html, but you should.

So I’m using wysihtml5 for my wysiwyg needs. I wanted something smaller and cleaner than TinyMCE. What I got was something smaller. The issue created by wysihtml5 was they were doing img tags with document.createElement(‘IMG’) — which by default creates an unclosed void element. Now if you append that void element to an xhtml doctype, the browser will automatically fix it, but if you’re taking the toString of it and throwing it directly into a database, it will stay

So I decided to try and filter the entire app before it got sent to my LMS with PHP Tidy. tidy_repair_string will take a string, some config options and “fix” most validation errors.

echo tidy_repair_string($content,
array(
'output-xhtml'=>true,
'doctype'=>'omit',
'show-body-only'=>true
));

This worked almost perfectly. The only issue was wysihtml5 uses textareas. And the imgs go into the textareas. And that’s a violation of xhtml. So what does Tidy do with that violation? It just strips out the img (it also strips out brs). And there is no config option to stop that from happening. “Don’t correct this validation violation.”

So what am I stuck with?

preg_replace("/(]*)>/", "$1/>", $content);

Lame.

http://stackoverflow.com/questions/10028681/how-can-i-close-an-element-created-by-document-createelement
http://stackoverflow.com/questions/7539551/php-dom-method-createelement-need-to-be-self-closing-tag
http://stackoverflow.com/questions/7003042/javascript-createelement-no-end-tag

http://www.php.net/manual/en/tidy.repairstring.php
http://tidy.sourceforge.net/docs/quickref.html

http://stackoverflow.com/questions/15365484/prevent-php-tidy-from-converting-style-tag-data-to-cdata

Posted in Uncategorized. Tags: , , , , , , . Comments Off on Why PHP Tidy didn’t work for me »

Back in Time with PHP

I recently had the opportunity to work on a PHP application that was written by a student in 2004. Before the time of PHP frameworks and separation of MVC, when applications had SQL and HTML in the same files. Each page was a form that submitted to itself. Everything contained in one file per page. Pretty crazy, right?

Crazy like awesome. I had so much fun working on features for this old application. It wasn’t just nostalgic, it was like comfort food. Easy and delicious. I’m not really sure how comfort food is “easy”, but just go with it. I was practically begging to do more work on it.

I can’t imagine myself creating a new application like this from scratch, but I’ve been thinking about the benefits. Anyone with just a tiny bit of PHP experience could pick it up and maintain it, there’s no technology ramp-up time. A project like this could be orphaned and passed around between anyone. It could be used to teach people basic PHP within the organization. Say, people who are so Java-centric they refuse to learn anything new or different.

It was a good opportunity to take a look at the past and see what we’ve lost by going forward with technology.

Posted in Design & Modeling, Development, PHP. Tags: , . Comments Off on Back in Time with PHP »

Giving up on Yii Oracle Clobs

Started off yesterday with the intention of trying to implement functional Oracle Clobs in Yii similar to how I implemented it in CakePHP a couple years ago. As yesterday went on I kept busting through boundaries and was feeling great about my progress. But Then I hit the roadblock and I wasn’t able to continue. It’s not worth spending another couple days on when I have a deadline for a pilot by Fall. 4000 characters is enough for the pilot.

The result has been to alter the Yii COciSchema. Just changing the declaration of text to a varchar2(4000).

   public $columnTypes=array(
        'pk' => 'NUMBER(10) NOT NULL PRIMARY KEY',
        'string' => 'VARCHAR2(255)',
        //'text' => 'CLOB',
        'text' => 'VARCHAR2(4000)',
        'integer' => 'NUMBER(10)',
        'float' => 'NUMBER',
        'decimal' => 'NUMBER',
        'datetime' => 'TIMESTAMP',
        'timestamp' => 'TIMESTAMP',
        'time' => 'TIMESTAMP',
        'date' => 'DATE',
        'binary' => 'BLOB',
        'boolean' => 'NUMBER(1)',
		'money' => 'NUMBER(19,4)',
    );

The issue is Yii (PDO) doesn’t support LOBs well at all, so that declaration didn’t make any sense to begin with.

Using Smarty variables inside Javascript

I looked for appropriate answers for this on the smarty site, and the resounding answer was escaping javascript’s {}s with {literal}’s

Smarty template vars and Javascript functions
How to use Javascript codes in template files?
Access Smarty value with javascript

They basically all say to do something like this:

// $question_ids_json = ["1","2","3","4","5"]
{literal}
<script>
$(document).ready(function(){
	var question_ids = {/literal}{$question_ids_json}{literal};
	
	alert(question_ids[0]);

});
</script>
{/literal}

So they want to put everything in a literal tag, and then basically escape that literal tag when smarty needs to be used.

I didn’t like this, so I put the value in a hidden input and then just retrieved that input in the javascript, thereby keeping the js clean of smarty shenanigans:

<input type="hidden" id="question_ids" value='{$question_ids_json}'/>

<script>
$(document).ready(function(){
	//var question_ids = {$question_ids_json};
	var question_ids = eval($('#question_ids').val());
	
	alert(question_ids[0]);


});
</script>

But this is just a matter of personal preference.

Yii handling “getLastInsertId” with Oracle

With MySQL or SQLite, when you insert something with an auto_increment field, it will automatically deal with the ActiveRecord by putting the last inserted id into $model->id. Because Oracle needs sequences and triggers to deal with that, neither the PDO driver nor the Yii PDO code felt it necessary to deal with that. Most people are probably fine with commiting to a database and throwing in Oracle specific sequence_name.nextval.

I just added a class in the models to extend CActiveRecord. The only thing you need to do with this is have your model extend this instead of CActiveRecord and add the variable schemaName to the model:

class User extends QActiveRecord
{
	public $sequenceName = 'USERS_SEQ';	
...

Using Facebook authentication with Yii (PHP)

Note: There many ways to implement this, but this seemed to make the most sense to me at the time.

A login can either come from someone clicking a login link and being sent to a login page or we can force the login and not allow guests.  The login/logout button is easy enough, just modify the distributed site controller’s login and logout “action” methods.  In order to force the login, the best wat to do this is to implement a behavior.  Please see Larry Ullman’s blog for more information on that.

Then we get to the IdentityFactory.  Yii has a nice configuration system in place for its components, so I did some Identity components extending the standard Yii UserIdentity that was included with the Yii distribution. I have the login entry point call on the identity factory which checks a param in the config and returns an instance of the appropriate object.

These objects are where all authentication type specifics happen.  Lets take a look at a simple flow diagram:

Facebook auth flow

So the IdentityFactory chooses which identity we’re using based on the config.  It will send the request over to the FacebookIdentity, which gets all the info needed for the UserIdentity class to query the database, update information there, and then set the user session.

The more interesting part is the connection between FacebookIdentity and the Facebook SDK.  For this I made use of a Yii extension.  I used yii-facebook-opengraph, which, while not the most mature of facebook connect extensions, is the most actively developed and the closest to functional.  (Last year Facebook made a huge change to their SDK which is not at all backwards compatible so they broke most extensions that exist and most developers did not make updates to their extensions.)  This extension only needed one method added to help deal with the Facebook problem with access tokens.


// had to add this function to deal with php's poor handling of expired access tokens
public function setAccessToken($access_token){
return $this->_getFacebook()->setAccessToken($access_token);
}

 

Posted in ATG, PHP, Quizmo, Yii. Tags: , , , , . Comments Off on Using Facebook authentication with Yii (PHP) »

Problems with the Facebook PHP SDK

There were a few reasons I wanted to add Facebook authentication to the new iteration of Quizmo.
  • I wanted a second form of authentication to help in abstracting authentication.
  • I needed a second form of authentication because the intention is to open source this project, and I need to provide something other than iSites authentication if I want people to use it.
  • The process is very similar to Harvard’s PIN authentication, which I have done before, but probably won’t be necessary for Quizmo as it will be available through iSites.
  • “Everyone” uses Facebook so it’s probably something worth knowing.
The first minor problem was there is no proxy support.  The Facebook SDK takes you to a Facebook login page to authenticate, but before it sends you there, it checks if you’re already logged in.  This is done through a curl request.  The problem comes if you’re working in a development environment which doesn’t have a direct outlet to the internets.  The curl options are set as

public static $CURL_OPTS = array(
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_USERAGENT => 'facebook-php-3.1',
);

So this is stored as a static variable in the abstract BaseFacebook class – which is absurd because that means it can’t be overridden.  As such the following line has to be added to the BaseFacebook class:

CURLOPT_PROXY => "my.proxy.address:myport",

The larger problem with the Facebook PHP SDK is its inability to handle token errors.  The tokens are set server side when someone authenticates the first time.  These tokens then expire and the SDK is unable to handle errors that occur because of this.  The weirdest thing about this error is that the developers have a solution, they just expect people using their SDK to implement it on their end.  Regardless, their code did not work for me as advertised and had to be tweaked as such:
private function checkAccessToken(){

$app_id = ;
$app_secret = ;
$my_url = ;

// known valid access token stored in a database
$access_token = ->getAccessToken();

$code = @$_REQUEST["code"];

// If we get a code, it means that we have re-authed the user
//and can get a valid access_token.
if (isset($code)) {
$token_url="https://graph.facebook.com/oauth/access_token?client_id="
. $app_id . "&amp;amp;amp;amp;amp;redirect_uri=" . urlencode($my_url)
. "&amp;amp;amp;amp;amp;client_secret=" . $app_secret
. "&amp;amp;amp;amp;amp;code=" . $code . "&amp;amp;amp;amp;amp;display=popup";

// Now all file stream functions can use this context.
$response = $this->curl_get_file_contents($token_url);
$params = null;
parse_str($response, $params);
$access_token = @$params['access_token'];
}

// Attempt to query the graph:
$graph_url = "https://graph.facebook.com/me?"
. "access_token=" . $access_token;
$response = $this->curl_get_file_contents($graph_url);
$decoded_response = json_decode($response);

//Check for errors
if (@$decoded_response->error) {
// check to see if this is an oAuth error:
if ($decoded_response->error->type== "OAuthException") {
// Retrieving a valid access token.
$dialog_url= "https://www.facebook.com/dialog/oauth?"
. "client_id=" . $app_id
. "&amp;amp;amp;amp;amp;redirect_uri=" . urlencode($my_url);
error_log("top.location.href='" . $dialog_url);
}
else {
error_log("other error has happened");
}
}
else {
// success
//error_log("success" . $decoded_response->name);
//error_log($access_token);
}

return $access_token;

}
Posted in ATG, PHP, Quizmo. Tags: , , , , , , . Comments Off on Problems with the Facebook PHP SDK »