More Than Just Web Design | INTERNET ENGINEERING | APPLICATION | DESIGN

Overriding concrete 5.7 Core Service

Posted: 28/12/16

concrete 5.7 replaces helpers with services. It's a little tricky to override these, but not when you know how.

I had occassion recently to use concrete5's mail helper to sent a message with an attachment. Although there is an addAttachment() method, it expects a file object to be passed to it. Unfortunately that means that the file has to exist within the file manager. In my case, I was wanting to send the invoice I'd just pushed into Xero, something that Xero cannot do with its API. Writing the file to disk and importing it into the file manager seemed like far too much overhead, not to mention clagging up the file manager with extraneous files. Here's how I got around it without modifying the concrete5 core.

The essence of overriding a core service, falls in to two parts:

  1. alter the contents of application/config/app.php and
  2. add the overridden files

In my case, the mail service was the one I wanted to override. Looking in the system configuration file concrete/config/app.php, among other things is an array of providers:

'providers'           => array(
        // Router service provider
        'core_router' => 'Concrete\Core\Routing\RoutingServiceProvider',
 
        'core_file'                   => '\Concrete\Core\File\FileServiceProvider',
        'core_encryption'             => '\Concrete\Core\Encryption\EncryptionServiceProvider',
        'core_validation'             => '\Concrete\Core\Validation\ValidationServiceProvider',
        'core_localization'           => '\Concrete\Core\Localization\LocalizationServiceProvider',
        'core_multilingual'           => '\Concrete\Core\Multilingual\MultilingualServiceProvider',
        'core_feed'                   => '\Concrete\Core\Feed\FeedServiceProvider',
        'core_html'                   => '\Concrete\Core\Html\HtmlServiceProvider',
        'core_editor'                 => '\Concrete\Core\Editor\EditorServiceProvider',
        'core_mail'                   => '\Concrete\Core\Mail\MailServiceProvider',
.....

Our application/config/app.php needs to override the core_mail service like so:

'providers' => array(
		'core_mail' => '\Application\Src\Mail\CustomMailServiceProvider'
)

We now need to add two files into a new folder application/src/Mail:

  • Service.php
  • CustomMailServiceProvider.php

As a start, the core files in concrete/src/Mail can be copied over (Service.php and MailServiceProvider.php)

CustomMailServiceProvider.php needs to be modified, changing the namespace, class name, and the class names referenced. Mine looks like this:

<?php 
namespace Application\Src\Mail;
use \Concrete\Core\Foundation\Service\Provider as ServiceProvider;
 
class CustomMailServiceProvider extends ServiceProvider {
 
	public function register() {
		$register = array(
			'helper/mail' => '\Application\Src\Mail\Service',
			'mail' => '\Application\Src\Mail\Service'
		);
 
		foreach($register as $key => $value) {
			$this->app->bind($key, $value);
		}
	}
}

The actual mail service itself only needed to add a single new function, so it extends the core. This is what I ended up with. Note the namespace has to change to match the new location, and the class name that is extended must of course be specified:

<?php
namespace Application\Src\Mail;
use Zend\Mime\Part as MimePart;
use Zend\Mime\Mime;
class Service extends \Concrete\Core\Mail\Service{
    public function addAttachmentData($content,$mimetype,$filename){
        // Create attachment.
        $mp = new MimePart($content);
        $mp->type = $mimetype;
        $mp->disposition = Mime::DISPOSITION_ATTACHMENT;
        $mp->encoding = Mime::ENCODING_BASE64;
        $mp->filename = $filename;
        // Add mimepart to attachments.
        $this->attachments[] = $mp;
    }
}

The parameters expected by this function are

  1. $content - the contents of a file, in this case a PDF invoice I just extracted from Xero
  2. $mimetype - the mime type, in this case "application/pdf"
  3. $filename - a filename that the attachment will use e.g. "INV-0010.PDF"

So, because we're extending the core, any future core updates ought to be safe and the functionality won't get lost.

References: