public static function handle_shortcode($arguments, $content, $parser, $shortcode, $extra = array())
    {
        // Get service URL
        if (!empty($content)) {
            $serviceURL = $content;
        } elseif (!empty($arguments['url'])) {
            $serviceURL = $arguments['url'];
        } else {
            return '';
        }

        // See https://github.com/oscarotero/Embed#example-with-all-options for service arguments
        $serviceArguments = [];
        if (!empty($arguments['width'])) {
            $serviceArguments['min_image_width'] = $arguments['width'];
        }
        if (!empty($arguments['height'])) {
            $serviceArguments['min_image_height'] = $arguments['height'];
        }

        /** @var EmbedResource $embed */
        $embed = Injector::inst()->create(Embeddable::class, $serviceURL);
        if (!empty($serviceArguments)) {
            $embed->setOptions(array_merge($serviceArguments, (array) $embed->getOptions()));
        }

        // Allow resolver to be mocked
        $dispatcher = null;
        if (isset($extra['resolver'])) {
            $dispatcher = Injector::inst()->create(
                $extra['resolver']['class'],
                $serviceURL,
                $extra['resolver']['config']
            );
        } elseif (Injector::inst()->has(DispatcherInterface::class)) {
            $dispatcher = Injector::inst()->get(DispatcherInterface::class);
        }

        if ($dispatcher) {
            $embed->setDispatcher($dispatcher);
        }

        // Process embed
        $embed = $embed->getEmbed();

        // Convert embed object into HTML
        if ($embed && $embed instanceof Adapter) {
            $result = static::embedForTemplate($embed, $arguments);
            if ($result) {
                return $result;
            }
        }

        // Fallback to link to service
        return static::linkEmbed($arguments, $serviceURL, $serviceURL);
    }