I build a function that if you give it an array of paths it will look for a file in each path and if you give it an array of one path it will look in that path only for the file.
My questions, is when you give it an array of paths such as:
$array = array(
'template_view_paths' => array(
'path_name' => some/path/
'path_name_two' => some/path/two/
)
)
It seems to find the file in some/path/ but keeps going on to some/path/two/ and freaks out because the file doesn't exist. What would I have to change so that if it find the file in any path that it stops looking in other paths?
The code - NOT re-factored
public function render_view($template_name){
if(!isset($this->_options['template_view_path'])){
throw new AisisCore_Template_TemplateException('Not view path was set.');
}
if(is_array($this->_options['template_view_path'])){
foreach($this->_options['template_view_path'] as $template=>$path){
require_once($path . $template_name . '.phtml');
}
}else{
if(!file_exists($this->_options['template_view_path'] . $template_name . '.phtml')){
throw new AisisCore_Template_TemplateException('Could not find: ' . $template_name . '.phtml at ' . $path);
}
require_once ($this->_options['template_view_path'] . $template_name . '.phtml');
}
}
Note: the part to focus on is the if(is_array()){} loop.
Shouldn't:
if(is_array($this->_options['template_view_path'])){
foreach($templates as $template=>$path){
require_once($path . $template_name . '.phtml');
}
}else{
be:
if(is_array($this->_options['template_view_path'])){
foreach($this->_options['template_view_path'] as $template=>$path){
if (file_exists($filename = $path . $template_name . '.phtml')) {
require_once($filename);
return;
}
}
throw new AisisCore_Template_TemplateException('Could not find: ' . $template_name . '.phtml in any paths');
}else{
You're never actually looping $this->_options['template_view_path'].
Related
zipping some directory on the server I receive extra folder inside zip-archive under Windows and Linux.
Extra folder "3b84" is the ending of using md5(integer) function to set filename inside getExportPaths() method. If I try to make filename shorter - it makes me a zip archive where all files placed in one directory without their subdirectories like "CSS", "fonts" etc.
And one important thing why I'm using md5() - I need to paste into one directory a lot of zip archives. So their name should be unique.
How to fix this and remove such extra folder with a name like "3b84"?
public function actionExportdocument($id)
{
$model = Order::findOne(['id' => $id, 'user_id' => Yii::$app->user->getId()]);
if (!$model) {
throw new BadRequestHttpException('Export not found.');
}
$paths = Order::getExportPaths($model->id, $model->design->path);
$prepareFiles = Order::prepareFiles($paths, $model);
$zip = new ZipArchive();
$zip->open($paths['exportRoot'] . DIRECTORY_SEPARATOR . $paths['exportFile'],
ZipArchive::CREATE | ZipArchive::OVERWRITE);
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($paths['exportPath']),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $name => $file)
{
// Skip directories (they would be added automatically)
if (!$file->isDir())
{
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($paths['designPath']) + 1);
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
FileHelper::sendFile($paths['exportRoot'] . DIRECTORY_SEPARATOR . $paths['exportFile'], 'script.zip');
}
Order class contains:
public static function getExportPaths($modelId, $designPath)
{
$paths['orderIdHash'] = md5($modelId);
$paths['designPath'] = \Yii::getAlias('#app') . DIRECTORY_SEPARATOR . 'designs' . DIRECTORY_SEPARATOR . $designPath;
$paths['exportRoot'] = \Yii::getAlias('#webroot') . DIRECTORY_SEPARATOR . 'export-document';
$paths['exportPath'] = $paths['exportRoot'] . DIRECTORY_SEPARATOR . $paths['orderIdHash'];
$paths['exportFile'] = $paths['orderIdHash'] . '.zip';
return $paths;
}
public static function prepareFiles($paths, $model)
{
$exportDir = \Yii::getAlias('#webroot') . DIRECTORY_SEPARATOR . 'export-document';
if (!is_dir($exportDir)) {
mkdir($exportDir);
}
FileHelper::deleteDirectory($paths['exportPath']);
FileHelper::copyRecursive($paths['designPath'], $paths['exportPath']);
$content = '';
foreach ($model->orderTemplates as $template) {
$content .= $template->value;
}
$str = file_get_contents($paths['exportPath'] . DIRECTORY_SEPARATOR . 'index.html');
$str = str_replace("{{CONTENT}}", $content, $str);
file_put_contents($paths['exportPath'] . DIRECTORY_SEPARATOR . 'index.html', $str);
}
If I've read your question correctly; you wish to remove folders like /3b84/ from being generated.
Look inside your Order class:
public static function getExportPaths($modelId, $designPath)
{
$paths['orderIdHash'] = md5($modelId);
$paths['designPath'] = \Yii::getAlias('#app') . DIRECTORY_SEPARATOR . 'designs' . DIRECTORY_SEPARATOR . $designPath;
$paths['exportRoot'] = \Yii::getAlias('#webroot') . DIRECTORY_SEPARATOR . 'export-document';
$paths['exportPath'] = $paths['exportRoot'] . DIRECTORY_SEPARATOR . $paths['orderIdHash'];
$paths['exportFile'] = $paths['orderIdHash'] . '.zip';
return $paths;
}
See $paths['exportPath'] = $paths['exportRoot'] . DIRECTORY_SEPARATOR . $paths['orderIdHash']; ?
Remove that and you your new path will no longer have folders like /3b84/.
The problem was that I've specified wrong $relativePath.
This string was incorrect
$relativePath = substr($filePath, strlen($paths['designPath']) + 1);
And instead of it
$relativePath = substr($filePath, strlen($paths['exportPath']) + 1);
I am trying to create a zip file with folders inside it.
Now the code is :
{
$zipper = new \Chumper\Zipper\Zipper;
$zipper->make(storage_path('app/' . $zipPath));
.
.
Storage::makeDirectory($zipPath . DIRECTORY_SEPARATOR . $user->username , 0777);
$zipper->folder($zipPath . DIRECTORY_SEPARATOR . $user->username);
$currentZipPath = $zipPath . DIRECTORY_SEPARATOR . $user->username;
Storage::makeDirectory($currentZipPath . DIRECTORY_SEPARATOR . $myfolder->name , 0777);
$zipper->folder($currentZipPath . DIRECTORY_SEPARATOR . $myfolder->name);
.
.
$this->addDataToZip($contents, $currentZipPath . DIRECTORY_SEPARATOR . $myfolder->name, $zipper, $user);
Log::info('Zip status : ' . $zipper->getStatus()); //Gives "No error"
$zipper->close();
}
public function addDataToZip($contents, $path, &$zipper, $user)
{
foreach ($contents as $content) {
$filebasepath = storage_path('app/' . $path);
Storage::copy(
$this->model->getActiveStorageBasePath($user)
. DIRECTORY_SEPARATOR . $content->unique_name,
$path . DIRECTORY_SEPARATOR . $content->unique_name
);
$zipper->add(storage_path() . DIRECTORY_SEPARATOR . 'app'
. DIRECTORY_SEPARATOR . $path
. DIRECTORY_SEPARATOR . $content->unique_name);
}
}
Now when I view the folder locally, the entie admin.zip folder is created with complete heirarchy and content.
But on $zipper->close, the zip file is not created and the admin.zip folder remains there.
Also there is no error in the API call or the logs.
Please guide on where I might be making an error
See with example Chumper/Zipper. This is the simple and straightforward way to use.
OR you can place this line "status ::". $zipper->status . "\n" after $zipper->add() to check status.
Right so i'm making a configuration class that will use an array of different file types in 4 main locations. Now I want to make it so that the configuration class will search these locations in order at the moment i'm using the following
if (file_exists(ROOT . DS . 'Application/Config/' . APP_ENV . DS . $file)) {
$this->filePath = ROOT . DS . 'Application/Config/' . APP_ENV . DS . $file;
echo $this->filePath;
} else {
if (file_exists(ROOT . DS . "Application/Config/$file")) {
$this->filePath = ROOT . DS . "Application/Config/$file";
echo $this->filePath;
} else {
if (file_exists(CARBON_PATH . 'Config' . DS . APP_ENV . DS . $file)) {
$this->filePath = CARBON_PATH . 'Config' . DS . APP_ENV . DS . $file;
echo $this->filePath;
} else {
if (file_exists(CARBON_PATH . "Config/$file")) {
$this->filePath = CARBON_PATH . "Config/$file";
echo $this->filePath;
} else {
throw new \Exception("Unable to locate: $file, Please check it exists");
}
}
}
}
pretty messy and not very flexible.
What I want to be able to do is search the locations in the same order BY FILE NAME ONLY after finding the first match It would then return the file with the extension for the configuration class to use the correct method to parse into a php array and so on.
What is the best way to search these locations for a file name
Example
Say we want a database configuration file as you can see there are 2
ConfigLocation1/Dev/
/file.php
/database.json
ConfigLocation1/
/database.ini
/anotherfile.json
I would want to use the function like so
config::findFile('database');
and it return
$result = ConfigLocation1/Dev/database.json
but if it wasnt found here then then
$result = ConfigLocation1/database.ini
Not very good at explaining things so hope the example helps
As you mentioned you need to check for file in 4 locations, so instead of if conditions, create an array of directories and loop through.
and you can use glob, to find a file irrespective of extension. see my example below:-
//Make a array of directory where you want to look for files.
$dirs = array(
ROOT . DS . 'Application/Config/' . APP_ENV . DS,
CARBON_PATH . 'Config' . DS . APP_ENV . DS
);
function findFiles($directory, $filename){
$match = array();
foreach ($directory => $dir) {
$files = glob($dir.$filename);
foreach ($files as $file) {
$match[] = $file;
}
}
return $match;
}
// to find database
$results = findFiles($dirs, 'database.*');
I was wondering, if it's possible not to repeat your self when using if statements in PHP. The following is the part of my spl_autoload_register function, e.g.:
if (is_file(Core::Config('plugins_path') . '/' . strtolower($required_class) . '.class.php'))
{
require_once (Core::Config('plugins_path') . '/' . strtolower($required_class) . '.class.php');
}
Is there a way to write it familiar to:
if (is_file(Core::Config('plugins_path') . '/' . strtolower($required_class) . '.class.php'))
{
require_once ( this );
}
in order not to duplicate exactly the same line of the code?
The example above is not working.. Is there a way really?
Not exactly as you described. But you can shrink the code with a variable.
$file = Core::Config('plugins_path') . '/' . strtolower($required_class) . '.class.php';
if (is_file($file))
{
require_once ( $file );
}
Based on the idea offered by Pietu, I'd rather shorten it to:
$file = Core::Config('plugins_path') . '/' . strtolower( $required_class ) . '.class.php';
is_file( $file ) && require_once ( $file );
im trying to create a Zend Framework custom Provider and here:
if($module == 'default'){
$modelsPath = dirname(__FILE__) . '/../application/models';
$filePath = realpath($modelsPath) . '/' . $name . '.php';
} else
if(!$module == ''){
$modelsPath = dirname(__FILE__) . '/../application/' . $module . '/models';
$filePath = realpath($modelsPath) . '/' . $name . '.php';
} else {
die('Please enter a module!');
}
when i im trying to create a path to the file and when its default module everything is ok, but when for ex. module is other word no matter what the realpath returns false?! where is the error?
try using the APPLICATION_PATH constant.
if($module == 'default'){
$modelsPath = APPLICATION_PATH . '/models';
$filePath = realpath($modelsPath) . '/' . $name . '.php';
} else
if(!$module == ''){
$modelsPath = APPLICATION_PATH . '/' . $module . '/models';
$filePath = realpath($modelsPath) . '/' . $name . '.php';
} else {
die('Please enter a module!');
}
Taken out of the php manual:
realpath() returns FALSE on failure, e.g. if the file does not exist.
Note:
The running script must have executable permissions on all directories in the hierarchy, otherwise realpath() will return FALSE.
So the problem most probably is with folder permission or the path simply is wrong!
Double check that the paths exist by simple echoing $filePath. If this checks out to be okay then ensure that the 'user' (apache, www-data, for example) have enough privileges. If you are not sure who your server is operating as you can simply debug by echoing whoami