Problem with namespacing?

Problem with namespacing?

by Frederic Nevers -
Number of replies: 18

I am developing a block, which makes use of scheduled tasks. The ’scheduled task’ part works just fine, as in it fires off when needed, shows up in the list of scheduled tasks and can be edited by the site’s admin. 

The part I am struggling with is calling functions from within the ‘public function execute()’, like it is done in the forum implementation of cron (see /mod/forum/classes/task/cron_task.php, as below)


namespace mod_forum\task;
class cron_task extends \core\task\scheduled_task {
    /**
     * Get a descriptive name for this task (shown to admins).
     *
     * @return string
     */
    public function get_name() {
        return get_string('crontask', 'mod_forum');
    }
    /**
     * Run forum cron.
     */
    public function execute() {
        global $CFG;
        require_once($CFG->dirroot . '/mod/forum/lib.php');
        forum_cron(); // function is being called here, and works fine
    }
}


Here is what my blocks/block_broken_links/classes/task/cron_task.php file looks like. When I run /admin/cron.php manually, it returns a fatal error stating it cannot find the broken_links_cron function. 


namespace block_broken_links\task;
class cron_task extends \core\task\scheduled_task {
    /**
     * Get a descriptive name for this task (shown to admins).
     *
     * @return string
     */
    public function get_name() {
        return get_string('crontask', 'block_broken_links');
    }
    /**
     * Run broken links cron.
     */
    public function execute() {
        global $CFG;
        require_once($CFG->dirroot . ‘/blocks/block_broken_links/block_broken_links.php');
        broken_links_cron(); //<— function is being called here, fatal error is returned
    }
}


It is worth noting that:

- When I replace the function call (broken_links_cron) with the actual code from that function, /admin/cron.php works fine and returns no error. 

- When I run the broken_links_cron from another file (completely bypassing the scheduled tasks and cron mechanisms), it works fine

- Other modules, or parts of Moodle, call functions from within the ‘public function execute()’ part of the cron_task.php files with no problems (e.g. badges)


What I am doing wrong? Should I namespace my block_broken_links.php file? Would that break anything? Am I missing something obvious? Is what I am trying to do impossible with non-core code? Any help would be appreciated


Cheers, 

Fred


Average of ratings: -
In reply to Frederic Nevers

Re: Problem with namespacing?

by Conn Warwicker -
Picture of Core developers Picture of Plugin developers

If the broken_links_cron method is in a file that you haven't named spaced, you should be able to call it by just adding a backslash to the front: \broken_links_cron()

In reply to Conn Warwicker

Re: Problem with namespacing?

by Frederic Nevers -

Thanks for your reply Conn. 

Unfortunately that doesn't work. It returns a fatal error as well.

Cheers, 

Fred

In reply to Frederic Nevers

Re: Problem with namespacing?

by Davo Smith -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Have you purged your site caches? (site admin > developer > purge caches)

For performance reasons, the class autoloading code caches the list of known classes, so the caches need purging when this changes (as always, the cache clear also happens when a plugin version.php changes, triggering an upgrade).

In reply to Davo Smith

Re: Problem with namespacing?

by Frederic Nevers -

Hi Davo, 

Thank you. Yes I did, to no avail. I have also added 

$CFG->debug = (E_ALL | E_STRICT);

to my config.php

I really don't know how to fix this problem. 

Cheers, 

Fred

In reply to Frederic Nevers

Re: Problem with namespacing?

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Its pretty curious. 

Just for the record I think you add the backslash in front of class names , not functions. 

So in a namespaced class to create a new stdClass you would do it like this.

$myclass = new \stdClass();

But calling functions like forum_cron() should be fine without the backslash.


Can you call any other functions in block_broken_links.php from your scheduled task? 

Can you call forum_cron() from it? 

That will at least tell you if the problem is in your task, or in your block code. 



In reply to Justin Hunt

Re: Problem with namespacing?

by Frederic Nevers -

Hi Justin,

Thank you for taking the time to look into this. 

  • I cannot call any other function from the block_broken_links.php file
  • I can call forum_cron() from my task file. It works fine and returns no error. 

I have removed any unnecessary functions from the block code, and created a simple function for debugging, and the fatal error returned is still

Fatal error: Call to undefined function block_broken_links\task\proof_of_concept() in xxxx 

I have attached the code if you wish to take a look at it.

Cheers, 

Fred


In reply to Frederic Nevers

Re: Problem with namespacing?

by Michael Aherne -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers

Looks like that's not a function - it's a method on the block_broken_links class, so you'll probably need to either create an instance of block_broken_links and call it on that, or change the method to static and call block_broken_links::proof_of_concept(). Either way, you may or may not need a backslash in front of block_broken_links - I'm not sure I understand namespacing well enough to say which!

Average of ratings: Useful (1)
In reply to Michael Aherne

Re: Problem with namespacing?

by Frederic Nevers -

Nicely spotted, Michael. Thanks a lot, worked a treat. 

\I did have to use the backslash

Cheers, 

Fred

Average of ratings: Useful (1)
In reply to Frederic Nevers

Re: Problem with namespacing?

by Damyon Wiese -
require_once($CFG->dirroot . ‘/blocks/block_broken_links/block_broken_links.php');

This path looks wrong. Should it be

require_once($CFG->dirroot . ‘/blocks/broken_links/block_broken_links.php');

?

(The quotes also look strange but maybe that is just a formatting issue in the forum).
In reply to Damyon Wiese

Re: Problem with namespacing?

by Frederic Nevers -

Hi Damyon, 

Thank you for your response. The path is wrong in the message, you are right. It is correct in my actual file, though. The quotes look weird due to some formatting issues, it's fine in the file. 

I will start the block_broken_links.php file from scratch again and see if new errors come up, or if it fixes things. Strangely enough I get no errors when installing the block, or when running it (I have debug set to 'Developer'). My IDE also doesn't return any errors. 

Cheers, 

Fred

In reply to Frederic Nevers

Re: Problem with namespacing?

by Robert Brenstein -
Have you checked the permissions and ownership of that file?
In reply to Robert Brenstein

Re: Problem with namespacing?

by Frederic Nevers -
Thank you, Robert for your response. Yes, I did. Files and folders belong to my webserver user, with the recommended permissions. 

I have even tried to set the broken_links folder (and all of its contents) to 777, to no avail. 

Cheers, 

Fred

In reply to Frederic Nevers

Re: Problem with namespacing?

by Robert Brenstein -
Have you tried to have cron report the actual path to the file as it sees it?
Have you checked whether an invisible character sneaked into the path?
In reply to Frederic Nevers

Re: Problem with namespacing?

by Michael Aherne -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers

Does your file block_broken_links.php have any namespace declarations in it?

In reply to Michael Aherne

Re: Problem with namespacing?

by Frederic Nevers -

No it doesn't. Should I add any? I tried to yesterday, but then it would prevent me from installing the block

In reply to Frederic Nevers

Re: Problem with namespacing?

by Michael Aherne -
Picture of Core developers Picture of Peer reviewers Picture of Plugin developers

No, it shouldn't - I was just wondering if that might have been causing the problem!

In reply to Frederic Nevers

Re: Problem with namespacing?

by Justin Hunt -
Picture of Particularly helpful Moodlers Picture of Plugin developers

Yes what Michael said is correct. That function is a class method so it has to be called differently. The easiest thing is to declare it static like this

static function broken_links_cron() {

..

}


Then call it from your task like this:

\block_broken_links::broken_links_cron() 


Average of ratings: Useful (1)
In reply to Justin Hunt

Re: Problem with namespacing?

by Frederic Nevers -

Hi, 

It worked perfectly. I was focusing on the wrong problem the whole time. Thanks to all those who helped. Much appreciated. 

Cheers, 

Fred