web-dev-qa-db-fra.com

Composant personnalisé - Lier le téléchargement de fichier du contrôleur à la vue

J'ai un composant personnalisé qui prend une entrée de l'administrateur et l'affiche sous la forme d'une vue stylée personnalisée sur le front-end du site. L'un des champs est le téléchargement d'un fichier pour une image et je ne peux pas trouver/trouver en ligne comment lier le code de téléchargement du contrôleur à la vue. Tout ce que j'ai lu en ligne dit en gros: "Étudiez le code des composants de base existants" et je l'ai fait en vain.

Mon contrôleur administrateur:

class NewsShowcaseController extends JController
{
    /**
     * display task
     *
     * @return void
     */
    function display($cachable = false, $urlparams = false) 
    {
            // set default view if not set
            $input = JFactory::getApplication()->input;
            $input->set('view', $input->getCmd('view', 'NewsShowcaseAdmin'));

            // call parent behavior
            parent::display($cachable);
    }

    /*
     * The folder we are uploading into
     */
    protected $folder = '';

    /**
     * Upload one or more files
     *
     * @since 1.5
     */
    public function upload()
    {
            // Check for request forgeries
            JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));
            $params = JComponentHelper::getParams('com_media');
            // Get some data from the request
            $files                  = JRequest::getVar('Filedata', '', 'files', 'array');
            $return                 = JRequest::getVar('return-url', null, 'post', 'base64');
            $this->folder   = JRequest::getVar('folder', '', '', 'path');

            // Set the redirect
            if ($return)
            {
                    $this->setRedirect(base64_decode($return) . '&folder=' . $this->folder);
            }

            // Authorize the user
            if (!$this->authoriseUser('create'))
            {
                    return false;
            }
            if (
                    $_SERVER['CONTENT_LENGTH']>($params->get('upload_maxsize', 0) * 1024 * 1024) ||
                    $_SERVER['CONTENT_LENGTH']>(int)(ini_get('upload_max_filesize'))* 1024 * 1024 ||
                    $_SERVER['CONTENT_LENGTH']>(int)(ini_get('post_max_size'))* 1024 * 1024 ||
                    (($_SERVER['CONTENT_LENGTH'] > (int) (ini_get('memory_limit')) * 1024 * 1024) && ((int) (ini_get('memory_limit')) != -1))
            )
            {
                    JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                    return false;
            }
            // Input is in the form of an associative array containing numerically indexed arrays
            // We want a numerically indexed array containing associative arrays
            // Cast each item as array in case the Filedata parameter was not sent as such
            $files = array_map( array($this, 'reformatFilesArray'),
                    (array) $files['name'], (array) $files['type'], (array) $files['tmp_name'], (array) $files['error'], (array) $files['size']
            );

            // Perform basic checks on file info before attempting anything
            foreach ($files as &$file)
            {
                    if ($file['error']==1)
                    {
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                            return false;
                    }
                    if ($file['size']>($params->get('upload_maxsize', 0) * 1024 * 1024))
                    {
                            JError::raiseNotice(100, JText::_('COM_MEDIA_ERROR_WARNFILETOOLARGE'));
                            return false;
                    }

                    if (JFile::exists($file['filepath']))
                    {
                            // A file with this name already exists
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_FILE_EXISTS'));
                            return false;
                    }

                    if (!isset($file['name']))
                    {
                            // No filename (after the name was cleaned by JFile::makeSafe)
                            $this->setRedirect('index.php', JText::_('COM_MEDIA_INVALID_REQUEST'), 'error');
                            return false;
                    }
            }

            // Set FTP credentials, if given
            JClientHelper::setCredentialsFromRequest('ftp');
            JPluginHelper::importPlugin('content');
            $dispatcher     = JDispatcher::getInstance();

            foreach ($files as &$file)
            {
                    // The request is valid
                    $err = null;
                    if (!MediaHelper::canUpload($file, $err))
                    {
                            // The file can't be upload
                            JError::raiseNotice(100, JText::_($err));
                            return false;
                    }

                    // Trigger the onContentBeforeSave event.
                    $object_file = new JObject($file);
                    $result = $dispatcher->trigger('onContentBeforeSave', array('com_media.file', &$object_file, true));
                    if (in_array(false, $result, true))
                    {
                            // There are some errors in the plugins
                            JError::raiseWarning(100, JText::plural('COM_MEDIA_ERROR_BEFORE_SAVE', count($errors = $object_file->getErrors()), implode('<br />', $errors)));
                            return false;
                    }

                    if (!JFile::upload($file['tmp_name'], $file['filepath']))
                    {
                            // Error in upload
                            JError::raiseWarning(100, JText::_('COM_MEDIA_ERROR_UNABLE_TO_UPLOAD_FILE'));
                            return false;
                    }
                    else
                    {
                            // Trigger the onContentAfterSave event.
                            $dispatcher->trigger('onContentAfterSave', array('com_media.file', &$object_file, true));
                            $this->setMessage(JText::sprintf('COM_MEDIA_UPLOAD_COMPLETE', substr($file['filepath'], strlen(COM_MEDIA_BASE))));
                    }
            }

            return true;
    }

}

J'ai pris le code de téléchargement du contrôleur "fichier" du composant principal com_media.

Mon avis:

   class NewsShowcaseViewNewsShowcaseAdmin extends JView
   {
/**
 * News Showcase Admin view display method
     * @return void
     */
    function display($tpl = null) 
    {
            // Get data from the model
            $items = $this->get('Items');
            $pagination = $this->get('Pagination');
            $this->image = $this->get('Image');
            $this->description = $this->get('Description');

            // Check for errors.
            if (count($errors = $this->get('Errors'))) 
            {
                    JError::raiseError(500, implode('<br />', $errors));
                    return false;
            }
            // Assign data to the view
            $this->items = $items;
            $this->pagination = $pagination;

            // Display the template
            parent::display($tpl);
    }

}

HTML:

            <form name="upload" method="post" enctype="multipart/form-data">
                <input type="file" name="file_upload" />
                <input type="submit" value="Upload Image" />
            </form>

Je n'ai inclus aucun code pour le modèle parce que je suppose que c'est l'élément qui me manque? Je ne sais pas comment procéder pour le coder. J'ai quelques méthodes "get" dans mon modèle, mais s'agirait-il d'une méthode "set"? Ou comment appeler une fonction à partir du contrôleur et lui transmettre l'entrée de HTML/view?

4
Eric

Pour commencer, il serait probablement préférable de passer par tout cela: http://docs.joomla.org/J2.5:Developing_a_MVC_Component/Developing_a_Basic_Component . C'est beaucoup d'informations, mais cela aidera certainement à répondre à beaucoup de vos questions.


Commençons par le formulaire. Vous pouvez effectuer quelques opérations pour que cela pointe vers la fonction du contrôleur:

<form name="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file_upload" />
    <input type="submit" value="Upload Image" />
    <input type="hidden" name="option" value="com_component_name" />
    <input type="hidden" name="task" value="controller.method" />
    <?php echo JHtml::_( 'form.token' ); ?>
</form>

J'ai ajouté deux entrées cachées au formulaire. Ces deux champs acheminent les données postées. Le premier devrait correspondre à votre composant. La seconde peut être soit juste un nom de méthode (si vous routez vers la base controller.php fichier à la racine de votre composant) ou il devrait utiliser cette "syntaxe à points" pour spécifier le contrôleur et la méthode. (Votre cas serait probablement juste upload puisque cela ressemble au contrôleur de base pour moi.)

Le bit php supplémentaire à la fin ajoute un jeton CSRF pour aider à prévenir les attaques CSRF. Vous pouvez en savoir plus à ce sujet ici: http://docs.joomla.org/How_to_add_CSRF_anti-spoofing_to_forms . La partie à vérifier pour ce jeton se trouve déjà en haut de la fonction de téléchargement.


Maintenant que votre fonction de téléchargement s'exécute sur la soumission du formulaire, nous devons traiter le fichier.

Ne prenez pas la peine d’utiliser la classe JRequest. Il est déconseillé et disparaîtra bientôt. Utilisez JInput comme indiqué ici: http://docs.joomla.org/Retrieving_request_data_using_JInput .

Presque tout ce qui précède la ligne suivante n'est probablement pas nécessaire pour la tâche à accomplir. Il permet une personnalisation dont vous n'avez pas vraiment besoin pour l'instant:

$files = array_map( array($this, 'reformatFilesArray'),
    (array) $files['name'], (array) $files['type'], (array) $files['tmp_name'], (array) $files['error'], (array) $files['size']
);

Puisque nous utilisons JInput maintenant, nous pouvons le faire comme ceci:

$app = JFactory::getApplication();
$files = $app->input->files->get('file_upload');

Je crois que tout le reste de l'interating sur le tableau $ files devrait fonctionner. Vous voudrez vérifier si $ files est un tableau de fichiers ou juste un tableau à un seul niveau d'un fichier. Dans ce dernier cas, vous n'avez pas besoin de foreach.


Cela devrait suffire à cette question. Je peux presque garantir que vous aurez plus de questions. Cette question est déjà assez large, alors ne continuez pas à poser des questions à ce sujet. Au lieu de cela, n'hésitez pas à poser de nouvelles questions sur les problèmes spécifiques que vous rencontrez (ainsi qu'à effectuer une recherche plus spécifique sur ces problèmes, car il existe déjà de nombreuses ressources à ce sujet.)

4
David Fritsch