CakePHP 1.3 - Calling Shells from a Controller? - shell

I cannot for the life of me figure out how to call a shell from a controller.
We have a background process that packages up data in a .pdf, and we don't want to bog down the page loads waiting for this to occur, so we want to put all this processing in a shell.
I've figured out how to pass values to a shell with $this->args
I know you can use App::import('Shell','TestShell')... but after that I am lost.
How do I call the main() function of the shell within a controller?

In Cake 1.3, I was able to get it working by doing the following:
App::import('Shell', 'Shell');
App::Import('Vendor', array('shells/shell_title'));
$myShell = new ShellTitleShell(new Object());
$myShell->initialize();
$myShell->someAction();

I should be more focused reading the question :/
Could do it in Cake2, not sure how different would it be for 1.3. :?
<?php
App::import('Console/Command', 'AppShell');
App::import('Console/Command', 'HelloWorldShell');
$h = new HelloWorldShell();
$h->dispatchMethod('main');
?>
Windows:
If you do not have your environment variables set you will need to provide location of PHP executable.
C:\wamp\bin\php\php_v\php.exe C:\wamp\www\cakephp\cake\console\cake.php test this_arg_0 this_arg_1
Linux:
You may already have your php location defined. If not, you may need to export it to your $PATH or provide full path to php
php /var/www/html/cakephp/cake/console/cake.php test this_arg_0 this_arg_1
main() function will be called by default.
Hope it helps!

Related

Firefox: run functions from Javascript through an extension

At the present I'm pasting a Javascript into the console of FF and I'm calling the functions from the console:
function fill (i){
if(i==1){
SINGLE_START();
}
else if(i==2){
DUAL_START();
}
else if(i==3){
INTEGRATED_START();
}
else{
alert("=======================\n Tool Filler\n=======================\n\n1 or 2");
}
}
It is used to scrape the content of the website and e.g. create a file or generate an email from certain parts of the website, e.g.:
function SINGLE_START(){
//Focus:
let d = $(document).activeElement.contentDocument.activeElement.contentDocument.activeElement.contentDocument;
etc.
I thougt, there could be a way to use it through an extension and so I installed Tampermonkey and saved the script as userscript within the extension. But than I have a problem that I'm not able to call the desired function from the script as I need it, not just start the script as the website loads.
Does anyone has an idea how to call the functions one by one from within Tampermonkey (or Greasemonkey), or any other extension?
Thanks in advance!
This is because Tampermonkey scripts run in isolated context. There are two kinds:
1. No special privilegies
If you're not using any special GM functions that are unlocked by #grant GM_doThisAndThat and instead you use #grant none, then what internally happens is something like this:
function TheScript() {
// Here is your script that you added to tampermonkey
}
TheScript();
This if you have a function there, it is only available in the script. You need to explicitly expose it to window context:
function fill (i){
... code here ...
}
window.myFill = fill;
Then in console you write myFill(42) and it will execute.
I would recommend that you avoid assigning fill to window since it's a name that could likely conflict with something, but that's up to you.
2. Special privilegies
If you're using some of the GM features, you need to add #grant unsafeWindow and then assign to unsafeWindow variable. Be careful what you expose like this, you don't want to allow the website to access any of the GM_function features as they could access your private data on other websites and your computer!

Trying to implement FPDF with all forms of instantiation but only one form works. Others give Error

Installed crabbley/fpdf-laravel as per instructions. Tried some sample code as follows:
$pdf= app('FPDF');
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Swordsmen Class Times');
$pdf->Output();
While the instantiation of fpdf is different from the samples in the tutorials, all works as expected and the pdf is displayed in the browser. I got this working sample from the crabbley packagist.org/packages/crabbly/fpdf-laravel readme under 'usage'. The 'usage' instructions also provide an alternative instantiation viz: $pdf = new Crabbly\FPDF\FPDF;
The tutorial samples use something slightly different again, ie
require('fpdf.php');
x=new FPDF();
and thus are a little different. When I changed it to be the same as the tutorial, all I changed was the instantiation line from
$pdf= app('FPDF');
to
$pdf = new FPDF('L', 'mm','A4');
and I get the error 'Class 'App\Http\Controllers\FPDF' not found'. I do not understand the difference between the different forms of instantiation and not sure what is going on but I need the latter format so I can set page orientation etc. I also tried the usage format as described above with the same sort of error, ie new Crabbly\FPDF\FPDF not found.
I have tried the require statement but FPDF is not found and I am unsure where to point 'require' to.
Installation consisted of:
composer require crabbly/fpdf-laravel
add Crabbly\FPDF\FpdfServiceProvider::class to config/app.php in the providers section
Any suggestions will be appreciated.
You are using an implementation for the Laravel framework that binds an instance of FPDF to the service container. Using app('FPDF') returns you a new instance of FPDF, which is pretty much the same what new FPDF() would do.
The require way of using it is framework agnostic and would be the way to use FPDF if you are just using a plain PHP script. While you could use this way with Laravel too, why would you want to do that?
The reason the require does not work, by the way, is that the fpdf.php file is not found from where you call it. It would be required to sit in the same directory unless you give it a path. Considering you installed it using composer, the fpdf.php script, if any, should sit inside the vendor directory.
However, just go with using the service container. The line $pdf = new FPDF('L', 'mm','A4'); just creates a new instance of the FPDF class and initializes it by passing arguments to the constructor, these being 'L' for landscape orientation, 'mm' for the measurement unit, and 'A4' for the page size. Without knowing the package you use and having testing it, you should also be able to set them equivalently by calling:
$pdf = app('FPDF', ['L', 'mm', 'A4']);
Hope that helps!

Laravel: How to run a Library in background (Process component)

I'm trying to create a program which generates event dates for the whole year. The program works if the user select few events but if the user select 100+ events and assigned them every week it reaches the Maximum execution time error.
In order to fix this, my idea is to run the program in the background.
I'm using Laravel 5.4, running the script below will call the function
$process = new Process('php -f '.$path.' generate_evnt_prepared ' . $content['evntid']);
$process->run();
Function Script
namespace App\Library\shellexec;
use App\Model\V1\EvntPlanDtl;
use App\Model\V1\EvntPlanDtlPrePo;
use Carbon\Carbon;
class RoutePlan {
//put your code here
public function process($method = null, $param = 0)
{
$this->$method($param);
}
I'm pretty sure that the function is called as I'm getting an error in error_logs that the Models are not found
PHP Fatal error: Class 'App\Model\V1\EvntPlanDtl' not found in C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php on line 30
PHP Stack trace:
PHP 1. {main}() C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php:0
PHP 2. App\Library\shellexec\EventPlan->process() C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php:88
PHP 3. App\Library\shellexec\EventPlan->generate_evnt_prepared ()
Anyone knows how to fix this? I'm open to suggestions if this is the wrong way.
Big thanks!
Sounds like a more scalable way is to create a "chunked" version and fire them into a queue for processing. For example, based off some assumptions about the example you provided, I might suggest one firing one queued message for each Event the user selects.
That adds some overhead to manage, but honestly I've always found it's more effective to take some of that cost up front and do it right, rather than finding workarounds like increasing settings or (shudder) shelling out to sub processes.

How to read session variables from bootstrap.php file

Is there any any way to read session from bootstrap file.
App::uses('CakeSession', 'Model/Datasource');
$value = CakeSession::read('User.id');
I tried this code. But fail to read. Please help me out ..
For future visitors,
Looking for Cakesession object in bootstrap.php is a little weird but if you really must do it, do it this way:
App::import('Model/Datasource', 'CakeSession');
$Session = new CakeSession();
// $userId = $Session->read("Auth.User.id");
Check the difference between App::uses() (attempted by OP) and App::import() in documentation.
rather than do all the initialisation overhead, I would here (and just here in bootstrap.php) resort to a basic php stuff:
session_start();
debug($_SESSION);

Cache won't work in Appcelerator

Titanium SDK version: 1.6.
iPhone SDK version: 4.2
I am trying out the cache snippet found on the Appcelerator forum but I get an error: [ERROR] Script Error = Can't find variable: utils at cache.js (line 9).
I put this one (http://pastie.org/1541768) in a file called cache.js and implemented the code from this one (http://pastie.org/pastes/1541787) in the calling script, but I get the error.
What is wrong? I copied the code exactly.
Your problems is whilst the first pastie defines utils.httpcache. The variable utils is not defined outside of this function closure (because it is not defined anywhere in global namespace). As below shows.
(function() {
utils.httpcache = {
};
})();
To make it all work in this instance add the following code to the top of your cache.js file.
var utils = {};
This declares the utils variable in global namespace. Then when the function closure is executed below it will add utils.httpcache to the utils object.
The problem is actually not specific to Appcelerator and is just a simple JavaScript bug. Checkout Douglas Crockfords book, JavaScript the Good Parts. Reading it will literally make you a more awesome JavaScript developer.
You can't use utils.httpcache.getFromCache(url) until you add this to your code:
var utils = {};
That's because how the author created his function, it's called JavaScript module pattern and it's generally used to structure the code.
I seem to lose this value "value.httpCacheExpire = expireTime;" when the code does the "Titanium.App.Properties.setString(key,JSON.stringify(value));" so when I get it back using the getString method, there's no longer the "value.httpCacheExpire.
Anyone else have this issue? Am I missing something to get this working?

Resources