Search code examples
phpconcrete5concrete5-8.x

Concrete5 8.2.1 Using Core classes outside of concrete


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);
        }

    });
});

Solution

  • 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