Jump to content
  • Status: Moved to Github

I helped upgrade a 3.4 forum to 5.0.3 (passing through 4.7.20) and loading an old topic with a poll threw this error:

TypeError: IPS\Poll::get_choices(): Return value must be of type array, null returned (0)
#0 /home/nuovo/public_html/invision/system/Patterns/ActiveRecord.php(360): IPS\Poll->get_choices()
#1 /home/nuovo/public_html/invision/system/Poll/Poll.php(528): IPS\Patterns\ActiveRecord->__get()
#2 /home/nuovo/public_html/invision/static/templates/forums_front_topics.php(3898): IPS\Poll->__toString()
#3 /home/nuovo/public_html/invision/system/Theme/SandboxedTemplate.php(68): IPS\Theme\class_forums_front_topics->topic()
#4 /home/nuovo/public_html/invision/applications/forums/modules/front/forums/topic.php(724): IPS\Theme\SandboxedTemplate->__call()
#5 /home/nuovo/public_html/invision/system/Dispatcher/Controller.php(139): IPS\forums\modules\front\forums\topic->manage()
#6 /home/nuovo/public_html/invision/system/Content/Controller.php(124): IPS\Dispatcher\Controller->execute()
#7 /home/nuovo/public_html/invision/applications/forums/modules/front/forums/topic.php(82): IPS\Content\Controller->execute()
#8 /home/nuovo/public_html/invision/system/Dispatcher/Dispatcher.php(169): IPS\forums\modules\front\forums\topic->execute()
#9 /home/nuovo/public_html/invision/index.php(16): IPS\Dispatcher->run()
#10 {main}

After looking into it I discovered the poll choices in the database were saved in the old serialized data instead of the new JSON format.

To temporarily fix the issue for them until a fix is included in a future upgrade I add an unserialize fallback in the get_choices() function for them.

Original code:

	/**
	 * Get choices
	 *
	 * @return	array
	 */
	public function get_choices(): array
	{
		return json_decode( $this->_data['choices'], TRUE );
	}

My change:

	/**
	 * Get choices
	 *
	 * @return	array
	 */
	public function get_choices(): array
	{
		$choices = json_decode($this->_data['choices'], true);
		
		# If json_decode fails, try unserialize as a fallback
		if (json_last_error() !== JSON_ERROR_NONE)
		{
			$choices = @unserialize($this->_data['choices']);
			
			# If the result is a proper array update the database to use JSON
			if ( is_array($choices) )
			{
				$this->choices = $choices;
				$this->save();
			}
		}
		
		return $choices;
	}

User Feedback

Recommended Comments

Esther E.

Invision Community Team

Just a note: We won't be handling the serialized data here. We'll fix it so that it doesn't throw an error if the data is invalid, but ultimately, converting that data should be done with a custom script.

Philip_B

Clients

thanks this is very timely. I had to add an additional check - some data was not serialized and just a string of one question (very old data ~2006). Edge case so accepting this will be lost.

	public function get_choices(): array
	{
		$choices = json_decode($this->_data['choices'], true);
		
		# If json_decode fails, try unserialize as a fallback
		if (json_last_error() !== JSON_ERROR_NONE)
		{
			$choices = @unserialize($this->_data['choices']);
			
			# If the result is a proper array update the database to use JSON
			if ( is_array($choices) )
			{
				$this->choices = $choices;
				$this->save();
			}		
		}
		
		if ( !is_array($choices) )
		{
			$choices = [];
		}
				
		return $choices;
	}