Adding a cronjob with moodle-cron-api is not working properly - php

I am trying to schedule a task in moodle-cron-api following the instructions here at: https://docs.moodle.org/dev/Task_API.
I have the root folder at /local and the name of the root folder is mod_hygene.
I have a cut_my_toe_nails.php at /local/mod_hygene/classes/task which is:
namespace mod_hygene\task;
/**
* An example of a scheduled task.
*/
class cut_my_toe_nails extends \core\task\scheduled_task {
/**
* Return the task's name as shown in admin screens.
*
* #return string
*/
public function get_name() {
return get_string('cutmytoenails', 'mod_hygene');
}
/**
* Execute the task.
*/
public function execute() {
// Apply fungus cream.
// Apply chainsaw.
// Apply olive oil.
echo 'do';
}
}
And there is /mod_hygene/db/tasks.php:
$tasks = [
[
'classname' => 'mod_hygene\task\cut_my_toe_nails',
'blocking' => 0,
'minute' => '*',
'hour' => '*',
'day' => '*',
'month' => '1,7',
'dayofweek' => '*',
],
];
As you see, the task should run every minute. I run my moodle container via terminal with
docker-compose up -d --build moodle
In the terminal I should see 'do' printed every minute. But, I am not seeing anything. I hovered to Site Administration/Server/Scheduled Tasks. There I am not seeing this task. But I checked in Site Administration/Plugins/Plugins Overview and could find local_mod_hygene in the Local Plugins.
Can anyone help me with it? Do I need to make some changes to the Dockerfile as well?

Just a tip, don't use the prefix mod_ for a local plugin, it could be confused for an activity plugin in the mod folder.
So assuming your code is in /local/hygene/
The task file should be /local/hygene/classes/task/cut_my_toe_nails.php
The class namespace should be
namespace local_hygene\task;
The tasks file should be /local/hygene/db/tasks.php with
'classname' => 'local_hygene\task\cut_my_toe_nails',
Once its installed, check if the task is enabled via
Site admin > Server > Tasks
Or direct to
yourwebsite/admin/tool/task/scheduledtasks.php
If its installed and enabled, then run it from the command line to test it.
First see if its listed - if its not listed then its not installed correctly
php admin/cli/scheduled_task.php --list
If it it listed, then note the name and run the task manually - note that the \ has to be escaped with \\
php admin/cli/scheduled_task.php --execute=\\local_hygene\\task\\cut_my_toe_nails
If the task is working correctly, then wait for cron
Or, depending on the settings, you can run cron manually via yourmoodlewebsite/admin/cron.php when logged in as an admin
Or from the command line
php admin/cli/cron.php

Related

Shopware 6 Production Unable to access plugin services from the container in a unit test

I setup a Unit Test in a Shopware custom (static) Plugin following this guide:
Shopware documentation
Everything runs fine and I'm able to run a unit test
class ProductReturnsTest extends TestCase
{
use IntegrationTestBehaviour;
use StorefrontPageTestBehaviour;
public function testConfirmPageSubscriber(): void
{
$container = $this->getKernel()->getContainer();
$dd = $container->get(CustomDataService::class); <== IT BREAKS HERE ServiceNotFoundException: You have requested a non-existent service
$dd = $container->get('event_dispatcher'); // WORKS WITH SHOPWARE ALIASES NOT WITH PLUGINS
}
}
I can make container->get on any shopware alias but as soon I try to recall and get from the container any service decleared in any xml of any 3th party plugin, i get
ServiceNotFoundException: You have requested a non-existent service "blabla"
What is wrong ?
Take a look at the answer given here: https://stackoverflow.com/a/70171394/10064036.
Probably your plugin is not marked as active in the DB your tests run against.
The test environment has a mostly unpopulated database to allow tests to to run unaffected with their own fixtures only. Therefore after each test there should be a rollback to all transactions made within the test. This principle also includes plugin installations and database transactions they may execute in their lifecycle events.
You may want to install your plugin properly before your tests, so you get a representative state of the environment with the plugins lifecycle events getting dispatched and thereby caused possible changes.
public function setUp(): void
{
$this->installPlugin();
}
private function installPlugin(): void
{
$application = new Application($this->getKernel());
$installCommand = $application->find('plugin:install');
$args = [
'--activate' => true,
'--reinstall' => false,
'plugins' => ['YourPluginName'],
];
$installCommand->run(new ArrayInput($args, $installCommand->getDefinition()), new NullOutput());
}

Laravel daily log files with older timestamps not cleared/deleted on rotation after name pattern change

I have a Laravel 5.8 project where daily log rotation worked fine until I fiddled and changed the filename pattern due to permission conflict issue from multiple source of log entry.
My current log channel (daily) configuration is following:
'daily' => [
'driver' => 'daily',
'tap' => [App\Logging\CustomFilenames::class],
'path' => storage_path('logs/laravel.log'),
'level' => 'debug',
'days' => 14,
],
Here the only modification I did is to add the tap option by googling, and the content of the said file is following:
<?php
namespace App\Logging;
use Monolog\Handler\RotatingFileHandler;
class CustomFilenames
{
/**
* Customize the given logger instance.
*
* #param \Illuminate\Log\Logger $logger
* #return void
*/
public function __invoke($logger)
{
foreach ($logger->getHandlers() as $handler) {
if ($handler instanceof RotatingFileHandler) {
$sapi = php_sapi_name();
$handler->setFilenameFormat("{filename}-{date}-$sapi", 'Y-m-d');
}
}
}
}
What's doing here is creating file based on SAPI user, by including the username in the filename, so that different user will have different files to write (because of the changed filename) and thus no permission conflict issue will occur. I don't have detail knowledge about SAPI user and just getting along until I can figure out another solution.
Now while log files are being generated daily, neither files with older format nor new ones (albeit more than 2 weeks old) are getting deleted. I suspect further modification is needed to make it compatible with Monolog\Handler\RotatingFileHandler, but have no idea what to do, thanks!

A way to call a command prompt function from controller in Laravel?

I'm trying to make a thumbnail in a Laravel project and I tried a lot other ways but with no success - Libraries, APIs... The problem is that the project is developed in Windows and the professor needs it in Windows as well.
So far, I experimented to integrate different libraries (wkhtmltoimage, spatie/browsershot, mpdf and s.o.) but in the most of the cases, there are problems with the path.
The required function, which I need, works very good in command prompt and I thought that I must find a way to call it in the controller.
I've tried with:
shell_execute($call);
system($call);
exec($call);
// with $call = "{func_name} {path_to_input_file} {name_of_output_file}";
// Example: $call = "wkhtmltoimage C:\xampp\htdocs\app\public\test.html img.jpg"
But no result. The function generates an image, which I want to store in the database.
Is there an other way to make a call to the command prompt?
Maybe SSH call?
You can execute Artisan commands directly via your controller.
Look at this example from the Laravel documentation:
Route::get('/foo', function () {
$exitCode = Artisan::call('email:send', [
'user' => 1, '--queue' => 'default'
]);
//
});

Segmentation fault during Laravel Migration

The problem
As per my previous question here, it was pointed out to me that I shouldn't be trying to fill related models in a Laravel Factory (i.e I should fill them in their own factory).
However, I have an observer that looks for the related data during the creation and tries to fill related models (this is so I can create multiple related entities using just the create:: method and a single multistep form). Now, I need to add a check to see if this data is populated in the observer so I don't have to specify it in the factory.
In doing so, I now get a segmentation fault when trying to seed my database. I've narrowed down the cause to this line - without the isset check, it works fine (other than $data['day'] is not specified, hence the check);
Segmentation fault (core dumped)
if(isset($data['day'])) $event->day->fill($data['day']);
Related Code
EventFactory.php
$factory->define(App\Event::class, function (Faker $faker) {
return [
"name" => "A Test Event",
"description" => $faker->paragraphs(3, true),
"event_start_date" => today(),
"event_opening_date" => today(),
"event_closing_date" => tomorrow(),
"user_id" => 1,
"banner_id" => 1,
"gallery_id" => 1,
"related_event_id" => 1,
"status" => "published",
"purchase_limit" => 1000,
"limit_remaining" => 1000,
"delivery_method" => "collection",
"merchandise_delivery_method" => "collection"
];
});
EventObserver.php
public function created($event){
# get all attributes
$data = $event->getAttributes();
# fill any related models
if(isset($data['day'])) $event->day->fill($data['day']);
# save user
$event->push();
}
public function updating($model){
# get all attributes
$data = $model->getAttributes();
# fill any related models
if(isset($data['day'])) $model->day->fill($data['day']);
# save user
$model->push();
}
Other Info
Command: sudo php artisan migrate:reset --seed
Host: Windows 10
VM Environment: Vagrant running Ubuntu 16.04 via HyperV, mounted share with Samba
PHP Version: 7.1.20
Laravel Version: 5.7
Update
Turns out the issue is actually with this line;
$event->push();
Could there be something recursive happening here?
Update 2
With Namoshek's help, I can now narrow it down to the following error from xdebug;
Maximum function nesting level of '256' reached, aborting!
Increasing xdebug.max_nesting_level to 200000 brings back the segfault.
This seems to me like it's stuck in an infinite loop. However, I can't see how calling save() or push() in created would end up calling back to itself. Confused.
This did indeed turn out to be an infinite recursion issue. Eliminating the line:
$event->push(); // this line appears to call update again, which in turn calls push, which calls update etc...
Solved the problem.

Typo3 scheduler class not found

I am trying to get a scheduler class running on typo3.
ext_autoload.php:
$extensionPath = t3lib_extMgm::extPath('mh_compass');
$loaderClass = array(
'tx_monitorcompassdailyreset_sched' => $extensionPath.'scheduler/class.tx_monitorcompassdailyreset_sched.php',
);
return $loaderClass;
ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks']['tx_monitorcompassdailyreset_sched'] = array(
'extension' => $_EXTKEY,
'title' => 'Compass Monitor Daily Reset Scheduler',
'description' => 'Reset daily Monitor Jobs',
);
class.tx_monitorcompassdailyreset_sched.php:
class tx_monitorcompassdailyreset_sched extends tx_scheduler_Task {
public function execute() {
error_log( "Start Compass Monitor Daily Reset Scheduled Job" );
//do some stuff
error_log( "Finished Compass Monitor Scheduled Job" );
}
}
When I try to add the task in the scheduler in the backend, I get the following error:
Fatal error: Class 'tx_monitorcompassdailyreset_sched' not found in /var/www/typo3_src-4.5.22/t3lib/class.t3lib_div.php on line 5375
This doesn't make sense as a) I have used debug on that function and it loads all the other classes, and b) I cannot see a discrepancy in my class naming.
The version of php is 5.3.10 (there was a bug like this with 5.3.2, but it disappeared)
Your class naming is obviously wrong. Your extension key is "mh_compass", so your class name needs to start with "tx_mhcompass_". The beginning of the class name always contains "tx_" followed up with the extension key without underscores.
Try renaming your class to "tx_mhcompass_Task_Reset" for example.

Categories