XF 2.0 How to use the thread creator to create a thread - by Cron entries or not logged in user

AndyB

Well-known member
Hello,

In my Birthday thread add-on I would like to be able to create a thread using creator. I can extend my own controller or extend forum controller. The code below works great as long as I'm logged in, but calling the same code via Cron entries or by a not logged in user I get an error.

Here's the PHP code:

PHP:
foreach ($userIds as $user)
{
    $titleNew = str_replace('{username}', $user['username'], $title);
    $messageNew = str_replace('{username}', $user['username'], $message);

    $em = \XF::em();
    $forum = $em->find('XF:Forum', $forum);
    $creator = \XF::app()->service('XF:Thread\Creator', $forum, 'Node');        
    $creator->setContent($titleNew, $messageNew);
    $thread = $creator->save();

    $userId = $user['user_id'];
    $user = \XF::app()->find('XF:User', $userId);
    $alertRepo = \XF::app()->repository('XF:UserAlert');
    $alertRepo->alert($user, $starterUserId, $starterUsername, 'post', $thread->first_post_id, 'mention');
}


This is the error message if I run the code as not logged in.

1510784119601.webp


Thank you.
 
Hi Snog,

Thank you for the link.

I read the thread very carefully and tried many things. I'm just not able to figure out what to do.
 
Last edited:
Hi Snog,

Thank you for looking at this.

Unfortunately the code Chris shows in that post does not work if the user is not logged in. Here's the code I just tried:

PHP:
$em = \XF::em();
$forum = $em->find('XF:Forum', $forum);         
         
$creator = \XF::service('XF:Thread\Creator', $forum);
$creator->setContent($titleNew, $messageNew);
$creator->setPrefix($forum['default_prefix_id']);
$creator->setIsAutomated();
$thread = $creator->save();


The code works fine if I'm logged in, but if I'm NOT logged in I get the exact error message I show in post #1 of this thread.
 
Whenever you do an automated post, you have to pre-define a user to make the post.
 
  • Like
Reactions: LPH
Looking at the XenForo code, it appears this code will "pre-define a user".

Example only:
PHP:
$creator = $this->app->service('XF:Conversation\Creator', $this->author);

but I already use this line to define the node the thread needs to be created in:
PHP:
$creator = \XF::service('XF:Thread\Creator', $forum);

So what do I need to do to define the node and the thread author?
 
You just PM'd me about this. I don't really have anything else to add. The exact code that Snog linked you to is correct.
 
You just PM'd me about this. I don't really have anything else to add. The exact code that Snog linked you to is correct.

Correct works just fine as long as you are logged in. But try that code in a Cron entry, you will see it gives an error. Note you can't run the Cron entry manually as you would be logged in. The Cron entry needs to be triggered by a non-logged in user.
 
Well, what is the error and what is the exact code you're using?

We create threads all of the time via a logged out Cron entry. That's pretty much where that code comes from -- the Cron entry to create threads from RSS feeds.
 
The Cron entry code:

PHP:
		foreach ($userIds as $user)
		{
			// add username to title
			$titleNew = str_replace('{username}', $user['username'], $title);
			
			// add username to message
			$messageNew = str_replace('{username}', $user['username'], $message);	

			$em = \XF::em();
			$forum = $em->find('XF:Forum', $forum);			

			$creator = \XF::service('XF:Thread\Creator', $forum);
			$creator->setContent($titleNew, $messageNew);
			$creator->setPrefix($forum['default_prefix_id']);
			$creator->setIsAutomated();
			$thread = $creator->save();	

			$userId = $user['user_id'];
			$user = \XF::app()->find('XF:User', $userId);
			$alertRepo = \XF::app()->repository('XF:UserAlert');
			$alertRepo->alert($user, $starterUserId, $starterUsername, 'post', $thread->first_post_id, 'mention');
		}
	}

The above code works fine if I run the Cron entry manually, but I get the following error if I allow it to run by being triggered by either a logged in member or not logged in visitor:

HTML:
    InvalidArgumentException: Attempted to convert NULL to string/binary [username] src/XF/Mvc/Entity/Entity.php:685 

    Generated by: Unknown account Nov 16, 2017 at 7:40 AM 

Stack trace

#0 src/XF/Mvc/Entity/Entity.php(572): XF\Mvc\Entity\Entity->_castValueToType(NULL, 'username', 5, Array)
#1 src/XF/Mvc/Entity/Entity.php(502): XF\Mvc\Entity\Entity->set('username', NULL)
#2 src/XF/Service/Thread/Creator.php(105): XF\Mvc\Entity\Entity->__set('username', NULL)
#3 src/XF/Service/Thread/Creator.php(69): XF\Service\Thread\Creator->setUser(Object(XF\Entity\User))
#4 src/XF/Service/Thread/Creator.php(53): XF\Service\Thread\Creator->setupDefaults()
#5 src/XF/Container.php(274): XF\Service\Thread\Creator->__construct(Object(XF\Pub\App), Object(XF\Entity\Forum))
#6 src/XF/App.php(1293): XF\Container->createObject('XF\\Service\\Thre...', Array)
#7 src/XF/Container.php(228): XF\App->XF\{closure}('XF\\Service\\Thre...', Array, Object(XF\Container))
#8 src/XF/App.php(2429): XF\Container->create('service', 'XF:Thread\\Creat...', Array)
#9 src/XF.php(526): XF\App->service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#10 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(144): XF::service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#11 [internal function]: Andy\BirthdayThread\XF\Cron\BirthdayThread::runBirthdayThread(Object(XF\Entity\CronEntry))
#12 src/XF/Job/Cron.php(35): call_user_func(Array, Object(XF\Entity\CronEntry))
#13 src/XF/Job/Manager.php(241): XF\Job\Cron->run(7.9999988079071)
#14 src/XF/Job/Manager.php(187): XF\Job\Manager->runJobInternal(Array, 7.9999988079071)
#15 src/XF/Job/Manager.php(76): XF\Job\Manager->runJobEntry(Array, 7.9999988079071)
#16 job.php(15): XF\Job\Manager->runQueue(false, 8)
#17 {main}

-------------

Previous InvalidArgumentException: Attempted to convert NULL to string/binary - src/XF/Mvc/Entity/ValueFormatter.php:104
#0 src/XF/Mvc/Entity/Entity.php(681): XF\Mvc\Entity\ValueFormatter->castValueToType(NULL, 5, Array)
#1 src/XF/Mvc/Entity/Entity.php(572): XF\Mvc\Entity\Entity->_castValueToType(NULL, 'username', 5, Array)
#2 src/XF/Mvc/Entity/Entity.php(502): XF\Mvc\Entity\Entity->set('username', NULL)
#3 src/XF/Service/Thread/Creator.php(105): XF\Mvc\Entity\Entity->__set('username', NULL)
#4 src/XF/Service/Thread/Creator.php(69): XF\Service\Thread\Creator->setUser(Object(XF\Entity\User))
#5 src/XF/Service/Thread/Creator.php(53): XF\Service\Thread\Creator->setupDefaults()
#6 src/XF/Container.php(274): XF\Service\Thread\Creator->__construct(Object(XF\Pub\App), Object(XF\Entity\Forum))
#7 src/XF/App.php(1293): XF\Container->createObject('XF\\Service\\Thre...', Array)
#8 src/XF/Container.php(228): XF\App->XF\{closure}('XF\\Service\\Thre...', Array, Object(XF\Container))
#9 src/XF/App.php(2429): XF\Container->create('service', 'XF:Thread\\Creat...', Array)
#10 src/XF.php(526): XF\App->service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#11 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(144): XF::service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#12 [internal function]: Andy\BirthdayThread\XF\Cron\BirthdayThread::runBirthdayThread(Object(XF\Entity\CronEntry))
#13 src/XF/Job/Cron.php(35): call_user_func(Array, Object(XF\Entity\CronEntry))
#14 src/XF/Job/Manager.php(241): XF\Job\Cron->run(7.9999988079071)
#15 src/XF/Job/Manager.php(187): XF\Job\Manager->runJobInternal(Array, 7.9999988079071)
#16 src/XF/Job/Manager.php(76): XF\Job\Manager->runJobEntry(Array, 7.9999988079071)
#17 job.php(15): XF\Job\Manager->runQueue(false, 8)
#18 {main}
 
Still not having any luck creating the new thread via Cron entry. Works fine if I run the Cron entry manually, just not if it runs on it's own.
PHP:
        foreach ($userIds as $userId)
        {
            $em = \XF::em();
            $forum = $em->find('XF:Forum', $forum); 
         
            $user = \XF::visitor();
         
            \XF::asVisitor($user, function() use ($forum, $title, $message)
            {
                $creator = \XF::service('XF:Thread\Creator', $forum);
                $creator->setContent($title, $message);
                $creator->setPrefix($forum['default_prefix_id']);
                $creator->setIsAutomated();
                $creator->save();
            });
        }

The error message when the Cron entry runs on its own:
HTML:
    InvalidArgumentException: Attempted to convert NULL to string/binary [username] src/XF/Mvc/Entity/Entity.php:685

    Generated by: Unknown account Nov 16, 2017 at 8:07 AM

Stack trace

#0 src/XF/Mvc/Entity/Entity.php(572): XF\Mvc\Entity\Entity->_castValueToType(NULL, 'username', 5, Array)
#1 src/XF/Mvc/Entity/Entity.php(502): XF\Mvc\Entity\Entity->set('username', NULL)
#2 src/XF/Service/Thread/Creator.php(105): XF\Mvc\Entity\Entity->__set('username', NULL)
#3 src/XF/Service/Thread/Creator.php(69): XF\Service\Thread\Creator->setUser(Object(XF\Entity\User))
#4 src/XF/Service/Thread/Creator.php(53): XF\Service\Thread\Creator->setupDefaults()
#5 src/XF/Container.php(274): XF\Service\Thread\Creator->__construct(Object(XF\Pub\App), Object(XF\Entity\Forum))
#6 src/XF/App.php(1293): XF\Container->createObject('XF\\Service\\Thre...', Array)
#7 src/XF/Container.php(228): XF\App->XF\{closure}('XF\\Service\\Thre...', Array, Object(XF\Container))
#8 src/XF/App.php(2429): XF\Container->create('service', 'XF:Thread\\Creat...', Array)
#9 src/XF.php(526): XF\App->service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#10 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(142): XF::service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#11 src/XF.php(392): Andy\BirthdayThread\XF\Cron\BirthdayThread::Andy\BirthdayThread\XF\Cron\{closure}()
#12 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(147): XF::asVisitor(Object(XF\Entity\User), Object(Closure))
#13 [internal function]: Andy\BirthdayThread\XF\Cron\BirthdayThread::runBirthdayThread(Object(XF\Entity\CronEntry))
#14 src/XF/Job/Cron.php(35): call_user_func(Array, Object(XF\Entity\CronEntry))
#15 src/XF/Job/Manager.php(241): XF\Job\Cron->run(7.9999990463257)
#16 src/XF/Job/Manager.php(187): XF\Job\Manager->runJobInternal(Array, 7.9999990463257)
#17 src/XF/Job/Manager.php(76): XF\Job\Manager->runJobEntry(Array, 7.9999990463257)
#18 job.php(15): XF\Job\Manager->runQueue(false, 8)
#19 {main}

-------------

Previous InvalidArgumentException: Attempted to convert NULL to string/binary - src/XF/Mvc/Entity/ValueFormatter.php:104
#0 src/XF/Mvc/Entity/Entity.php(681): XF\Mvc\Entity\ValueFormatter->castValueToType(NULL, 5, Array)
#1 src/XF/Mvc/Entity/Entity.php(572): XF\Mvc\Entity\Entity->_castValueToType(NULL, 'username', 5, Array)
#2 src/XF/Mvc/Entity/Entity.php(502): XF\Mvc\Entity\Entity->set('username', NULL)
#3 src/XF/Service/Thread/Creator.php(105): XF\Mvc\Entity\Entity->__set('username', NULL)
#4 src/XF/Service/Thread/Creator.php(69): XF\Service\Thread\Creator->setUser(Object(XF\Entity\User))
#5 src/XF/Service/Thread/Creator.php(53): XF\Service\Thread\Creator->setupDefaults()
#6 src/XF/Container.php(274): XF\Service\Thread\Creator->__construct(Object(XF\Pub\App), Object(XF\Entity\Forum))
#7 src/XF/App.php(1293): XF\Container->createObject('XF\\Service\\Thre...', Array)
#8 src/XF/Container.php(228): XF\App->XF\{closure}('XF\\Service\\Thre...', Array, Object(XF\Container))
#9 src/XF/App.php(2429): XF\Container->create('service', 'XF:Thread\\Creat...', Array)
#10 src/XF.php(526): XF\App->service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#11 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(142): XF::service('XF:Thread\\Creat...', Object(XF\Entity\Forum))
#12 src/XF.php(392): Andy\BirthdayThread\XF\Cron\BirthdayThread::Andy\BirthdayThread\XF\Cron\{closure}()
#13 src/addons/Andy/BirthdayThread/XF/Cron/BirthdayThread.php(147): XF::asVisitor(Object(XF\Entity\User), Object(Closure))
#14 [internal function]: Andy\BirthdayThread\XF\Cron\BirthdayThread::runBirthdayThread(Object(XF\Entity\CronEntry))
#15 src/XF/Job/Cron.php(35): call_user_func(Array, Object(XF\Entity\CronEntry))
#16 src/XF/Job/Manager.php(241): XF\Job\Cron->run(7.9999990463257)
#17 src/XF/Job/Manager.php(187): XF\Job\Manager->runJobInternal(Array, 7.9999990463257)
#18 src/XF/Job/Manager.php(76): XF\Job\Manager->runJobEntry(Array, 7.9999990463257)
#19 job.php(15): XF\Job\Manager->runQueue(false, 8)
#20 {main}
 
Last edited:
Or again, if you don't want the user to post their own birthday, pre-define a user in your add-on options and use that user. (this is what most people do)
 
Top Bottom