CodeIgniter - how to selectively cache output? - php

My application allows registered users to post stuff. On the top bar, like many social apps, when logged in one can see their avatar etc.
My issue is that the user-specific content in the header gets cached when using CodeIgniter's output cache.
This is because first I load user-specific logic via a MY_Controller, which is then extended by all other controllers.
When I place
$this->output->cache(MINUTES);
in the controller that loads my home page, it also ends up caching the avatar and name of the user that generated that cached page.
Does anyone have a suggestion on what would be the best way to selectively cache only the public content? Glad to post more code if needed.

I'm sure someone will correct me if I'm wrong but I believe codeigniter caching only allows the caching of full pages. There are some additional libraries which enable partial page caching, check out phil sturgeons effort here:
http://getsparks.org/packages/cache/show
My personal approach is to not bother with page caching and just use database caching which is more selective - but if you want/need page caching then I think the above is the only way to go

Codeigniter do not separate cache by visitor and authenticated user.
Otherwise you can do it by yourself by override output class.
Create MY_Output.php in CI/application/core
This is my code for latest project.
class MY_Output extends CI_Output
{
/**
* Write Cache
*
* #param string $output Output data to cache
* #return void
*/
public function _write_cache($output)
{
$CI =& get_instance();
//-XXX CUSTOM------------------------------------
$cache_path = $this->cachePath();
//-----------------------------------------------
if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
{
log_message('error', 'Unable to write cache file: '.$cache_path);
return;
}
$uri = $CI->config->item('base_url')
.$CI->config->item('index_page')
.$CI->uri->uri_string();
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
if (is_array($cache_query_string))
{
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
}
else
{
$uri .= '?'.$_SERVER['QUERY_STRING'];
}
}
$cache_path .= md5($uri);
if ( ! $fp = #fopen($cache_path, 'w+b'))
{
log_message('error', 'Unable to write cache file: '.$cache_path);
return;
}
if ( ! flock($fp, LOCK_EX))
{
log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
fclose($fp);
return;
}
// If output compression is enabled, compress the cache
// itself, so that we don't have to do that each time
// we're serving it
if ($this->_compress_output === TRUE)
{
$output = gzencode($output);
if ($this->get_header('content-type') === NULL)
{
$this->set_content_type($this->mime_type);
}
}
$expire = time() + ($this->cache_expiration * 60);
// Put together our serialized info.
$cache_info = serialize(array(
'expire' => $expire,
'headers' => $this->headers
));
$output = $cache_info.'ENDCI--->'.$output;
for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
{
if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
{
break;
}
}
flock($fp, LOCK_UN);
fclose($fp);
if ( ! is_int($result))
{
#unlink($cache_path);
log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
return;
}
chmod($cache_path, 0640);
log_message('debug', 'Cache file written: '.$cache_path);
// Send HTTP cache-control headers to browser to match file cache settings.
$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
}
// --------------------------------------------------------------------
/**
* Update/serve cached output
*
* #uses CI_Config
* #uses CI_URI
*
* #param object &$CFG CI_Config class instance
* #param object &$URI CI_URI class instance
* #return bool TRUE on success or FALSE on failure
*/
public function _display_cache(&$CFG, &$URI)
{
//-XXX CUSTOM------------------------------------
$cache_path = $this->cachePath($CFG);
//$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
//-----------------------------------------------
// Build the file path. The file name is an MD5 hash of the full URI
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
if (is_array($cache_query_string))
{
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
}
else
{
$uri .= '?'.$_SERVER['QUERY_STRING'];
}
}
$filepath = $cache_path.md5($uri);
if ( ! file_exists($filepath) OR ! $fp = #fopen($filepath, 'rb'))
{
return FALSE;
}
flock($fp, LOCK_SH);
$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';
flock($fp, LOCK_UN);
fclose($fp);
// Look for embedded serialized file info.
if ( ! preg_match('/^(.*)ENDCI--->/', $cache, $match))
{
return FALSE;
}
$cache_info = unserialize($match[1]);
$expire = $cache_info['expire'];
$last_modified = filemtime($filepath);
// Has the file expired?
if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
{
// If so we'll delete it.
#unlink($filepath);
log_message('debug', 'Cache file has expired. File deleted.');
return FALSE;
}
// Send the HTTP cache control headers
$this->set_cache_header($last_modified, $expire);
// Add headers from cache file.
foreach ($cache_info['headers'] as $header)
{
$this->set_header($header[0], $header[1]);
}
//-XXX CUSTOM------------------------------------
$exTime = $this->executionTime();
setcookie('exe_time', "$exTime", time()+120, '/');
//-----------------------------------------------
// Display the cache
$this->_display(self::substr($cache, self::strlen($match[0])));
log_message('debug', 'Cache file is current. Sending it to browser.');
return TRUE;
}
// --------------------------------------------------------------------
/**
* Delete cache
*
* #param string $uri URI string
* #return bool
*/
public function delete_cache($uri = '')
{
$CI =& get_instance();
//-XXX CUSTOM------------------------------------
$cache_path = $CI->config->item('cache_path');
$cache_path = ($cache_path === '') ? APPPATH.'cache/' : $cache_path;
//-----------------------------------------------
if ( ! is_dir($cache_path))
{
log_message('error', 'Unable to find cache path: '.$cache_path);
return FALSE;
}
if (empty($uri))
{
$uri = $CI->uri->uri_string();
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
if (is_array($cache_query_string))
{
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
}
else
{
$uri .= '?'.$_SERVER['QUERY_STRING'];
}
}
}
//-XXX CUSTOM------------------------------------
$passed = TRUE;
$path1 = $cache_path.'xmember/'.md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
if ( ! #unlink($path1))
{
log_message('error', 'Unable to delete cache file for '.$uri);
$passed = FALSE;
}
$path2 = $cache_path.'xvisitor/'.md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
if ( ! #unlink($path2))
{
log_message('error', 'Unable to delete cache file for '.$uri);
$passed = FALSE;
}
//-----------------------------------------------
return $passed;
}
private function cachePath(&$CFG=false)
{
$hasSession = !empty($_COOKIE[COOKIE_CUSTOMER_SESSION_ID]);
if(empty($CFG)) {
$CI =& get_instance();
$CFG = $CI->config;
}
$path = $CFG->item('cache_path');
$path = empty($path) ? APPPATH.'cache/' : $path;
$path .= $hasSession?'xmember/':'xvisitor/';
return $path;
}
function executionTime()
{
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$total_time = round(($time - LOAD_PAGE_START), 4); //second unit
return $total_time;
}
}

Related

I have created a FileUploader class in PHP which validates and uploads any submited file. works fine but does not move the uploaded file

I am working on a project and so I am writing Object Oriented PHP. Hence, I have created a class called FileUploader. This class has all the method to validate file size, and file extension type as well as create directories if not existing.
Everything works just fine but I noticed that it only creates empty directories and does not move the uploaded files. I tried accessing the File error form the stored property but it always gives 0 as the error code
This is the FileUploader class
<?php
namespace Utility\Classes;
class FileUploader
{
//property declarations
protected $error_msg = array();
protected $tmp_file_name;
protected $max_file_size;
protected $target_location;
protected $allowed_file_type = array();
protected $File;
protected $default_file_name = true;
private $backlink_step;
private $unit_size; //to keep track of measurement unit of upload sizes MB|KB|BYTES
function __construct(array $file, array $allowed_ext = [], int $file_max_size = 5)
{
$this->File = $file;
$this->backlink_step = '';
$this->set_allowed_extensions($allowed_ext);
$this->set_max_upload_size($file_max_size);
}
/*This method helps to make sure that files are uploaded to the exact location as desired
*as in the case of deep nesting of subdirectory process
*/
function set_backlink_step($prfx)
{
$this->backlink_step = $prfx;
}
function set_target(string $target, $dated = false)
{
$this->target_location = $target;
if ($dated) {
$this->target_location .= "/" . $date = date("M-Y");
}
}
function get_target()
{
return $this->target_location;
}
//method to set valid/allowed file types
function set_allowed_extensions(array $allowed_ext)
{
$this->allowed_file_type = $allowed_ext;
}
//method to get the allowed file extensions
function get_allowed_extensions()
{
return $this->allowed_file_type;
}
function set_error_msg($err)
{
$this->error_msg[] = $err;
}
function get_error_msg()
{
return $this->error_msg;
}
function set_file_name($name)
{
$this->File['name'] = $name;
}
function get_file_name()
{
return $this->File['name'];
}
function get_tmp_name()
{
return $this->File['tmp_name'];
}
/**
* #description: method to return file size in a specified unit
* #param:String ['TB'|'MB'|'KB'|'B'] default MB
* #return: Int file size
* */
function get_file_size(String $unit = "MB")
{
if (strtolower($unit) === "tb") {
$quadrant = 1024 * 1024 * 1024;
} elseif (strtolower($unit) === "mb") {
$quadrant = 1024 * 1024;
} elseif (strtolower($unit) === "kb") {
$quadrant = 1024;
} elseif (strtolower($unit) === "b") {
$quadrant = 1;
}
$size = $this->file_size() / $quadrant;
return number_format($size, 2);
}
/**
* #return int size of the file
* */
function file_size()
{
$fsize = $this->File['size'];
return $fsize;
}
/* Method to get the extension name of a file eg: jpg,mp4 */
function get_ext()
{
$extension = explode('.', $this->get_file_name());
return "." . end($extension);
}
function validate($allowed_ext = [])
{
//fall back to the object allowed_file_type property if param not set by user
if (empty($allowed_ext)) {
$allowed_ext = $this->get_allowed_extensions();
}
//validate allowed file type if specified in the array
if (!empty($allowed_ext)) {
if (!$this->is_allowed_extension($allowed_ext)) {
$this->set_error_msg("Type of '{$this->get_file_name()} does not match allowed file types [" . implode('|', $this->get_allowed_extensions()) . "]");
return false;
}
}
//validate file size
if ($this->is_above_max_upload_size()) {
$this->set_error_msg("Size of the file '{$this->get_file_name()}' is larger than max allowed size of {$this->get_max_upload_size()}");
return false;
}
return true;
}
/*Method to upload file
* #return: the uploaded target location
*/
function upload_file()
{
//create necessary directories if not in existence
$this->create_dir();
$target = $this->backlink_step . $this->target_location . "/" . $this->get_file_name();
//attempt upload of the file
if (move_uploaded_file($this->tmp_file_name, $target)) {
//update target location with the filename
return $target;
} else {
//return false;
die("tmp_name: {$this->get_tmp_name()} \n target: {$target} \n Error: {$this->File['error']}");
}
}
/*This method sets the maximum upload size for file track and album_art respectively
*This method ignores invalid value for unit and replaces it with bytes*/
function set_max_upload_size($file_size, $unit = "MB")
{
$mulitplicant = 1;
if (strtolower($unit) === "tb") {
$multiplicant = 1024 * 1024 * 1024;
} elseif (strtolower($unit) === "mb") {
$multiplicant = 1024 * 1024;
} elseif (strtolower($unit) === "kb") {
$multiplicant = 1024;
} else {
$unit = "Bytes";
}
$this->max_file_size = $multiplicant * $file_size; //set max size for file
$this->unit_size = strtoupper($unit);
}
function get_max_upload_size()
{
return $this->max_file_size;
}
/*Method to compare the size of files to be uploaded with the maximum allowed size*/
function is_above_max_upload_size()
{
$file_unit = $this->unit_size;
//return FALSE if upload size > max size otherwise TRUE
return ($this->file_size() > $this->get_max_upload_size()) ? true : false;
}
/*Method to check if upload file is allowed in by extension name
*The first paramater takes the string of the actual file extension
*The second parameter takes an array of allowed extensions
*/
function is_allowed_extension(array $allowed_ext)
{
return (!in_array($this->get_ext(), $allowed_ext)) ? false : true;
}
//method to create directories
function create_dir()
{
//check if user set a storage location and attempt to create the location
if (empty($this->get_target())) {
$this->set_error_msg('Target Not set.');
return false;
}
//Create the directory
$location = explode('/', $this->get_target());
$prepend = $this->backlink_step . "";
foreach ($location as $key => $value) {
if (!is_dir($prepend . $value)) {
mkdir($prepend . $value);
}
$prepend .= $value . "/";
}
}
}
Then I have another php script where I process the uploaded file by instantiating the FileUploader Class with the $_FILES variable process.php
require_once "../vendor/autoload.php";
use Utility\Classes\FileUploader;
//Instantiate new FileUploader with the files to be uploaded.
$LogoUploader = new FileUploader($_FILES['logo'], ['.png', '.jpg']);
//validate logo size and type - Upload to folder if everything Ok
$logo_validated = $LogoUploader->validate();
//upload files that passed validation
if ($logo_validated) {
$LogoUploader->set_target($location);
$LogoUploader->set_backlink_step('../');
$ltarget = $LogoUploader->upload_file();
if (!$ltarget) {
//upload error
print_error($LogoUploader->get_error_msg());
exit;
} else { //upload success
print "Logo uploaded successfully";
}
} else { //validation error
print_error($LogoUploader->get_error_msg());
exit;
}
Please what am I not doing right?? everything is ok, validation is working, user can set the upload target and if it does not exist, it will be created but it does not upload the file into the created directory or anywhere else in my working directory
I think you need to change the following line
if (move_uploaded_file($this->tmp_file_name, $target)) {
to
if (move_uploaded_file( $this->get_tmp_name(), $target )) {
in the upload_file method. ie:
public function upload_file(){
$this->create_dir();
$target = $this->backlink_step . $this->target_location . "/" . $this->get_file_name();
if (move_uploaded_file( $this->get_tmp_name(), $target )) {
return $target;
} else {
die("tmp_name: {$this->get_tmp_name()} \n target: {$target} \n Error: {$this->File['error']}");
}
}

PHP ftp_connect doesn't responds from batch file in scheduled task

I have a PHP script that synchronize a local directory with a remote one ...
[...]
$ftp = new Ftp('11.222.11.222', 'the_user', 'the_pass');
$ftp->syncFolder('userfiles/project', '/web/userfiles/project', true);
[...]
And a Class
class Ftp
{
public $conn;
private $url;
private $user;
private $password;
private $loged;
/**
* Ftp constructor.
* #param $url
* #param $user
* #param $password
* #throws Exception
*/
public function __construct($url, $user, $password)
{
$this->conn = ftp_connect($url);
$this->user = $user;
$this->password = $password;
if ($this->ftp_login($this->user, $this->password)) {
$this->loged = true;
} else {
$this->loged = false;
}
$this->ftp_pasv(true);
}
/**
* #param $func
* #param $a
* #return mixed
* #throws Exception
*/
public function __call($func, $a)
{
if (strstr($func, 'ftp_') !== false && function_exists($func)) {
array_unshift($a, $this->conn);
return call_user_func_array($func, $a);
} else {
if (method_exists($this, $func)) {
return call_user_func_array($func, $a);
} else {
throw new Exception('Undefine Class Function');
}
}
}
/**
* #param $local
* #param $server
* #param $verbose
* #return bool
* #throws Exception
*/
function syncFolder($local, $server, $verbose)
{
if (!$this->loged) {
return false;
}
$this->ftp_chdir($server);
$server_list = $this->ftp_nlist('.');
$local_list = scandir(BASE_PATH . $local);
foreach ($server_list as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$folder = $this->ftp_nlist($item);
if ($folder[0] == '.') {
if (!in_array($item, $local_list)) {
$this->emptyDir($server . '/' . $item, $verbose);
$this->ftp_chdir($server);
} else {
$this->syncFolder($local . '/' . $item, $server . '/' . $item, $verbose);
$this->ftp_chdir($server);
}
} else {
if (!in_array($item, $local_list)) {
if ($this->ftp_delete($item)) {
} else {
}
} else {
$stats = stat(BASE_PATH . $local . '/' . $item);
if ($this->ftp_mdtm($item) < $stats['mtime']) {
if ($this->ftp_put($item, BASE_PATH . $local . '/' . $item, FTP_BINARY)) {
} else {
}
} else {
}
}
}
}
$this->putMissingFilesFromDir($local, $server, $verbose);
$this->ftp_chdir($server);
}
/**
* #param $dir
* #param $verbose
* #return bool
* #throws Exception
*/
function emptyDir($dir, $verbose)
{
if (!$this->loged) {
return false;
}
$this->ftp_chdir($dir);
$server_list = $this->ftp_nlist('.');
foreach ($server_list as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$folder = $this->ftp_nlist($item);
if ($folder[0] == '.') {
$this->emptyDir($dir . '/' . $item, $verbose);
$this->ftp_chdir($dir);
} else {
if ($this->ftp_delete($item)) {
} else {
}
}
}
if ($this->ftp_rmdir($dir)) {
} else {
}
}
/**
* #param $local
* #param $server
* #param $verbose
* #return bool
* #throws Exception
*/
function putMissingFilesFromDir($local, $server, $verbose)
{
if (!$this->loged) {
return false;
}
$this->ftp_chdir($server);
$server_list = $this->ftp_nlist('.');
$local_list = scandir(BASE_PATH . $local);
foreach ($local_list as $item) {
if ($item == '.' || $item == '..') {
continue;
}
if (is_dir(BASE_PATH . $local . '/' . $item)) {
if (!in_array($item, $server_list)) {
$this->ftp_mkdir($item);
}
$this->putMissingFilesFromDir($local . '/' . $item, $server . '/' . $item, $verbose);
$this->ftp_chdir($server);
} else {
if (!in_array($item, $server_list)) {
if ($this->ftp_put($item, BASE_PATH . $local . '/' . $item, FTP_BINARY)) {
} else {
}
}
}
}
}
}
This script works fine from browser and from windows' CMD using this command:
C:\php5.6\php.exe -f "D:\www\project\cron\synchro_hosting.php"
But when I try to run this script from a batch file in a scheduled task the ftp_connect function doesn't do anything. It remains waiting for something.
cd /D "D:\www\project\cron\"
"C:\php5.6\php.exe" -f synchro_hosting.php
I'm using a log file to write events (now removed for summarize the code) and the code stop in ftp_connect.
Ideas?
UPDATE 1:
I tried to run the same command from CMD, batch file triggered from CMD and a batch file triggered from scheduled task, and works fine with two first options. The execution stops in ftp_connect function when is triggered from batch file in a scheduled task. The windows user that execute this actions is the same in the three cases.
C:\php5.6\php.exe -f "D:\www\project\cron\synchro_hosting.php"
I don't know where is the problem with ftp_connect from scheduled task. Is maybe a permissions issue?
There are another way in Windows to trigger an php script recurrently?
As I told to Rockstar, I have found a solution to avoid the problem, not to fix it. I tried to execute a php file directly from scheduled tasks and it worked instead of execute a bat file.
The action tab from scheduled tasks should look like this:
Action: Start a program
Program or Script: C:\php5.6\php.exe
Add arguments: "D:\www\project\cron\synchro_hosting.php"
Action Tab from Scheduled Tasks

API for dropbox login, access,upload ,delete using cakephp

I have created application in dropbox developer account.
I am using this component class for dropbox .when i trying to login i am getting this error "Please create your dropbox_token and dropbox_token_secret fields in your user model."
<?php
/**
* CAKEPHP DROPBOX COMPONENT v0.4
* Connects Cakephp to Dropbox using cURL.
*
* Copyright (C) 2010 Kyle Robinson Young
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* #author Kyle Robinson Young <kyle at kyletyoung.com>
* #copyright 2010 Kyle Robinson Young
* #license http://www.opensource.org/licenses/mit-license.php The MIT License
* #version 0.4
* #link http://www.kyletyoung.com/code/cakephp_dropbox_component
*
* SETTINGS:
* email/password: To your dropbox account
* cache: Set to name of cache config or false for no cache
*
* When in doubt, clear the cache.
*
* TODO:
* Make sync function smarter (use modified).
*
*/
class DropboxComponent extends Object
{
var $email, $password;
var $loggedin = false;
var $post, $cookie = array();
var $cache = 'default';
var $_wcache = array();
/**
* INITIALIZE
* #param class $controller
* #param array $settings
*/
function initialize(&$controller, $settings=array())
{
if (!extension_loaded('curl'))
{
trigger_error('Dropbox Component: I require the cURL extension to work.');
} // no curl
if (empty($settings['email']) || empty($settings['password']))
{
trigger_error('Dropbox Component: I need your dropbox email and password to login.');
} // email|pass empty
else
{
$this->email = $settings['email'];
$this->password = $settings['password'];
if (isset($settings['cache'])) $this->cache = $settings['cache'];
$this->login();
} // else
} // initialize
/**
* UPLOAD
* Upload a local file to a remote folder.
*
* #param $file
* #param $dir
* #return bool
*/
function upload($from=null, $to='/')
{
if (!file_exists($from)) return false;
$data = $this->request('https://www.dropbox.com/home');
$token = $this->findOnDropbox('token_upload', $data);
if ($token === false) return false;
$this->post = array(
'plain' => 'yes',
'file' => '#'.$from,
'dest' => $to,
't' => $token
);
$data = $this->request('https://dl-web.dropbox.com/upload');
if (strpos($data, 'HTTP/1.1 302 FOUND') === false) return false;
return true;
} // upload
/**
* DOWNLOAD
* Download a remote file to a local folder.
* Both from and to must be a path to a file name.
*
* #param str $from
* #param str $to
* #param str $w
* #return bool
*/
function download($from=null, $to=null, $w=null)
{
$data = $this->file($from, $w);
if (empty($data['data'])) return false;
if (!is_writable(dirname($to))) return false;
if (!$fp = fopen($to, 'w')) return false;
if (fwrite($fp, $data['data']) === false) return false;
fclose($fp);
return true;
} // download
/**
* SYNC
* Compares files from the local and remote folders
* then syncs them.
* Both local and remote must be folders.
*
* TODO:
* Currently only checks if files exists. Doesn't
* check if they are up to date which it should.
*
* #param str $local
* #param str $remote
* #return bool
*/
function sync($local=null, $remote=null)
{
if (!is_dir($local)) return false;
// GET REMOTE FILES
$remote_files = $this->files($remote);
// GET LOCAL FILES
$local_files = array();
$d = dir($local);
while (false !== ($entry = $d->read()))
{
if (substr($entry, 0, 1) == '.') continue;
if (is_dir($local.DS.$entry)) continue;
$local_files[] = $entry;
} // while
$d->close();
// DOWNLOAD FILES
$tmp = array();
foreach ($remote_files as $file)
{
if (empty($file['w'])) continue;
$tmp[] = $file['name'];
if (in_array($file['name'], $local_files)) continue;
$this->download($file['path'].$file['name'], $local.$file['name'], $file['w']);
} // foreach
// UPLOAD FILES
foreach ($local_files as $file)
{
if (in_array($file, $tmp)) continue;
$this->upload($local.$file, $remote);
} // foreach
return true;
} // sync
/**
* FILES
* Returns an array of remote files/folders
* within the given dir param.
*
* #param str $dir
* #return array
*/
function files($dir='/')
{
$dir = $this->escape($dir);
if ($this->cache === false) Cache::delete('dropbox_files_'.$dir, $this->cache);
if (($files = Cache::read('dropbox_files_'.$dir, $this->cache)) === false)
{
$files = array();
$data = $this->request('https://www.dropbox.com/browse_plain/'.$dir.'?no_js=true');
// GET FILES
$matches = $this->findOnDropbox('files', $data);
if ($matches === false) return false;
// GET TYPES
$types = $this->findOnDropbox('file_types', $data);
// GET SIZES
$sizes = $this->findOnDropbox('file_sizes', $data);
// GET MODS
$mods = $this->findOnDropbox('file_modified_dates', $data);
$i = 0;
foreach ($matches as $key => $file)
{
// IF PARENT
if (strpos($file, "Parent folder") !== false) continue;
// GET FILENAME
$found = $this->findOnDropbox('filename', $file);
if ($found === false) continue;
$found = parse_url($found);
$filename = pathinfo($found['path']);
$filename = $filename['basename'];
if (empty($filename)) continue;
// SET DEFAULTS
$path = $dir.$filename;
$type = 'unknown';
$size = 0;
$modified = 0;
// GET TYPE
if (!empty($types[$key])) $type = trim($types[$key]);
// GET SIZE
if (!empty($sizes[$key])) $size = trim($sizes[$key]);
// GET MODIFIED
if (!empty($mods[$key])) $modified = trim($mods[$key]);
// ADD TO FILES
$files[$i] = array(
'path' => urldecode($dir),
'name' => $filename,
'type' => $type,
'size' => $size,
'modified' => $modified
);
// IF FILE OR FOLDER - FILES HAVE W
$w = $this->findOnDropbox('w', $file);
if ($w !== false)
{
$files[$i]['w'] = $w;
// SAVE W FOR LATER
$this->_wcache[$dir.'/'.$filename] = $w;
} // !empty
$i++;
} // foreach
} // Cache::read
if ($this->cache !== false)
{
Cache::write('dropbox_files_'.$dir, $files, $this->cache);
} // if cache
return $files;
} // files
/**
* FILE
* Returns a remote file as an array.
*
* #param str $file
* #param str $w
* #return array
*/
function file($file=null, $w=null)
{
$file = $this->escape($file);
if ($this->cache === false) Cache::delete('dropbox_file_'.$file, $this->cache);
if (($out = Cache::read('dropbox_file_'.$file, $this->cache)) === false)
{
if (empty($w))
{
if (!empty($this->_wcache[$file])) $w = $this->_wcache[$file];
else return false;
} // empty w
$data = $this->request('https://dl-web.dropbox.com/get/'.$file.'?w='.$w);
$type = $this->findOnDropbox('content_type', $data);
$data = substr(stristr($data, "\r\n\r\n"), 4);
if (!empty($type[0])) $type = $type[0];
$out = array(
'path' => $file,
'w' => $w,
'data' => $data,
'content_type' => $type
);
if ($this->cache !== false)
{
Cache::write('dropbox_file_'.$file, $out, $this->cache);
} // if cache
} // Cache::read
return $out;
} // file
/**
* LOGIN
* to dropbox
*
* #return bool
*/
function login()
{
if (!$this->loggedin)
{
if (empty($this->email) || empty($this->password)) return false;
$data = $this->request('https://www.dropbox.com/login');
// GET TOKEN
$token = $this->findOnDropbox('token_login', $data);
if ($token === false) return false;
// LOGIN TO DROPBOX
$this->post = array(
'login_email' => $this->email,
'login_password' => $this->password,
't' => $token
);
$data = $this->request('https://www.dropbox.com/login');
// IF WERE HOME
if (stripos($data, 'location: /home') === false) return false;
$this->loggedin = true;
} // if loggedin
return true;
} // login
/**
* REQUEST
* Returns data from given url and
* saves cookies. Use $this->post and
* $this->cookie to submit params.
*
* #param str $url
* #return str
*/
function request($url=null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// IF POST
if (!empty($this->post))
{
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post);
$this->post = array();
} // !empty
// IF COOKIES
if (!empty($this->cookie))
{
$cookies = array();
foreach ($this->cookie as $key => $val)
{
$cookies[] = "$key=$val";
} // foreach
$cookies = implode(';', $cookies);
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
} // !empty
// GET DATA
$data = curl_exec($ch);
// SAVE COOKIES
$cookies = $this->findOnDropbox('cookies', $data);
if ($cookies !== false)
{
$this->cookie = array_merge($this->cookie, $cookies);
} // if cookies
curl_close($ch);
return $data;
} // request
/**
* ESCAPE
* Returns a dropbox friendly str
* for a url
*
* #param str $str
* #return str
*/
function escape($str=null)
{
return str_replace(
array('+','_','%2E','-','%2F','%3A'),
array('%20','%5F','.','%2D','/',':'),
urlencode($str)
);
} // escape
/**
* FIND ON DROPBOX
* A single function for parsing data from
* Dropbox. For easy update when/if Dropbox
* updates their html.
*
* #param str $key
* #param str $data
* #return mixed
*/
function findOnDropbox($key=null, $data=null)
{
switch (strtolower($key))
{
// FIND FILES & NAMES
case 'files':
preg_match_all('/<div.*details-filename.*>(.*?)<\/div>/i', $data, $matches);
if (!empty($matches[0])) return $matches[0];
break;
// FIND FILE TYPES
case 'file_types':
preg_match_all('/<div.*details-icon.*>(<img.*class="sprite s_(.*)".*>)<\/div>/i', $data, $matches);
if (!empty($matches[2])) return $matches[2];
break;
// FIND FILE SIZES
case 'file_sizes':
preg_match_all('/<div.*details-size.*>(.*)<\/div>/i', $data, $matches);
if (!empty($matches[1])) return $matches[1];
break;
// FIND FILE MODIFIED DATES
case 'file_modified_dates':
preg_match_all('/<div.*details-modified.*>(.*)<\/div>/i', $data, $matches);
if (!empty($matches[1])) return $matches[1];
break;
// FIND FILE NAME
case 'filename':
preg_match('/href=[("|\')]([^("|\')]+)/i', $data, $match);
if (!empty($match[1])) return $match[1];
break;
// FIND W
case 'w':
preg_match('/\?w=(.[^"]*)/i', $data, $match);
if (!empty($match[1])) return $match[1];
break;
// FIND CONTENT TYPE
case 'content_type':
preg_match('/Content-Type: .+\/.+/i', $data, $type);
if (!empty($type)) return $type;
break;
// FIND COOKIES
case 'cookies':
preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches);
$return = array();
foreach ($matches[1] as $key => $val)
{
$return[(string)$val] = $matches[2][$key];
} // foreach
if (!empty($return)) return $return;
break;
// FIND LOGIN FORM TOKEN
case 'token_login':
preg_match('/<form [^>]*\/login[^>]*>.*?<\/form>/si', $data, $match);
if (!empty($match[0]))
{
preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
if (!empty($match[1])) return $match[1];
} // !empty
break;
// FIND UPLOAD FORM TOKEN
case 'token_upload':
preg_match('/<form [^>]*https\:\/\/dl-web\.dropbox\.com\/upload[^>]*>.*?<\/form>/si', $data, $match);
if (!empty($match[0]))
{
preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
if (!empty($match[1])) return $match[1];
} // !empty
break;
} // switch
return false;
} // findOnDropbox
} // DropboxComponent
?>
Controller code
class DropboxWebserverController extends AppController
{
var $name = 'DropboxWebserver';
var $uses = array();
var $autoRender = false;
var $components = array('Dropbox' => array(
'email' => 'email#gmail.com',
'password' => 'password',
//'cache' => false
));
var $root_folder = '/';
var $default_home = array('index.html', 'index.htm', 'index.php');
/**
* INDEX
*/
function index()
{
$args = func_get_args();
$args = implode('/', $args);
$path = pathinfo($args);
if ($path['dirname'] == ".")
{
$folder = $path['basename'];
$file = '';
} // dirname == .
else
{
$folder = $path['dirname'];
$file = $path['basename'];
} // else
$files = $this->Dropbox->files($this->root_folder.$folder);
//debug($files);
// FIND FILE
foreach ($files as $f)
{
if (strpos($f['type'], 'folder') !== false) continue;
if (empty($f['name'])) continue;
if ($f['name'] == $file)
{
$file = $this->Dropbox->file($this->root_folder.$folder.'/'.$file, $f['w']);
$output = $file['data'];
$content_type = $file['content_type'];
break;
} // name == file
// FIND DEFAULT HOME
if (in_array($f['name'], $this->default_home))
{
$default = $f;
} // in_array
} // foreach
if (!empty($output))
{
header('Content-Type: '.$content_type);
echo $output;
} // !empty
elseif (!empty($default))
{
$file = $this->Dropbox->file($this->root_folder.$folder.'/'.$default['name'], $default['w']);
header('Content-Type: '.$file['content_type']);
echo $file['data'];
} // !empty default
else
{
echo 'Error 404: File Not Found';
} // else
} // index
}
How to login and access drop box account using cakephp

Vqmod improve error logging, by adding the parent file name the error is referring too

A default error logging using vqmod is as follows:
---------- Date: 2012-10-09 19:46:06 ~ IP : 127.0.0.1 ----------
REQUEST URI : /oc/
MOD DETAILS:
modFile : C:\wamp\www\oc\vqmod\xml\templace.xml
id : Template
version : 1.5.2 - 1.5.2.1
vqmver : 1.0.8
author : templace.com
SEARCH NOT FOUND (ABORTING MOD): require_once(foo . 'library/template.php');
----------------------------------------------------------------------
Example vqmod causing the error
<modification>
<id>Templace</id>
<version>1.5.2 - 1.5.2.1</version>
<author>templace.com</author>
<vqmver>1.0.8</vqmver>
<file name="system/startup.php">
<operation>
<search position="before"><![CDATA[
require_once(foo . 'library/template.php');
]]></search>
<add><![CDATA[
require_once(DIR_SYSTEM . 'library/templace.php');
]]></add>
</operation>
</file>
</modification>
To resole this issue I would have to open the vqmod file templace.xml and search for the file[name] this error is referring too.
QUESTION: How could I add the parent file[name] the actual error is referring too?
E.g adding: "system/startup.php" to the error message to make it easier to debug.
vqmod.php
/**
* VQMod
* #description Main Object used
*/
final class VQMod {
private $_vqversion = '2.1.7';
private $_modFileList = array();
private $_mods = array();
private $_filesModded = array();
private $_cwd = '';
private $_doNotMod = array();
private $_virtualMode = true;
public $useCache = false;
public $logFilePath = 'vqmod/vqmod.log';
public $vqCachePath = 'vqmod/vqcache/';
public $protectedFilelist = 'vqmod/vqprotect.txt';
public $logging = true;
public $cacheTime = 5; // local=5secs live=60secs
public $log;
/**
* VQMod::__construct()
*
* #param bool $path File path to use
* #param bool $logging Enable/disabled logging
* #return null
* #description Startup of VQMod
*/
public function __construct($path = false, $logging = true) {
if(!class_exists('DOMDocument')) {
die('ERROR - YOU NEED DOMDocument INSTALLED TO USE VQMod');
}
if(!$path){
$path = dirname(dirname(__FILE__));
}
$this->_setCwd($path);
$this->logging = (bool) $logging;
$this->log = new VQModLog($this);
$this->_getMods();
$this->_loadProtected();
}
/**
* VQMod::modCheck()
*
* #param string $sourceFile path for file
* #return string
* #description Checks if a file has modifications and applies them, returning cache files or the file name
*/
public function modCheck($sourceFile) {
if(!preg_match('%^([a-z]:)?[\\\\/]%i', $sourceFile)) {
$sourcePath = $this->path($sourceFile);
} else {
$sourcePath = realpath($sourceFile);
}
if(!$sourcePath || is_dir($sourcePath) || in_array($sourcePath, $this->_doNotMod)) {
return $sourceFile;
}
$stripped_filename = preg_replace('~^' . preg_quote($this->getCwd(), '~') . '~', '', $sourcePath);
$cacheFile = $this->_cacheName($stripped_filename);
if($this->useCache && file_exists($cacheFile)) {
//return $cacheFile; // useCache being Deprecated in favor of cacheTime
}
if(isset($this->_filesModded[$sourcePath])) {
return $this->_filesModded[$sourcePath]['cached'] ? $cacheFile : $sourceFile;
}
$changed = false;
$fileHash = sha1_file($sourcePath);
$fileData = file_get_contents($sourcePath);
foreach($this->_mods as $modObject) {
foreach($modObject->mods as $path => $mods) {
if($this->_checkMatch($path, $sourcePath)) {
$modObject->applyMod($mods, $fileData);
}
}
}
// START QPHORIA CACHELOCK CODE
//
if (sha1($fileData) != $fileHash) {
$writePath = $cacheFile;
$cacheLock = false;
if(file_exists($writePath) && ((filemtime($writePath) + (float)$this->cacheTime) >= time())) {
$cacheLock = true;
$changed = true;
}
if(!$cacheLock && (!file_exists($writePath) || is_writable($writePath))) {
file_put_contents($writePath, $fileData);
$changed = true;
} else {
//file_put_contents('./cachelock.txt', "$writePath \r\n", FILE_APPEND); // debugging only.
}
//file_put_contents('./cachetotal.txt', "$writePath \r\n", FILE_APPEND);
} // END QPHORIA CACHELOCK CODE
/* Original Code
if(sha1($fileData) != $fileHash) {
$writePath = $this->_virtualMode ? $cacheFile : $sourcePath;
if(!file_exists($writePath) || is_writable($writePath)) {
file_put_contents($writePath, $fileData);
$changed = true;
}
}*/
$this->_filesModded[$sourcePath] = array('cached' => $changed);
return $changed ? $writePath : $sourcePath;
}
/**
* VQMod::path()
*
* #param string $path File path
* #param bool $skip_real If true path is full not relative
* #return bool, string
* #description Returns the full true path of a file if it exists, otherwise false
*/
public function path($path, $skip_real = false) {
$tmp = $this->_cwd . $path;
$realpath = $skip_real ? $tmp : realpath($tmp);
if(!$realpath) {
return false;
}
if(is_dir($realpath)) {
$realpath = rtrim($realpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
return $realpath;
}
/**
* VQMod::getCwd()
*
* #return string
* #description Returns current working directory
*/
public function getCwd() {
return $this->_cwd;
}
/**
* VQMod::_getMods()
*
* #return null
* #description Gets list of XML files in vqmod xml folder for processing
*/
private function _getMods() {
$this->_modFileList = glob($this->path('vqmod/xml/') . '*.xml');
if($this->_modFileList) {
$this->_parseMods();
} else {
$this->log->write('NO MODS IN USE');
}
}
/**
* VQMod::_parseMods()
*
* #return null
* #description Loops through xml files and attempts to load them as VQModObject's
*/
private function _parseMods() {
$dom = new DOMDocument('1.0', 'UTF-8');
foreach($this->_modFileList as $modFileKey => $modFile) {
if(file_exists($modFile)) {
if(#$dom->load($modFile)) {
$mod = $dom->getElementsByTagName('modification')->item(0);
$this->_mods[] = new VQModObject($mod, $modFile, $this);
} else {
$this->log->write('DOM UNABLE TO LOAD: ' . $modFile);
}
} else {
$this->log->write('FILE NOT FOUND: ' . $modFile);
}
}
}
/**
* VQMod::_loadProtected()
*
* #return null
* #description Loads protected list and adds them to _doNotMod array
*/
private function _loadProtected() {
$file = $this->path($this->protectedFilelist);
if($file && is_file($file)) {
$protected = file_get_contents($file);
if(!empty($protected)) {
$protected = preg_replace('~\r?\n~', "\n", $protected);
$paths = explode("\n", $protected);
foreach($paths as $path) {
$fullPath = $this->path($path);
if($fullPath && !in_array($fullPath, $this->_doNotMod)) {
$this->_doNotMod[] = $fullPath;
}
}
}
}
}
/**
* VQMod::_cacheName()
*
* #param string $file Filename to be converted to cache filename
* #return string
* #description Returns cache file name for a path
*/
private function _cacheName($file) {
return $this->path($this->vqCachePath) . 'vq2-' . preg_replace('~[/\\\\]+~', '_', $file);
}
/**
* VQMod::_setCwd()
*
* #param string $path Path to be used as current working directory
* #return null
* #description Sets the current working directory variable
*/
private function _setCwd($path) {
$realpath = realpath($path);
if(!$realpath) {
die('COULDNT RESOLVE CWD REALPATH');
}
$this->_cwd = rtrim($realpath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
/**
* VQMod::_checkMatch()
*
* #param string $modFilePath Modification path from a <file> node
* #param string $checkFilePath File path
* #return bool
* #description Checks a modification path against a file path
*/
private function _checkMatch($modFilePath, $checkFilePath) {
$modFilePath = str_replace('\\', '/', $modFilePath);
$checkFilePath = str_replace('\\', '/', $checkFilePath);
$modFilePath = preg_replace('/([^*]+)/e', 'preg_quote("$1", "~")', $modFilePath);
$modFilePath = str_replace('*', '[^/]*', $modFilePath);
$return = (bool) preg_match('~^' . $modFilePath . '$~', $checkFilePath);
return $return;
}
}
/**
* VQModLog
* #description Object to log information to a file
*/
class VQModLog {
private $_sep;
private $_vqmod;
private $_defhash = 'da39a3ee5e6b4b0d3255bfef95601890afd80709';
private $_logs = array();
/**
* VQModLog::__construct()
*
* #param VQMod $vqmod VQMod main class as reference
* #return null
* #description Object instantiation method
*/
public function __construct(VQMod $vqmod) {
$this->_vqmod = $vqmod;
$this->_sep = str_repeat('-', 70);
}
/**
* VQModLog::__destruct()
*
* #return null
* #description Logs any messages to the log file just before object is destroyed
*/
public function __destruct() {
if(empty($this->_logs) || $this->_vqmod->logging == false) {
return;
}
$txt = array();
$txt[] = str_repeat('-', 10) . ' Date: ' . date('Y-m-d H:i:s') . ' ~ IP : ' . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'N/A') . ' ' . str_repeat('-', 10);
$txt[] = 'REQUEST URI : ' . $_SERVER['REQUEST_URI'];
foreach($this->_logs as $count => $log) {
if($log['obj']) {
$vars = get_object_vars($log['obj']);
$txt[] = 'MOD DETAILS:';
foreach($vars as $k => $v) {
if(is_string($v)) {
$txt[] = ' ' . str_pad($k, 10, ' ', STR_PAD_RIGHT) . ': ' . $v;
}
}
}
foreach($log['log'] as $msg) {
$txt[] = $msg;
}
if ($count > count($this->_logs)-1) {
$txt[] = '';
}
}
$txt[] = $this->_sep;
$txt[] = str_repeat(PHP_EOL, 2);
$logPath = $this->_vqmod->path($this->_vqmod->logFilePath, true);
if(!file_exists($logPath)) {
$res = file_put_contents($logPath, '');
if($res === false) {
die('COULD NOT WRITE TO LOG FILE');
}
}
file_put_contents($logPath, implode(PHP_EOL, $txt), FILE_APPEND);
}
/**
* VQModLog::write()
*
* #param string $data Text to be added to log file
* #param VQModObject $obj Modification the error belongs to
* #return null
* #description Adds error to log object ready to be output
*/
public function write($data, VQModObject $obj = NULL) {
if($obj) {
$hash = sha1($obj->id);
} else {
$hash = $this->_defhash;
}
if(empty($this->_logs[$hash])) {
$this->_logs[$hash] = array(
'obj' => $obj,
'log' => array()
);
}
$this->_logs[$hash]['log'][] = $data;
}
}
/**
* VQModObject
* #description Object for the <modification> that orchestrates each applied modification
*/
class VQModObject {
public $modFile = '';
public $id = '';
public $version = '';
public $vqmver = '';
public $author = '';
public $mods = array();
private $_vqmod;
private $_skip = false;
/**
* VQModObject::__construct()
*
* #param DOMNode $node <modification> node
* #param string $modFile File modification is from
* #param VQMod $vqmod VQMod object as reference
* #return null
* #description Loads modification meta information
*/
public function __construct(DOMNode $node, $modFile, VQmod $vqmod) {
if($node->hasChildNodes()) {
foreach($node->childNodes as $child) {
$name = (string) $child->nodeName;
if(isset($this->$name)) {
$this->$name = (string) $child->nodeValue;
}
}
}
$this->modFile = $modFile;
$this->_vqmod = $vqmod;
$this->_parseMods($node);
}
/**
* VQModObject::skip()
*
* #return bool
* #description Returns the skip status of a modification
*/
public function skip() {
return $this->_skip;
}
/**
* VQModObject::applyMod()
*
* #param array $mods Array of search add nodes
* #param string $data File contents to be altered
* #return null
* #description Applies all modifications to the text data
*/
public function applyMod($mods, &$data) {
if($this->_skip) return;
$tmp = $data;
foreach($mods as $mod) {
$indexCount = 0;
$tmp = $this->_explodeData($tmp);
$lineMax = count($tmp) - 1;
switch($mod['search']->position) {
case 'top':
$tmp[$mod['search']->offset] = $mod['add']->getContent() . $tmp[$mod['search']->offset];
break;
case 'bottom':
$offset = $lineMax - $mod['search']->offset;
if($offset < 0){
$tmp[-1] = $mod['add']->getContent();
} else {
$tmp[$offset] .= $mod['add']->getContent();
}
break;
case 'all':
$tmp = array($mod['add']->getContent());
break;
default:
$changed = false;
foreach($tmp as $lineNum => $line) {
if($mod['search']->regex == 'true') {
$pos = #preg_match($mod['search']->getContent(), $line);
if($pos === false) {
if($mod['error'] == 'log' || $mod['error'] == 'abort' ) {
$this->_vqmod->log->write('INVALID REGEX ERROR - ' . $mod['search']->getContent(), $this);
}
continue 2;
} elseif($pos == 0) {
$pos = false;
}
} else {
$pos = strpos($line, $mod['search']->getContent());
}
if($pos !== false) {
$indexCount++;
$changed = true;
if(!$mod['search']->indexes() || ($mod['search']->indexes() && in_array($indexCount, $mod['search']->indexes()))) {
switch($mod['search']->position) {
case 'before':
$offset = ($lineNum - $mod['search']->offset < 0) ? -1 : $lineNum - $mod['search']->offset;
$tmp[$offset] = empty($tmp[$offset]) ? $mod['add']->getContent() : $mod['add']->getContent() . "\n" . $tmp[$offset];
break;
case 'after':
$offset = ($lineNum + $mod['search']->offset > $lineMax) ? $lineMax : $lineNum + $mod['search']->offset;
$tmp[$offset] = $tmp[$offset] . "\n" . $mod['add']->getContent();
break;
default:
if(!empty($mod['search']->offset)) {
for($i = 1; $i <= $mod['search']->offset; $i++) {
if(isset($tmp[$lineNum + $i])) {
$tmp[$lineNum + $i] = '';
}
}
}
if($mod['search']->regex == 'true') {
$tmp[$lineNum] = preg_replace($mod['search']->getContent(), $mod['add']->getContent(), $line);
} else {
$tmp[$lineNum] = str_replace($mod['search']->getContent(), $mod['add']->getContent(), $line);
}
break;
}
}
}
}
if(!$changed) {
$skip = ($mod['error'] == 'skip' || $mod['error'] == 'log') ? ' (SKIPPED)' : ' (ABORTING MOD)';
if($mod['error'] == 'log' || $mod['error'] == 'abort') {
$this->_vqmod->log->write('SEARCH NOT FOUND' . $skip . ': ' . $mod['search']->getContent(), $this);
}
if($mod['error'] == 'abort') {
$this->_skip = true;
return;
}
}
break;
}
ksort($tmp);
$tmp = $this->_implodeData($tmp);
}
$data = $tmp;
}
/**
* VQModObject::_parseMods()
*
* #param DOMNode $node <modification> node to be parsed
* #return null
* #description Parses modifications in preparation for the applyMod method to work
*/
private function _parseMods(DOMNode $node){
$files = $node->getElementsByTagName('file');
foreach($files as $file) {
$fileToMod = $file->getAttribute('name');
$error = ($file->hasAttribute('error')) ? $file->getAttribute('error') : 'log';
$fullPath = $this->_vqmod->path($fileToMod);
if(!$fullPath){
if(strpos($fileToMod, '*') !== false) {
$fullPath = $this->_vqmod->getCwd() . $fileToMod;
} else {
if ($error == 'log' || $error == 'abort') {
$skip = ($error == 'log') ? ' (SKIPPED)' : ' (ABORTING MOD)';
$this->_vqmod->log->write('Could not resolve path for [' . $fileToMod . ']' . $skip, $this);
}
if ($error == 'log' || $error == 'skip') {
continue;
} elseif ($error == 'abort') {
return false;
}
}
}
$operations = $file->getElementsByTagName('operation');
foreach($operations as $operation) {
$error = ($operation->hasAttribute('error')) ? $operation->getAttribute('error') : 'abort';
$this->mods[$fullPath][] = array(
'search' => new VQSearchNode($operation->getElementsByTagName('search')->item(0)),
'add' => new VQAddNode($operation->getElementsByTagName('add')->item(0)),
'error' => $error
);
}
}
}
/**
* VQModObject::_explodeData()
*
* #param string $data File contents
* #return string
* #description Splits a file into an array of individual lines
*/
private function _explodeData($data) {
return explode("\n", $data);
}
/**
* VQModObject::_implodeData()
*
* #param array $data Array of lines
* #return string
* #description Joins an array of lines back into a text file
*/
private function _implodeData($data) {
return implode("\n", $data);
}
}
/**
* VQNode
* #description Basic node object blueprint
*/
class VQNode {
public $trim = 'false';
private $_content = '';
/**
* VQNode::__construct()
*
* #param DOMNode $node Search/add node
* #return null
* #description Parses the node attributes and sets the node property
*/
public function __construct(DOMNode $node) {
$this->_content = $node->nodeValue;
if($node->hasAttributes()) {
foreach($node->attributes as $attr) {
$name = $attr->nodeName;
if(isset($this->$name)) {
$this->$name = $attr->nodeValue;
}
}
}
}
/**
* VQNode::getContent()
*
* #return string
* #description Returns the content, trimmed if applicable
*/
public function getContent() {
$content = ($this->trim == 'true') ? trim($this->_content) : $this->_content;
return $content;
}
}
/**
* VQSearchNode
* #description Object for the <search> xml tags
*/
class VQSearchNode extends VQNode {
public $position = 'replace';
public $offset = 0;
public $index = 'false';
public $regex = 'false';
public $trim = 'true';
/**
* VQSearchNode::indexes()
*
* #return bool, array
* #description Returns the index values to use the search on, or false if none
*/
public function indexes() {
if($this->index == 'false') {
return false;
}
$tmp = explode(',', $this->index);
foreach($tmp as $k => $v) {
if(!is_int($v)) {
unset($k);
}
}
$tmp = array_unique($tmp);
return empty($tmp) ? false : $tmp;
}
}
/**
* VQAddNode
* #description Object for the <add> xml tags
*/
class VQAddNode extends VQNode {
}
Also couple of other ideas to make debugging even easier:
List any other vqmod files which have previously edited this same file.
This is another common issue where I find when two extensions are editing the same file and the latter is causing the error but it would be useful to know about any other vqmods editing the same file. Yes I suppose I could add error="skip" to everything but dont think this is the best approach to just hide all of the errors, the user should be made aware there is an error...
"Suggested Fix", maybe some smart way you can test what type of error it is.
Contradict what I said above but even at its most basic form you could suggest hiding the error if its not essential. So that anybody can read it and understand how it fix it.
E.g
OPEN: vqmod/xml/templace.xml (line:23)
FIND: <operation>
REPLACE <operation error="skip">
Adding the line number in the XML file the error is coming from. It would be lovely not having to search all of the time and could quickly go to the line number in the vqmod
The issue for the file being edited is certainly one that is way overdue and one I plan on adding in the next release of vQmod. As for the other suggestions
Interesting idea, and one that could certainly be considered. The only problem I see with this is that it would possibly make some log files enormous
This is going to be next to impossible to incorporate
This is impossible without some pretty expensive runtime. The error doesn't lie in the XML as such, so would require re-opening the xml that's been parsed, searching for the line in question line by line and then reporting that. it sounds simple, but you have to remember that xml's can have the same search parameter for multiple operations - so in that situation you'd be no better off than searching the file yourself

Pass MySQL Variable to Joomla Module instead of using default field for Twitter Search

It seems I've hit a wall here and could use some help
Would like to pass a MySql variable to a Joomla Module
Im using Yootheme's Widget-kit to display tweets from a search term. Works great and all but you need to enter the twitter search term in the Module back end.
Instead I would like to use a variable ( already used on the page) and pass that variable to the Twitter module so it can display the tweets I want
Here are some lines of PHP with the variable I'd like to use
$document->setTitle(JText::sprintf('COVERAGE_DATA_PLACE', $this->country->country_name, $this->city->city_name));
$text = JString::str_ireplace('%city_name%',$this->city->city_name,$text);
$this->setBreadcrumbs(array('country','city'));
Is there any way to take the "City" variable and send it to the 'word" field found in the twitter module?
Here is the Code for the twitter module
<?php
Class: TwitterWidgetkitHelper
Twitter helper class
*/
class TwitterWidgetkitHelper extends WidgetkitHelper {
/* type */
public $type;
/* options */
public $options;
/*
Function: Constructor
Class Constructor.
*/
public function __construct($widgetkit) {
parent::__construct($widgetkit);
// init vars
$this->type = strtolower(str_replace('WidgetkitHelper', '', get_class($this)));
$this->options = $this['system']->options;
// create cache
$cache = $this['path']->path('cache:');
if ($cache && !file_exists($cache.'/twitter')) {
mkdir($cache.'/twitter', 0777, true);
}
// register path
$this['path']->register(dirname(__FILE__), $this->type);
}
/*
Function: site
Site init actions
Returns:
Void
*/
public function site() {
// add translations
foreach (array('LESS_THAN_A_MINUTE_AGO', 'ABOUT_A_MINUTE_AGO', 'X_MINUTES_AGO', 'ABOUT_AN_HOUR_AGO', 'X_HOURS_AGO', 'ONE_DAY_AGO', 'X_DAYS_AGO') as $key) {
$translations[$key] = $this['system']->__($key);
}
// add stylesheets/javascripts
$this['asset']->addFile('css', 'twitter:styles/style.css');
$this['asset']->addFile('js', 'twitter:twitter.js');
$this['asset']->addString('js', sprintf('jQuery.trans.addDic(%s);', json_encode($translations)));
// rtl
if ($this['system']->options->get('direction') == 'rtl') {
$this['asset']->addFile('css', 'twitter:styles/rtl.css');
}
}
/*
Function: render
Render widget on site
Returns:
String
*/
public function render($options) {
if ($tweets = $this->_getTweets($options)) {
// get options
extract($options);
return $this['template']->render("twitter:styles/$style/template", compact('tweets', 'show_image', 'show_author', 'show_date', 'image_size'));
}
return 'No tweets found.';
}
/*
Function: _getURL
Create Twitter Query URL
Returns:
String
*/
protected function _getURL($options) {
// get options
extract($options);
// clean options
foreach (array('from_user', 'to_user', 'ref_user', 'word', 'nots', 'hashtag') as $var) {
$$var = preg_replace('/[##]/', '', preg_replace('/\s+/', ' ', trim($$var)));
}
// build query
$query = array();
if ($from_user) {
$query[] = 'from:'.str_replace(' ', ' OR from:', $from_user);
}
if ($to_user) {
$query[] = 'to:'.str_replace(' ', ' OR to:', $to_user);
}
if ($ref_user) {
$query[] = '#'.str_replace(' ', ' #', $ref_user);
}
if ($word) {
$query[] = $word;
}
if ($nots) {
$query[] = '-'.str_replace(' ', ' -', $nots);
}
if ($hashtag) {
$query[] = '#'.str_replace(' ', ' #', $hashtag);
}
$limit = min($limit ? intval($limit) : 5, 100);
// build timeline url
if ($from_user && !strpos($from_user, ' ') && count($query) == 1) {
$url = 'http://twitter.com/statuses/user_timeline/'.strtolower($from_user).'.json';
if ($limit > 15) {
$url .= '?count='.$limit;
}
return $url;
}
// build search url
if (count($query)) {
$url = 'http://search.twitter.com/search.json?q='.urlencode(implode(' ', $query));
if ($limit > 15) {
$url .= '&rpp='.$limit;
}
return $url;
}
return null;
}
/*
Function: _getTweets
Get Tweet Object Array
Returns:
Array
*/
protected function _getTweets($options) {
// init vars
$tweets = array();
// query twitter
if ($url = $this->_getURL($options)) {
if ($path = $this['path']->path('cache:twitter')) {
$file = rtrim($path, '/').sprintf('/twitter-%s.php', md5($url));
// is cached ?
if (file_exists($file)) {
$response = file_get_contents($file);
}
// refresh cache ?
if (!file_exists($file) || (time() - filemtime($file)) > 300) {
// send query
$request = $this['http']->get($url);
if (isset($request['status']['code']) && $request['status']['code'] == 200) {
$response = $request['body'];
file_put_contents($file, $response);
}
}
}
}
// create tweets
if (isset($response)) {
$response = json_decode($response, true);
if (is_array($response)) {
if (isset($response['results'])) {
foreach ($response['results'] as $res) {
$tweet = new WidgetkitTweet();
$tweet->user = $res['from_user'];
$tweet->name = $res['from_user'];
$tweet->image = $res['profile_image_url'];
$tweet->text = $res['text'];
$tweet->created_at = $res['created_at'];
$tweets[] = $tweet;
}
} else {
foreach ($response as $res) {
$tweet = new WidgetkitTweet();
$tweet->user = $res['user']['screen_name'];
$tweet->name = $res['user']['name'];
$tweet->image = $res['user']['profile_image_url'];
$tweet->text = $res['text'];
$tweet->created_at = $res['created_at'];
$tweets[] = $tweet;
}
}
}
}
return array_slice($tweets, 0, $options['limit'] ? intval($options['limit']) : 5);
}
}
class WidgetkitTweet {
public $user;
public $name;
public $image;
public $text;
public $created_at;
public function getLink() {
return 'http://twitter.com/'.$this->user;
}
public function getText() {
// format text
$text = preg_replace('#(https?://([-\w\.]+)+(/([\w/_\.]*(\?\S+)?(#\S+)?)?)?)#', '$1', $this->text);
$text = preg_replace('/#(\w+)/', '#$1', $text);
$text = preg_replace('/\s+#(\w+)/', ' #$1', $text);
return $text;
}
}
// bind events
$widgetkit = Widgetkit::getInstance();
$widgetkit['event']->bind('site', array($widgetkit['twitter'], 'site'));
I believe you can do what you want with this:
http://www.j-plant.com/joomla-extensions/free-extensions/26-module-plant.html
This plugin supports module parameters overriding. Use the next code
for overriding parameters:
[moduleplant id="77" <param_name_1>="<param_value_1>" <param_name_N>="<param_value_N>"]
replace and with the necessary parameter name and value.
You can override as many parameters as you want.
Available module parameters can be found in module XML manifest
file. A manifest file is usually located in the next path:
modules/<module_type>/<module_type>.xml

Categories