1

I am trying to use the Concrete Core Classes to create a user outside of the main folder structure.

For example I had a main folder called

Project One
-- concrete
-- application
-- packages
... etc etc

and another folder called user-upload. In here I have an import-users.php script.

I have a single page which has a form with a file upload element. This takes a CSV and tries to send it to the import-users.php script ready to loop through and create a new user for each row in the CSV. But I keep getting the following error when trying to use the classes:

Fatal error: Class 'Core' not found in path/user_upload/import-users.php on line 6 Call Stack: 0.2009 254592 1. {main}() path/user_upload/import-users.php:0

How can I use the class outside of the concrete5 installation?? Examples would be extremely helpful

Edit 1 Script to upload the CSV

$('#user_upload_submit').click(function () {

    var fileInput = document.getElementById('usersfile');
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('file', file);

    $.ajax({
        type: "POST",
        url: new_path+"user_upload/import-users.php",
        data: formData,
        contentType: false,
        processData: false,
        success: function (msg) {
            $('#user_result').html(msg); 
        },
        error: function (jqXHR, exception) {
            var msg = '';
            if (jqXHR.status === 0) {
                msg = 'Not connect.\n Verify Network.';
            } else if (jqXHR.status == 404) {
                msg = 'Requested page not found. [404]';
            } else if (jqXHR.status == 500) {
                msg = 'Internal Server Error [500].';
            } else if (exception === 'parsererror') {
                msg = 'Requested JSON parse failed.';
            } else if (exception === 'timeout') {
                msg = 'Time out error.';
            } else if (exception === 'abort') {
                msg = 'Ajax request aborted.';
            } else {
                msg = 'Uncaught Error.\n' + jqXHR.responseText;
            }
            alert(msg);
        }

    });
});
1stthomas
  • 731
  • 2
  • 15
  • 22
Mr Dansk
  • 766
  • 3
  • 8
  • 23
  • How are you trying to send the CSV file to the import-users.php script? – Michele Locati Nov 30 '17 at 09:46
  • Yes, that is right. However the import-users.php script is outside of the concrete and application folders in a folder called user_upload. So I'm trying to get it send the uploaded CSV via AJAX to import-users.php and then return a list of succesfully uploaded users to a table in the original file. – Mr Dansk Nov 30 '17 at 09:50
  • See the edit in my question. I am using AJAX to send the form across from a single page to a folder in the root of the concrete installation (at the same level as the concrete and application folders) – Mr Dansk Nov 30 '17 at 10:01

1 Answers1

2

First of all, you should add a validation token to every request you send to the server, and the server-side script should validate the received token.

Then, you should handle the submit in the single page controller.

Let's assume your single page is available at the /test path. The View of your single page (where you put the HTML and JavaScript) must be saved as /application/single_pages/test.php. The controller of the single page (where you put the PHP code that handles the requests) must be saved as /application/controllers/single_page/test.php.

In the /application/single_pages/test.php you have to add a validation token to the data to be sent, and you have to call the URL of a controller method (let's call it handleSubmit).

This can be done with this code:

<script>
<?php
$token = Core::make('token');
?>
$('#user_upload_submit').click(function () {
    // ...
    var formData = new FormData();
    formData.append(<?= json_encode($token::DEFAULT_TOKEN_NAME) ?>, <?= json_encode($token->generate()) ?>);
    formData.append('file', file);
    $.ajax({
        url: <?= json_encode($view->action('handleSubmit')) ?>,
        data: formData,
        // ...
    });
});
</script>

Then, your controller file (/application/controllers/single_page/test.php) can be something like this:

<?php

namespace Application\Controller\SinglePage;

use Concrete\Core\Error\UserMessageException;
use Concrete\Core\Http\ResponseFactoryInterface;
use Concrete\Core\Page\Controller\PageController;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class Test extends PageController
{
    public function handleSubmit()
    {
        $token = $this->app->make('token');
        if (!$token->validate()) {
            throw new UserMessageException($token->getErrorMessage());
        }
        $file = $this->request->files->get('file');
        if (!($file instanceof UploadedFile)) {
            throw new UserMessageException(t('File not received.'));
        }
        if (!$file->isValid()) {
            throw new UserMessageException($file->getErrorMessage());
        }
        // Process the file. It's path is $file->getPathname();
        // ...

        // Send the final response
        return $this->app->make(ResponseFactoryInterface::class)->json(true);
    }
}

The namespace of the controller and its class name must reflect the URL of the single page.

Examples:

  1. Your single page is available as /test

    • Full path to the view: /application/single_pages/test.php
    • Full path to the controller: /application/controllers/single_page/test.php
    • Namespace of the controller: Application\Controller\SinglePage
    • Class name of the controller: Test
  2. Your single page is available as /foo/bar/baz

    • Full path to the view: /application/single_pages/foo/bar/baz.php
    • Full path to the controller: /application/controllers/single_page/foo/bar/baz.php
    • Namespace of the controller: Application\Controller\SinglePage\Foo\Bar
    • Class name of the controller: Baz
Michele Locati
  • 1,655
  • 19
  • 25
  • I tried to put your code in but I'm getting a 404 error 'Requested Page not found' when the url is: url: = json_encode($view->action('handleSubmit')) ?>, – Mr Dansk Nov 30 '17 at 13:18
  • This means that concrete5 can't find your controller. The causes for this are: 1. your controller file is in the wrong directory or has a wrong file name; 2. your controller file doesn't have the right namespace and class name; If both are correct, you should try to clear the concrete5 cache. – Michele Locati Nov 30 '17 at 13:46
  • If the controller file and single page have the matching name user_upload_dw.php, will the class name need to be the same or UserUploadDw. I'm guessing the latter, maybe that is the issue? – Mr Dansk Nov 30 '17 at 14:02
  • The file names must be in snake case (`user_upload_dw` in your case); the corresponding controller class name must be in camel case (`UserUploadDw`) – Michele Locati Nov 30 '17 at 14:11
  • I am getting True returned now! It would seem we are in business :) thanks for the help. I guess now I can use the Registration classes and any other class inside that controller page? – Mr Dansk Nov 30 '17 at 14:19
  • 1
    Yes, inside the controller you have access to the whole concrete5 framework. Happy coding ;) – Michele Locati Nov 30 '17 at 15:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/160264/discussion-between-mr-dansk-and-michele-locati). – Mr Dansk Dec 01 '17 at 08:41