4
\$\begingroup\$

I am working on a Web chat application. In the app, users can run commands (such as /nick, /msg, etc) by starting with a / and then typing the command followed by parameters. For example, if someone wanted to change their username to "foobar", they would enter this in:

/whois foobar

However, I cannot think of a good way to organize the code for this. This is what I have so far:

In User.php

function User_command(array $args)
{
 $command = $args['command']; 
 list($command_name, $command_parameters) = explode(' ', $command, 2); 
 $command_name = str_replace('/', '', strtolower($command_name)); 
$result = Command::process($command_name, $command_parameters); 
if (!$result)
 return responseFailure(); 
addQueueEntry($result['json'], $result['user_id'], $result['room_id'], $result['added_by']); 
return responseSuccess(); 
}

* In Command.php *

class Command
{
public function process($command, $parameters)
{
 $method = 'MinteCommand_' . $command; 
 if (function_exists($method))
 return $method($parameters); 
 return null; 
}
}
/* Note: When implementing commands, you must specify all fields for $response */
/* If you don't, then they might not work correctly or as intended. */
function MinteCommand_notice($message)
{
$response = array(); 
$response['json'] = array('addChatNotice' => $message);
$response['user_id'] = null; 
$response['room_id'] = MINTE; 
$response['added_by'] = SYSTEM; 
return $response; 
}
function MinteCommand_announce($message)
{
$response = array(); 
$response['json'] = array('addChatAnnouncement' => $message); 
$response['user_id'] = null; 
$response['room_id'] = MINTE; 
$response['added_by'] = SYSTEM; 
return $response; 
}
function MinteCommand_announcement($message)
{
// Command "announcement" is an alternative spelling for command "announce"
return MinteCommand_announce($message); 
}
function MinteCommand_clear($message)
{
$response = array(); 
$response['json'] = array('clearChat' => $message); 
$response['added_by'] = SYSTEM; 
$response['user_id'] = MINTE; 
$response['room_id'] = null; 
return $response; 
}
function MinteCommand_whois($username)
{
$response = array(); 
$response['added_by'] = 'SYSTEM'; 
$query = DB::query('SELECT ip_address, user_agent, last_activity, room_id FROM mt_users 
 WHERE username = ? LIMIT 1', $username); 
$exists = $query['num_rows'] > 0; 
$ip_address = $user_agent = $last_activity = $room_id = ""; 
if ($exists)
{
 $row = $query['rows'][0]; 
 $ip_address = $row['ip_address']; 
 $user_agent = $row['user_agent']; 
 $last_activity = $row['last_activity']; 
 $room_id = $row['room_id']; 
}
$response['json'] = array('addChatNotice' => !$exists ? 'User ' . $username . ' does not exist' : 
 '[' . $username . '] ' . $ip_address . '/' . $user_agent . ', last_activity=' . $last_activity . ', room_id=' . $room_id); 
$response['added_by'] = SYSTEM; 
$response['user_id'] = MINTE; 
$response['room_id'] = null; 
return $response; 
}
function MinteCommand_msg($args)
{
 list($username, $message) = explode(' ', $args, 2); 
}

How can I go about improving the code and making it more organized and elegant? In total there will be around 30 commands.

asked Jul 11, 2011 at 0:58
\$\endgroup\$
1
  • \$\begingroup\$ Just a note that you really want to whitelist the possible commands that can match, to be secure. \$\endgroup\$ Commented Jul 20, 2011 at 16:27

1 Answer 1

3
\$\begingroup\$

Just an idea, but maybe this will help you from a manageability point of view:

 public function process($command, $parameters) {
 $method = 'MinteCommand_' . $command; 
 $methodFile = dirname(__FILE__) . 'commands/' . $method . ".php";
 if (file_exists($methodFile)) {
 require_once($methodFile);
 if (function_exists($method)) { 
 return $method($parameters); 
 } else { 
 throw "invalid function";
 }
 } else {
 throw "invalid function file";
 }
 }

The only benefit to this is that you simply create a new file with the new command (function) inside of that file and it'll automatically search for it if the command is issued. One caveat will be the limit on the number of commands you can have is a limit on the number of files you can have in a single directory on the filesystem...

Note The code may not be perfect from a syntax point of view. It's just to give you the general idea / concept.

answered Jul 11, 2011 at 12:57
\$\endgroup\$
2
  • 2
    \$\begingroup\$ You cannot throw strings. \$\endgroup\$ Commented Jul 11, 2011 at 21:58
  • \$\begingroup\$ It was to provide a general suggestion .. see the Note in the post... \$\endgroup\$ Commented Jul 12, 2011 at 5:40

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.