 
 , (*1)
, (*1)
Drupal Paranoia
Composer plugin for improving the website security for composer-based Drupal websites by moving all PHP files out of docroot., (*2)
Why use this Plugin?
The critical security issue with Coder is a good example to consider moving PHP files outside of docroot:
- SA-CONTRIB-2016-039 - Remote Code Execution
- https://twitter.com/drupalsecurity/status/753263548458004480, (*3)
More related links:
- Moving all PHP files out of the docroot
- #1672986: Option to have all php files outside of web root, (*4)
Requirements
Except for Windows, this plugin should work on environments that have Composer support. Do you use Windows? Help us., (*5)
Installation
Make sure you have a based drupal-composer/drupal-project project created., (*6)
Rename your current docroot directory to /app., (*7)
cd drupal-project-root
mv web app
Update the composer.json of your root package with the following values:, (*8)
"extra": {
    "drupal-paranoia": {
        "app-dir": "app",
        "web-dir": "web"
    },
    "installer-paths": {
        "app/core": ["type:drupal-core"],
        "app/libraries/{$name}": ["type:drupal-library"],
        "app/modules/contrib/{$name}": ["type:drupal-module"],
        "app/profiles/contrib/{$name}": ["type:drupal-profile"],
        "app/themes/contrib/{$name}": ["type:drupal-theme"],
        "drush/contrib/{$name}": ["type:drupal-drush"]
    }
}
Explaining:
- /app folder: Drupal full installation.
- /web folder: Will contain only symlinks of the assets files and PHP stub files (index.php, install.php, etc) from the /app folder., (*9)
Use composer require ... to install this Plugin on your project., (*10)
composer require drupal-composer/drupal-paranoia:~1
Done! The plugin and the new docroot are now installed., (*11)
Asset file types
The asset files are symlinked from /app to /web folder., (*12)
Default asset file types are provided by the plugin:, (*13)
robots.txt
.htaccess
*.css
*.eot
*.ico
*.gif
*.jpeg
*.jpg
*.js
*.map
*.otf
*.png
*.svg
*.ttf
*.woff
*.woff2
To extend the list of assets file types you can use the asset-files config:, (*14)
"extra": {
    "drupal-paranoia": {
        "app-dir": "app",
        "web-dir": "web",
        "asset-files": [
            "somefile.txt",
            "*.md"
        ]
    },
    "..."
}
If you need to modify the list you can use the post-drupal-set-asset-file-types event:, (*15)
"scripts": {
    "post-drupal-set-asset-file-types": [
        "DrupalProject\\composer\\ScriptHandler::setAssetFileTypes"
    ],
    "..."
},
<?php
/**
 * @file
 * Contains \DrupalProject\composer\ScriptHandler.
 */
namespace DrupalProject\composer;
use DrupalComposer\DrupalParanoia\AssetFileTypesEvent;
class ScriptHandler {
  public static function setAssetFileTypes(AssetFileTypesEvent $event) {
    $asset_file_types = $event->getAssetFileTypes();
    // Do what you want with the asset file types.
    $event->setAssetFileTypes($asset_file_types);
  }
}
By the purpose of this plugin, the following files types are not allowed and if listed they will be ignored:, (*16)
*.inc
*.install
*.module
*.phar
*.php
*.profile
*.theme
Exclude paths
With the drupal-paranoia option excludes, you can provide paths that should not be symlinked or stubbed to /web folder. The plugin provides no excludes by default., (*17)
"extra": {
    "drupal-paranoia": {
        "app-dir": "app",
        "web-dir": "web",
        "excludes": [
            "core/install.php",
            "sites/simpletest"
        ]
    },
    "..."
}
NOTE: Consider to exclude /install.php from your site. There are security concerns when this URL is publicly available, it can be used to create a list of contributed modules existing on the site.
You can exclude it via plugin as described above or via .htaccess rules. 
- DO#2840973: Install system should not produce PHP errors
- https://www.drupalxray.com, (*18)
Web server docroot
Change the document root config of your web server to point to /web folder., (*19)
Plugin events
This plugin fires the following named event during its execution process:, (*20)
- 
drupal-paranoia-post-command-run: Occurs after the command drupal:paranoiais executed.
Example of event subscriber
<?php
namespace MyVendor;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use DrupalComposer\DrupalParanoia\PluginEvents as DrupalParanoiaPluginEvents;
class MyClass implements PluginInterface, EventSubscriberInterface
{
    protected $composer;
    protected $io;
    public function activate(Composer $composer, IOInterface $io)
    {
        $this->composer = $composer;
        $this->io = $io;
    }
    public static function getSubscribedEvents()
    {
        return array(
            DrupalParanoiaPluginEvents::POST_COMMAND_RUN => 'postDrupalParanoiaCommand',
        );
    }
    public function postDrupalParanoiaCommand(CommandEvent $event) {
        // Add your custom action.
    }
}
Local development
Every time you install or update a Drupal package via Composer, the /web folder will be recreated., (*21)
composer require drupal/devel:~1.0
> drupal-paranoia: docroot folder has been rebuilt.
When working with themes, CSS and JS for example, it may be necessary to rebuild the folder manually to symlink the new assets., (*22)
composer drupal:paranoia
Public files
This plugin assumes that the public files folder exists at app/sites/<site>/files and symlinks web/sites/<site>/files -> ../../../app/sites/<site>/files., (*23)