Jump to content

UPLOAD type field in 3rd-party resources


Adriano Faria

Recommended Posts

When someone uses an UPLOAD extra field type in my app, they get a 1S160/2 message error and can't download the file. So debugging here and there I noticed that the method isValidFile from the Extra Field File storage  extension is always returning FALSE because it can't find the file due to this:

JuLrC5t.png

As you can see, using Downloads as an example, it saves only the file path, while it saves the full path in my app.

Comparing Field model from Downloads and my app, I don't see any difference in the way it is done.

So the question is: where do I change that?

Link to comment
Share on other sites

8 hours ago, Adriano Faria said:

When someone uses an UPLOAD extra field type in my app, they get a 1S160/2 message error and can't download the file. So debugging here and there I noticed that the method isValidFile from the Extra Field File storage  extension is always returning FALSE because it can't find the file due to this:

JuLrC5t.png

As you can see, using Downloads as an example, it saves only the file path, while it saves the full path in my app.

Comparing Field model from Downloads and my app, I don't see any difference in the way it is done.

So the question is: where do I change that?

 

when you are saving it to the DB looks like you are using the url() method to get the URL to save, not allowing the DB save to trigger the __toString() method of the File Extension class (which will give you the path, not the URL, the URL is useless. you should be using the {file} template plugin to display the upload).

Link to comment
Share on other sites

 

1 minute ago, TheJackal84 said:

I save mine to the database like


'mycolumn' => (string) $values['my_setting']

then it saves like it shows in the downloads image

yWSIeK4.png

This is an app. It is an extension. You don’t save it to DB directly like that. You have a form and presave or something method. 

25 minutes ago, CodingJungle said:

 

when you are saving it to the DB looks like you are using the url() method to get the URL to save, not allowing the DB save to trigger the __toString() method of the File Extension class (which will give you the path, not the URL, the URL is useless. you should be using the {file} template plugin to display the upload).

It is exactly like appears on Downloads. Not sure why it doesn’t work.

Link to comment
Share on other sites

3 minutes ago, Adriano Faria said:

 

This is an app. It is an extension. You don’t save it to DB directly like that. You have a form and presave or something method. 

It is exactly like appears on Downloads. Not sure why it doesn’t work.

Mine is a app, Media uploader in my signature, can't you insert it or update the column?

if( $values = $form->values() )
		{
			\IPS\Db::i()->insert( 'mediauploader_media', array( 'show_to' => $member, 'location' => (string) $values['mu_uploadimage'], 'member_id' => $member, 'group_id' => $group_id, 'time_date' => time(), 'ext' => 0, 'private' => $values['mu_public'] ) );			
		}

location being the place its stored, I cut the rest of the code out but you should get what I mean

Cqi0fsb.png

Link to comment
Share on other sites

3 minutes ago, Adriano Faria said:

It is exactly like appears on Downloads. Not sure why it doesn’t work.

i would have to see the execution process from form to saving to be of more help, all the times i've used the upload field i've just let the __toString() get executed by the DB when it saves.

Link to comment
Share on other sites

26 minutes ago, TheJackal84 said:

Mine is a app, Media uploader in my signature, can't you insert it or update the column?


if( $values = $form->values() )
		{
			\IPS\Db::i()->insert( 'mediauploader_media', array( 'show_to' => $member, 'location' => (string) $values['mu_uploadimage'], 'member_id' => $member, 'group_id' => $group_id, 'time_date' => time(), 'ext' => 0, 'private' => $values['mu_public'] ) );			
		}

location being the place its stored, I cut the rest of the code out but you should get what I mean

Cqi0fsb.png

No, extension do not use a regular form where you can do a manual insert.

26 minutes ago, CodingJungle said:

i would have to see the execution process from form to saving to be of more help, all the times i've used the upload field i've just let the __toString() get executed by the DB when it saves.

Here you go:

- Field model (like any other app out there):

<?php
/**
 * @brief		Field Model
 * @author		<a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
 * @copyright	(c) 2001 - 2016 Invision Power Services, Inc.
 * @license		http://www.invisionpower.com/legal/standards/
 * @package		IPS Community Suite
 * @subpackage	Quizzes
 * @since		3 Oct 2013
 * @version		SVN_VERSION_NUMBER
 */

namespace IPS\quizzes;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
	header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
	exit;
}

/**
 * Field Node
 */
class _Field extends \IPS\CustomField
{
	/**
	 * @brief	[ActiveRecord] Multiton Store
	 */
	protected static $multitons;
	
	/**
	 * @brief	[ActiveRecord] Database Table
	 */
	public static $databaseTable = 'quizzes_cfields';
	
	/**
	 * @brief	[ActiveRecord] Database Prefix
	 */
	public static $databasePrefix = 'cf_';
		
	/**
	 * @brief	[Node] Order Database Column
	 */
	public static $databaseColumnOrder = 'position';

	/**
	 * @brief	[CustomField] Column Map
	 */
	public static $databaseColumnMap = array(
		'not_null'	=> 'not_null'
	);
	
	/**
	 * @brief	[Node] Node Title
	 */
	public static $nodeTitle = 'q_cfields';
	
	/**
	 * @brief	[CustomField] Title/Description lang prefix
	 */
	protected static $langKey = 'quizzes_field';

	/**
	 * @brief	[Node] Title prefix.  If specified, will look for a language key with "{$key}_title" as the key
	 */
	public static $titleLangPrefix = 'quizzes_field_';
	
	/**
	 * @brief	[CustomField] Content Table
	 */
	public static $contentDatabaseTable = 'quizzes_ccontent';

	/**
	 * @brief	[Node] ACP Restrictions
	 */
	protected static $restrictions = array(
		'app'		=> 'quizzes',
		'module'	=> 'quizzes',
		'prefix'	=> 'fields_',
	);

	/**
	 * @brief	[CustomField] Editor Options
	 */
	public static $editorOptions = array( 'app' => 'quizzes', 'key' => 'Quizzes' );

	/**
	 * @brief	[CustomField] FileStorage Extension for Upload fields
	 */
	public static $uploadStorageExtension = 'quizzes_QuizField';

	/**
	 * Get topic format
	 *
	 * @param	\IPS\Helpers\Form	$form	The form
	 * @return	void
	 */
	public function get_topic_format()
	{
		return $this->format;
	}

	/**
	 * [Node] Add/Edit Form
	 *
	 * @param	\IPS\Helpers\Form	$form	The form
	 * @return	void
	 */
	public function form( &$form )
	{
		parent::form( $form );
		
		if ( \IPS\Application::appIsEnabled( 'forums' ) )
		{
			$form->addHeader('quizzes_category_forums_integration');
			$form->add( new \IPS\Helpers\Form\YesNo( 'cf_topic_quizzes', $this->topic ) );
			$form->add( new \IPS\Helpers\Form\TextArea( 'pf_format', $this->id ? $this->topic_format : '', FALSE, array( 'placeholder' => "<strong>{title}:</strong> {content}" ) ) );
		}
	}
	
	/**
	 * [Node] Format form values from add/edit form for save
	 *
	 * @param	array	$values	Values from the form
	 * @return	array
	 */
	public function formatFormValues( $values )
	{
		if ( \IPS\Application::appIsEnabled( 'forums' ) AND isset( $values['cf_topic_quizzes'] ) )
		{
			$values['topic'] = $values['cf_topic_quizzes'];
			unset( $values['cf_topic_quizzes'] );
		}

		$values['search_type']			= ( $values['pf_search_type'] === NULL ) ? '' : $values['pf_search_type'];
		$values['allow_attachments']	= $values['pf_allow_attachments'];
		unset( $values['pf_search_type'] );
		unset( $values['pf_allow_attachments'] );

		return parent::formatFormValues( $values );
	}
}

- File Storage extension:

<?php
/**
 * @brief		File Storage Extension: QuizField
 * @author		<a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright	(c) Invision Power Services, Inc.
 * @license		https://www.invisioncommunity.com/legal/standards/
 * @package		Invision Community
 * @subpackage	Quizzes
 * @since		02 Oct 2017
 */

namespace IPS\quizzes\extensions\core\FileStorage;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
	header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
	exit;
}

/**
 * File Storage Extension: QuizField
 */
class _QuizField
{
	/**
	 * Count stored files
	 *
	 * @return	int
	 */
	public function count()
	{
		$count = 0;

		foreach( \IPS\Db::i()->select( '*', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) ) AS $field )
		{
			$count += \IPS\Db::i()->select( 'COUNT(*)', 'quizzes_ccontent', array( "field_{$field['cf_id']}<>? OR field_{$field['cf_id']} IS NOT NULL", '' ) )->first();
		}

		return $count;
	}

	/**
	 * Move stored files
	 *
	 * @param	int			$offset					This will be sent starting with 0, increasing to get all files stored by this extension
	 * @param	int			$storageConfiguration	New storage configuration ID
	 * @param	int|NULL	$oldConfiguration		Old storage configuration ID
	 * @throws	\UnderflowException					When file record doesn't exist. Indicating there are no more files to move
	 * @return	void|int							An offset integer to use on the next cycle, or nothing
	 */
	public function move( $offset, $storageConfiguration, $oldConfiguration=NULL )
	{
        if( !\IPS\Db::i()->select( 'COUNT(*)', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) )->first() )
        {
            throw new \Underflowexception;
        }

		foreach( \IPS\Db::i()->select( '*', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) ) AS $field )
		{
			$cfield	= \IPS\Db::i()->select( '*', 'quizzes_ccontent', array( "field_{$field['cf_id']}<>? OR field_{$field['cf_id']} IS NOT NULL", '' ), 'quiz_id', array( $offset, 1 ) )->first();
			
			try
			{
				$file = \IPS\File::get( $oldConfiguration ?: 'core_FileField', $cfield[ 'field_' . $field['cf_id'] ] )->move( $storageConfiguration );
				
				if ( (string) $file != $cfield[ 'field_' . $field['cf_id'] ] )
				{
					\IPS\Db::i()->update( 'quizzes_ccontent', array( "field_{$field['cf_id']}=?", (string) $file ), array( 'quiz_id=?', $cfield['quiz_id'] ) );
				}
			}
			catch( \Exception $e )
			{
				/* Any issues are logged */
			}
		}
	}

	/**
	 * Fix all URLs
	 *
	 * @param	int			$offset					This will be sent starting with 0, increasing to get all files stored by this extension
	 * @return void
	 */
	public function fixUrls( $offset )
	{
		if( !\IPS\Db::i()->select( 'COUNT(*)', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) )->first() )
        {
            throw new \Underflowexception;
        }

		foreach( \IPS\Db::i()->select( '*', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) ) AS $field )
		{
			$cfield	= \IPS\Db::i()->select( '*', 'quizzes_ccontent', array( "field_{$field['cf_id']}<>? OR field_{$field['cf_id']} IS NOT NULL", '' ), 'quiz_id', array( $offset, 1 ) )->first();
			
			if ( $new = \IPS\File::repairUrl( $cfield[ 'field_' . $field['cf_id'] ] ) )
			{
				\IPS\Db::i()->update( 'quizzes_ccontent', array( "field_{$field['cf_id']}=?", $new ), array( 'quiz_id=?', $cfield['quiz_id'] ) );
			}
		}
	}

	/**
	 * Check if a file is valid
	 *
	 * @param	string	$file		The file path to check
	 * @return	bool
	 */
	public function isValidFile( $file )
	{
		$valid = FALSE;
		foreach( \IPS\Db::i()->select( '*', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) ) AS $field )
		{
			try
			{
				\IPS\Db::i()->select( '*', 'quizzes_ccontent', array( "field_{$field['cf_id']}=?", (string) $file ) )->first();
				
				$valid = TRUE;
				break;
			}
			catch( \UnderflowException $e ) {}
		}

		return $valid;
	}

	/**
	 * Delete all stored files
	 *
	 * @return	void
	 */
	public function delete()
	{
		foreach( \IPS\Db::i()->select( '*', 'quizzes_cfields', array( 'cf_type=?', 'Upload' ) ) AS $field )
		{
			try
			{
				foreach( \IPS\Db::i()->select( '*', 'quizzes_ccontent', array( "field_{$field['cf_id']}<>? OR field_{$field['cf_id']} IS NOT NULL", '' ) ) as $cfield )
				{
					\IPS\File::get( 'core_FileField', $cfield[ 'field_' . $field['cf_id'] ] )->delete();
				}
			}
			catch( \Exception $e ){}
		}
	}
}

As far as I can tell, it is like Downloads, that works.

 

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

I'm talking about this:

g6viV9z.png

Files uploaded via UPLOAD extra field type.

Link to comment
Share on other sites

		foreach ( $this->container()->cfields as $field )
		{
			$helper							 = $field->buildHelper();
			if ( $helper instanceof \IPS\Helpers\Form\Upload )
			{
				$cfields[ "field_{$field->id}" ] = (string) $values[ "downloads_field_{$field->id}" ];
			}
			else
			{
				$cfields[ "field_{$field->id}" ] = $helper::stringValue( $values[ "downloads_field_{$field->id}" ] );
			}
			
			if ( $helper instanceof \IPS\Helpers\Form\Editor )
			{
				$field->claimAttachments( $this->id );
			}
		}

this is how downloads saves it custom fields, so they do check to see if it is a upload helper and then cast it as a string like @TheJackal84 been saying to do.

Link to comment
Share on other sites

That fixed it. I totally forgot to check the content item save method! >_<

Mine was:

		foreach ( $this->container()->cfields as $field )
		{
			$helper							 = $field->buildHelper();
			$cfields[ "field_{$field->id}" ] = $helper::stringValue( $values[ "quizzes_field_{$field->id}" ] );
			
			if ( $helper instanceof \IPS\Helpers\Form\Editor )
			{
				$field->claimAttachments( $this->id );
			}
		}

Thank you both.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...