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.png


Thank you.
 

AndyB

Well-known member
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:

AndyB

Well-known member
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.
 

Snog

Well-known member
Whenever you do an automated post, you have to pre-define a user to make the post.
 
Reactions: LPH

AndyB

Well-known member
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?
 

Chris D

XenForo developer
Staff member
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.
 

AndyB

Well-known member
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.
 

Chris D

XenForo developer
Staff member
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.
 

AndyB

Well-known member
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}
 

AndyB

Well-known member
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:

Snog

Well-known member
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