public function getFileFromString($string, $directory, $extensions = array()): string
    {
        $directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : $this->directory).DS);

        if (strpbrk($directory, "\\/?%*:|\"<>") === TRUE || strpbrk($string, "\\/?%*:|\"<>") === TRUE)
        {
            throw new LayoutException('Could not get file. Invalid file string', 1);
        }

        if (!file_exists($directory)) {
            throw new LayoutException('Could not get file. Directory does not exist', 1);
        }

        // Set the file name and location
        $layoutSelector = explode('/', $string);
        if (count($layoutSelector) == 1) {
            $layoutSelector = 'layout.'.$layoutSelector[0];
        } else {
            // Get last file
            $file = end($layoutSelector);

            // Reset to start
            reset($layoutSelector);

            // Remove last value
            array_pop($layoutSelector);

            $layoutSelector[] = 'layout.'.$file;

            // And create the final value
            $layoutSelector = implode(DS, $layoutSelector);
        }

        // Then try and select a file
        $fileSelected = false;
        $selectedFile = null;
        foreach ($extensions as $extension) {
            $file = $directory.$layoutSelector.'.'.strtolower($extension);
            $file = preg_replace('#/+#', '/', $file);
            if (file_exists($file) && !$fileSelected) {
                $selectedFile = $file;
                $fileSelected = true;
                Logger::log("Found matching file: '".$file."'");
            } elseif (file_exists($file) && $fileSelected) {
                throw new LayoutException('Could not select template. Multiple valid extensions detected. Can not choose.', 1);
            }
        }

        // And choose what to output
        if (!$fileSelected) {
            throw new LayoutException('Could not select template. No matching file found.');
        }

        return $selectedFile;
    }