Invision Community 4: SEO, prepare for v5 and dormant account notifications By Matt Monday at 02:04 PM
Adriano Faria Posted October 2, 2017 Posted October 2, 2017 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: 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?
CodingJungle Posted October 2, 2017 Posted October 2, 2017 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: 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).
TheJackal84 Posted October 2, 2017 Posted October 2, 2017 I save mine to the database like 'mycolumn' => (string) $values['my_setting'] then it saves like it shows in the downloads image
Adriano Faria Posted October 2, 2017 Author Posted October 2, 2017 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 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.
TheJackal84 Posted October 2, 2017 Posted October 2, 2017 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
CodingJungle Posted October 2, 2017 Posted October 2, 2017 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.
Adriano Faria Posted October 2, 2017 Author Posted October 2, 2017 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 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: Files uploaded via UPLOAD extra field type.
CodingJungle Posted October 2, 2017 Posted October 2, 2017 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.
Adriano Faria Posted October 3, 2017 Author Posted October 3, 2017 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.
newbie LAC Posted October 3, 2017 Posted October 3, 2017 10 hours ago, Adriano Faria said: - File Storage extension: contains 2 references to core_FileField
Adriano Faria Posted October 3, 2017 Author Posted October 3, 2017 2 minutes ago, newbie LAC said: contains 2 references to core_FileField Just like the one in Downloads. It’s working fine after change the saving method in the item.
newbie LAC Posted October 3, 2017 Posted October 3, 2017 52 minutes ago, Adriano Faria said: Just like the one in Downloads It's wrong. For Downloads should be downloads_FileField
Adriano Faria Posted October 3, 2017 Author Posted October 3, 2017 5 minutes ago, newbie LAC said: It's wrong. For Downloads should be downloads_FileField Ok. Did you submit a bug so they can fix it?
newbie LAC Posted October 3, 2017 Posted October 3, 2017 6 minutes ago, Adriano Faria said: Did you submit a bug so they can fix it? No.
Recommended Posts
Archived
This topic is now archived and is closed to further replies.