Commit 3566a592 authored by Michael McAndrew's avatar Michael McAndrew
Browse files

Rewritten in Symfony3

parents
#!/usr/bin/env php
<?php
require_once dirname(__FILE__).'/../var/SymfonyRequirements.php';
$lineSize = 70;
$symfonyRequirements = new SymfonyRequirements();
$iniPath = $symfonyRequirements->getPhpIniConfigPath();
echo_title('Symfony Requirements Checker');
echo '> PHP is using the following php.ini file:'.PHP_EOL;
if ($iniPath) {
echo_style('green', ' '.$iniPath);
} else {
echo_style('warning', ' WARNING: No configuration file (php.ini) used by PHP!');
}
echo PHP_EOL.PHP_EOL;
echo '> Checking Symfony requirements:'.PHP_EOL.' ';
$messages = array();
foreach ($symfonyRequirements->getRequirements() as $req) {
/** @var $req Requirement */
if ($helpText = get_error_message($req, $lineSize)) {
echo_style('red', 'E');
$messages['error'][] = $helpText;
} else {
echo_style('green', '.');
}
}
$checkPassed = empty($messages['error']);
foreach ($symfonyRequirements->getRecommendations() as $req) {
if ($helpText = get_error_message($req, $lineSize)) {
echo_style('yellow', 'W');
$messages['warning'][] = $helpText;
} else {
echo_style('green', '.');
}
}
if ($checkPassed) {
echo_block('success', 'OK', 'Your system is ready to run Symfony projects');
} else {
echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects');
echo_title('Fix the following mandatory requirements', 'red');
foreach ($messages['error'] as $helpText) {
echo ' * '.$helpText.PHP_EOL;
}
}
if (!empty($messages['warning'])) {
echo_title('Optional recommendations to improve your setup', 'yellow');
foreach ($messages['warning'] as $helpText) {
echo ' * '.$helpText.PHP_EOL;
}
}
echo PHP_EOL;
echo_style('title', 'Note');
echo ' The command console could use a different php.ini file'.PHP_EOL;
echo_style('title', '~~~~');
echo ' than the one used with your web server. To be on the'.PHP_EOL;
echo ' safe side, please check the requirements from your web'.PHP_EOL;
echo ' server using the ';
echo_style('yellow', 'web/config.php');
echo ' script.'.PHP_EOL;
echo PHP_EOL;
exit($checkPassed ? 0 : 1);
function get_error_message(Requirement $requirement, $lineSize)
{
if ($requirement->isFulfilled()) {
return;
}
$errorMessage = wordwrap($requirement->getTestMessage(), $lineSize - 3, PHP_EOL.' ').PHP_EOL;
$errorMessage .= ' > '.wordwrap($requirement->getHelpText(), $lineSize - 5, PHP_EOL.' > ').PHP_EOL;
return $errorMessage;
}
function echo_title($title, $style = null)
{
$style = $style ?: 'title';
echo PHP_EOL;
echo_style($style, $title.PHP_EOL);
echo_style($style, str_repeat('~', strlen($title)).PHP_EOL);
echo PHP_EOL;
}
function echo_style($style, $message)
{
// ANSI color codes
$styles = array(
'reset' => "\033[0m",
'red' => "\033[31m",
'green' => "\033[32m",
'yellow' => "\033[33m",
'error' => "\033[37;41m",
'success' => "\033[37;42m",
'title' => "\033[34m",
);
$supports = has_color_support();
echo($supports ? $styles[$style] : '').$message.($supports ? $styles['reset'] : '');
}
function echo_block($style, $title, $message)
{
$message = ' '.trim($message).' ';
$width = strlen($message);
echo PHP_EOL.PHP_EOL;
echo_style($style, str_repeat(' ', $width).PHP_EOL);
echo_style($style, str_pad(' ['.$title.']', $width, ' ', STR_PAD_RIGHT).PHP_EOL);
echo_style($style, str_pad($message, $width, ' ', STR_PAD_RIGHT).PHP_EOL);
echo_style($style, str_repeat(' ', $width).PHP_EOL);
}
function has_color_support()
{
static $support;
if (null === $support) {
if (DIRECTORY_SEPARATOR == '\\') {
$support = false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
} else {
$support = function_exists('posix_isatty') && @posix_isatty(STDOUT);
}
}
return $support;
}
{
"name": "michael/civicrm.docs",
"license": "proprietary",
"type": "project",
"autoload": {
"psr-4": {
"": "src/"
},
"classmap": [
"app/AppKernel.php",
"app/AppCache.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.0.*",
"doctrine/orm": "^2.5",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3",
"symfony/monolog-bundle": "^2.8",
"sensio/distribution-bundle": "^5.0",
"sensio/framework-extra-bundle": "^3.0.2",
"incenteev/composer-parameter-handler": "^2.0"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "^3.0"
},
"scripts": {
"post-install-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
]
},
"config": {
"platform": {
"php": "5.5.9"
}
},
"extra": {
"symfony-app-dir": "app",
"symfony-bin-dir": "bin",
"symfony-var-dir": "var",
"symfony-web-dir": "web",
"symfony-tests-dir": "tests",
"symfony-assets-install": "relative",
"incenteev-parameters": {
"file": "app/config/parameters.yml"
}
}
}
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!-- http://phpunit.de/manual/4.1/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="app/autoload.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="KERNEL_DIR" value="app/" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
<exclude>
<directory>src/*Bundle/Resources</directory>
<directory>src/*/*Bundle/Resources</directory>
<directory>src/*/Bundle/*Bundle/Resources</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
<?php
namespace AppBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AppBundle extends Bundle
{
}
<?php
//
// namespace AppBundle\Controller;
//
// use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
// use Symfony\Bundle\FrameworkBundle\Controller\Controller;
// use Symfony\Component\HttpFoundation\Request;
//
// class DefaultController extends Controller
// {
// /**
// * @Route("/", name="homepage")
// */
// public function indexAction(Request $request)
// {
// // replace this example code with whatever you need
// return $this->render('default/index.html.twig', [
// 'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..'),
// ]);
// }
// }
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Parser;
//@TODO Make the errors that will occur if the slugs don't pass the regexp more obvious to the user
class PublishController extends Controller
{
/**
* @Route("/admin/publish")
*/
public function PublishInstructionsAction()
{
return $this->render('AppBundle:Publish:publish.html.twig');
}
/**
* @Route("/admin/publish/{book}/{lang}/{branch}", requirements={
* "lang":"[[:alpha:]]{2}",
* "book":"[[:alpha:]\-]+",
* "branch":"[[:alnum:]\-\.]+",
* })
*/
public function PublishAction(Request $request, $lang, $book, $branch)
{
$publisher = $this->get('publisher');
$publisher->publish($book, $lang, $branch);
$content['messages'] = $publisher->getMessages();
return $this->render('AppBundle:Publish:publish.html.twig', $content);
}
/**
* @Route("/admin/listen")
*/
public function ListenAction(Request $request)
{
$secret = $this->getParameter('secret');
if(!$request->headers->has('x-hub-signature')){
throw new \Exception("Missing 'X-Hub-Signature' header.");
}
$signature = $request->headers->get('X-Hub-Signature');
list($algo, $hash) = explode('=', $signature, 2);
$body = $request->getContent();
$payloadHash = hash_hmac($algo, $body, $secret);
if ($hash !== $payloadHash) {
throw new \Exception("Bad secret.");
}
$event = $request->headers->get('X-GitHub-Event');
$payload = json_decode($body);
$yaml = new Parser();
$finder = new Finder();
foreach ($finder->in($this->get('kernel')->getRootDir().'/config/books')->name("*.yml") as $file) {
$books[basename($file, '.yml')] = $yaml->parse(file_get_contents("$file"));
}
$processor = $this->get('github.hook.processor');
$processor->process($event, $payload, $books);
if(!$processor->published){
return new Response('OK', 200);
}
$messages = $processor->getMessages();
$details = $processor->getDetails();
$subject = $processor->getSubject();
;
$mail = \Swift_Message::newInstance()
->setSubject("[CiviCRM docs] $subject")
->setFrom('docs@civicrm.org')
->setTo('michaelmcandrew@thirdsectordesign.org')
->setBody($this->renderView( 'Emails/notify.html.twig', array('details' => $details, 'messages' => $messages) ), 'text/html');
//->setBody('hello');
$this->get('mailer')->send($mail);
return new Response('OK', 200);
}
}
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Yaml\Parser;
class ReadController extends Controller
{
/**
* @Route("/{path}")
*/
public function RedirectAction($path)
{
//If path is the recognised name of a book, then redirect to the stable path of the book, else redirect to the home page.
$k = $this->get('kernel');
$fs = $this->get('filesystem');
$bookConfigFile = $k->getRootDir()."/config/books/{$path}.yml";
if (!$fs->exists($bookConfigFile)) {
return $this->redirect("/");
}
return $this->redirect("{$path}/en/stable");
}
// $k = $this->get('kernel');
// if(substr( $path, -1)=='/'){
// return new Response(file_get_contents($k->getCacheDir()."/{$path}index.html"));
// }else{
// return new Response(file_get_contents($k->getCacheDir()."/$path"));
// }
// //return $this->render('AppBundle:Read:read.html.twig');
/**
* @Route("/")
*/
public function HomeAction()
{
return $this->render('AppBundle:Read:home.html.twig');
}
// $k = $this->get('kernel');
// if(substr( $path, -1)=='/'){
// return new Response(file_get_contents($k->getCacheDir()."/{$path}index.html"));
// }else{
// return new Response(file_get_contents($k->getCacheDir()."/$path"));
// }
// //return $this->render('AppBundle:Read:read.html.twig');
}
{% extends "::base.html.twig" %}
{% block title %}Listener{% endblock %}
{% block body %}
<h1>I'm listening...</h1>
{% endblock %}
{% extends "::base.html.twig" %}
{% block title %}CiviCRM Documentation: Publish{% endblock %}
{% block body %}
<h1>Publish documentation</h1>
<p>For help and more information, you can consult the <a href="https://github.com/civicrm/civicrm-docs">documentation documentation,</a> and the <a href="/log">logs of the publishing process</a>.
{% if messages is defined %}
<h2>Results</h2>
{% for message in messages %}
<p>
<span class="message message-{{ message.label|lower }}">{{ message.label }}:</span>
{{ message.content|raw }}</p>
{% endfor %}
{% endif %}
{% endblock %}
{% extends "::base.html.twig" %}
{% block title %}CiviCRM Documentation: Publish{% endblock %}
{% block body %}
<h1>Read documentation</h1>
{% endblock %}
<?php
namespace AppBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class NotifyControllerTest extends WebTestCase
{
public function testNotify()
{
$client = static::createClient();
$crawler = $client->request('GET', '/Notify');
}
}
<?php
namespace AppBundle\Utils;
class GitHubHookProcessor{
protected $messages = array();
protected $recipients = array();
public $published = false;
public function __construct($publisher){
$this->publisher = $publisher;
}
function process($event, $payload, $books){
$this->books = $books;
switch ($event) {
case 'pull_request':
$this->pullRequest($payload);
break;
case 'push':
$this->push($payload);
break;
}
}
function PullRequest($payload){
if($payload->action != 'closed' OR !$payload->pull_request->merged){
return;
}
$branch = $payload->pull_request->base->ref;
$repo = $payload->repository->html_url;
foreach ($this->books as $bookName => $bookConfig) {
foreach ($bookConfig['langs'] as $bookLang => $bookLangDetails) {
if($bookLangDetails['repo'] == $repo){
$book = $bookName;
$lang = $bookLang;
}
}
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $payload->pull_request->commits_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json', 'User-Agent: Awesome-Octocat-App')); // Assuming you're requesting JSON
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch));
//$commits = json_decode(file_get_contents('https://api.github.com/zen'));
foreach($response as $commit){
$recipients[]=$commit->commit->author->email;
$recipients[]=$commit->commit->committer->email;
}
$recipients = array_unique($recipients);
$this->publisher->publish($book, $lang, $branch);
$this->details = array('book' => $book, 'lang' => $lang, 'branch' => $branch);
$this->published = true;
$this->subject = "Published '{$branch}' branch of '{$book}' in '{$lang}'";
$this->messages = array_merge($this->messages, $this->publisher->getMessages());
}
function Push($event){
//do something, then...
$this->publisher->publish($book, $lang, $branch);
array_merge($this->messages, $this->publisher->getMessages());
}
public function getMessages()
{
return $this->messages;
}
public function getRecipients()
{
return $this->recipients;
}
public function getSubject()
{
return $this->subject;
}
public function getDetails()
{
return $this->details;
}
}
<?php
namespace AppBundle\Utils;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Process\Process;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class Publisher{
public $bookConfigFile;
public function __construct(RequestStack $requestStack, $logger, $fs, $configDir, $reposRoot, $publishRoot){
$this->configDir = $configDir;
$this->reposRoot = $reposRoot;
$this->publishRoot = $publishRoot;
$this->baseUrl = $requestStack->getCurrentRequest()->getUriForPath('');
//$this->baseUrl = $requestStack->getCurrentRequest()->$getBaseUrl();
$this->logger = $logger;
$this->fs = $fs;
}
public function Publish($book, $lang, $branch)
{
//Attempt to load a configuration file for the book
$bookConfigFile = $this<