You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

211 lines
6.7 KiB

<?php
/**
* Créer les liens «Source» (liens vers Trac ou Redmine ou autre) sur chaque élément
*/
namespace autodoc\Plugin\Core\Compiler\Pass;
use autodoc\Plugin\Core\Compiler\Pass\VcsInformations\VcsInformationsAbstract;
use autodoc\Plugin\Core\Compiler\Pass\VcsViewer\DefaultViewer;
use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\Tag\LinkDescriptor;
use Cilex\Application;
/**
* Collecter les erreurs
*/
class VcsLinkBuilder implements CompilerPassInterface
{
const COMPILER_PRIORITY = 8790;
/**
* L'application
*
* Pour retrouver la source des fichiers sur le disque
*
* @var Application
**/
private $app;
/**
* Constructeur
*
* @param Application $app
**/
public function __construct(Application $app) {
$this->app = $app;
}
/**
* {@inheritDoc}
*/
public function getDescription()
{
return '[Autodoc] Create "source" link on each element';
}
/**
* {@inheritDoc}
*/
public function execute(ProjectDescriptor $project)
{
# $is_spip = SpipShare::is_spip($project);
// retrouver la racine des sources locales…
$root = $this->getRoot($project);
// parcourir les fichiers
foreach ($project->getFiles() as $file) {
$line = $file->getLine();
$path = $file->getPath();
$dir = dirname($path);
if ($dir == '.') {
$dir = '';
}
$vcs_infos = VcsInformations\Finder::find($root, $dir);
$vcs_viewer = $this->getVcsViewer($vcs_infos);
$vcs_viewer->setFilename($file->getName());
// ajouter les tags source
$this->addSourceTag($file, $vcs_viewer);
// fonctions & constantes
foreach ($file->getFunctions() as $function) {
$this->addSourceTag($function, $vcs_viewer);
}
foreach ($file->getConstants() as $constant) {
$this->addSourceTag($constant, $vcs_viewer);
}
// classes, interfaces, traits
foreach (array('getClasses', 'getInterfaces', 'getTraits') as $get) {
foreach ($file->$get() as $class) {
$this->addSourceTag($class, $vcs_viewer);
foreach ($class->getMethods() as $method) {
$this->addSourceTag($method, $vcs_viewer);
}
foreach ($class->getConstants() as $constant) {
$this->addSourceTag($constant, $vcs_viewer);
}
foreach ($class->getProperties() as $property) {
$this->addSourceTag($property, $vcs_viewer);
}
}
}
}
}
/**
* Obtenir la racine des sources locales…
*
* Bien planquée dans le parseur.
*
* @note
* Malheureusement, le parseur n'a pas de methode `getPath()`
* On l'obtient de la propriété privée `path` par une réflexion
* sur l'instance du parseur.
*
* @param ProjectDescriptor $project
* @return bool
**/
private function getRoot(ProjectDescriptor $project) {
$parser = $this->app['parser'];
$reflectedParser = new \ReflectionClass( $parser );
$property = $reflectedParser->getProperty('path');
$property->setAccessible(true);
return $property->getValue( $parser );
}
/**
* Ajouter un tag Source sur un élément
*
* @note
* Tristement les descripteurs d'éléments n'ont pas connaissance
* du numéro de ligne du début du docblock, seulement du numéro
* de ligne de l'élément (fonction, méthode, ...)
*
* C'est ennuyant pour créer les liens vers trac ou redmine :
* ils pointent donc après le docblock éventuel.
*
* @param DescriptorAbstract $element
* @param DefaultViewer $vcsViewer
**/
private function addSourceTag(DescriptorAbstract $element, DefaultViewer $vcsViewer) {
// FIXME: (re)Trouver le début du docblock.
$vcsViewer->setLine( $element->getLine() );
$url = $vcsViewer->getUrl();
$sourceTag = new LinkDescriptor('source');
$sourceTag->setDescription("[Voir en ligne]($url)");
$sourceTag->setLink( $url );
// ajouter le tag aux autres 'source' s'il y en a (aucazou)
$sources = $element->getTags()->get('source', new Collection());
$sources->add($sourceTag);
$element->getTags()->set('source', $sources);
}
/**
* Obtenir un calculateur d'URL des sources des fichiers en ligne
*
* @param VcsInformationsAbstract $vcs_infos Informations sur le VCS
* @return DefaultViewer
**/
public function getVcsViewer(VcsInformationsAbstract $vcs_infos) {
$root = $vcs_infos->getUrlRoot();
list($viewer, $url) = $this->source_pour_humains($root);
if (is_null($viewer)) $viewer = 'DefaultViewer';
$VcsViewer = 'autodoc\Plugin\Core\Compiler\Pass\VcsViewer\\' . ucfirst($viewer);
if (!class_exists($VcsViewer)) {
throw new \Exception('Classe ' . $VcsViewer . ' introuvable.');
}
return new $VcsViewer( $vcs_infos, $url );
}
/**
* Retourne l'URL pour un humain d'une source de repository,
* si on la connait.
*
* @todo
* Rendre paramétrable en config cette liste d'URLs
*
* @param string $url_repo URL du repository (svn)
* @return array Liste : type de viewer (trac|redmine|autre, sinon null), URL (du viewer, sinon du repository).
**/
function source_pour_humains($url_repo) {
static $connus = array(
'svn://zone.spip.org/spip-zone' => array('trac', 'https://zone.spip.org/trac/spip-zone'),
'svn://trac.rezo.net/spip' => array('redmine', 'https://core.spip.net/projects/spip'),
'https://git.spip.net' => array('gitea', 'https://git.spip.net'),
'git@git.spip.net' => array('gitea', 'https://git.spip.net'),
'https://github.com' => array('github', 'https://github.com'),
'git@github.com' => array('github', 'https://github.com'),
'https://gitlab.com' => array('gitlab', 'https://gitlab.com'),
'git@gitlab.com' => array('gitlab', 'https://gitlab.com'),
);
$url_repo = (string) $url_repo;
if (isset($connus[$url_repo])) {
return $connus[$url_repo];
}
return array(null, $url_repo);
}
}