picorose/docfx-php

Parser for generating DocFx v2 yaml files from php classes

v1.2.0 2023-07-16 11:36 UTC

This package is auto-updated.

Last update: 2024-04-16 13:33:53 UTC


README

Latest Stable Version PHP Version Require License Total Downloads

DocFX PHP

This library helps you produce a YAML representation of your php classes, which can be integrated into DocFx.

DocFX-php only supports DocFX v2. It has not been tested on newer versions.

Disclaimer This project was mostly created for personal use. It has not been thoroughly tested and it may miss some features. I also have no plans of maintaining this project on the long-term. Use at your own discretion.

Getting started

Dependencies

  • php: >= 8.1
  • nikic/php-parser: ^4.13
  • symfony/yaml: ^6
  • phpdocumentor/reflection-docblock: ^5
  • maennchen/zipstream-php: ^2.1

Installation

DocFX-php is available on Packagist. It is therefore recommended to install the library via Composer.

To get started execute the following command in your project

composer require --dev picorose/docfx-php

or add this one line to your composer.json

"picorose/docfx-php": "^1.0"

Alternatively you can download the latest version as a zip file and manually include it in your project. Keep in mind that you will have to manually include each file when you want to use the library as well as all its dependencies.

The following snippet shows one way to include all the files in the source folder without having to manually specify each file:

<?php
function loadFiles(string $path) {
    if (!is_dir($path))
        return;

    // Loop through each file in the given path
    foreach (scandir($path) as $file) {
        if ($file == "." || $file == "..")
            continue;
            
        // Only load php files
        if (strlen($file) > 4 && strtolower(substr($file, -4)) == ".php")
            require_once realpath($path) . "/$file";
            
        // Recursively load files in sub-directories
        if (is_dir($file))
            loadFiles($path . "/$file");
    }
}

loadFiles("src");

Usage

Using the command line tool

The easiest way to parse classes is to use the command line tool. If the project is installed via composer, there will be a vendor/bin/docfx-php file.

> vendor/bin/docfx-php help
DocFX-php v1.2.0
Copyright (c) 2022 Picorose
This is opensource software under the MIT license.

    Usage: docfx-php <subcommand> [<args>]
    Example: docfx-php build project/src -o project.zip -ns "com\\Picorose\\Example"

Do 'docfx-php help <command>' to read more about a specific subcommand.

    build                  : Build the yaml files for a project
    help, -h, --help       : Show a help page for a subcommand or this command
    version, -v, --version : Show the current version of the tool 

The tool is pretty straight forward and offers help where necessary. An example usage could be:

> vendor/bin/docfx-php build src -o target/myProject.zip -ns com\\Picorose\\Examples
Successfully parsed classes! File was saved to '/home/user/Documents/target/myProject.zip'

Using php

First of all make sure the classes you'd like to parse are loaded by including them with require, require_once or include. For these examples we'll be referencing the IAnimal classes in the examples folder of this project.

<?php
// Load composer dependencies
require_once "PATH/TO/VENDOR/autoload.php";

// Load model classes
loadFiles("Models");

Parsing php classes and namespaces is very simple. There's 3 ways to serialize classes:

<?php
use \com\Picorose\DocFx\ClassParser;

// Parse a single class into a managed reference. This will generate a single ManagedReference instance 
$managedReference = ClassParser::parseClass("com\\Picorose\\Examples\\Dog");
$yaml = $managedReference->toYaml();

// Parse all classes in the given namespace. In addition to generating ManagedReference instances for each class, this
// will also generate a TableOfContents instance and a ManagedReference instance for the namespace itself
$namespace = ClassParser::parseNamespace("com\\Picorose\\Examples");
$yamlFiles = [];
foreach ($namespace as $obj)
    $yamlFiles[] = $obj->toYaml();

// Does the same as the previous method, except that it will also convert the resulting objects into yaml files, package
// them all in a zip file and set the headers for downloading the zip file
ClassParser::parseNamespaceAsZip("com\\Picorose\\Examples");

The yaml produced for the Dog class should look something like this:

### YamlMime:ManagedReference
items:
  -
    uid: com.Picorose.Examples.Dog
    id: Dog
    parent: com.Picorose.Examples
    children:
      - 'com.Picorose.Examples.Dog.__construct(Human,string,Color,string)'
      - com.Picorose.Examples.Dog.getColor()
      - com.Picorose.Examples.Dog.getBreed()
      - com.Picorose.Examples.Dog.doesEat(IAnimal)
      - com.Picorose.Examples.Dog.mixedVal
      - com.Picorose.Examples.Dog.type
      - com.Picorose.Examples.Dog.VARIABLE
    langs:
      - php
    name: Dog
    nameWithType: Dog
    fullName: com\Picorose\Examples\Dog
    type: Class
    namespace: com\Picorose\Examples
    assemblies:
      - php
    syntax:
      content: 'class Dog extends Pet'
    inheritance:
      - com.Picorose.Examples.Pet
    implements:
      - com.Picorose.Examples.IAnimal
    inheritedMembers:
      - com.Picorose.Examples.Pet.getOwner()
      - com.Picorose.Examples.Pet.getName()
      - com.Picorose.Examples.Pet.toArray()
    summary: "Represents human's best friend, a dog"
  -
    uid: 'com.Picorose.Examples.Dog.__construct(Human,string,Color,string)'
    id: '__construct(Human,string,Color,string)'
    parent: com.Picorose.Examples.Dog
    langs:
      - php
    name: '__construct(?Human $owner, ?string $name, Color $color, string $breed)'
    nameWithType: 'Dog->__construct(?Human $owner, ?string $name, Color $color, string $breed)'
    fullName: 'com\Picorose\Examples\Dog->__construct(?Human $owner, ?string $name, Color $color, string $breed)'
    type: Constructor
    namespace: com\Picorose\Examples
    assemblies:
      - php
    syntax:
      content: 'public function __construct(?Human $owner, ?string $name, Color $color, string $breed)'
      parameters:
        -
          id: owner
          type: com.Picorose.Examples.Human
          allowsNull: true
          description: 'The owner of the dog'
        -
          id: name
          type: string
          allowsNull: true
          description: 'The name of the dog'
        -
          id: color
          type: com.Picorose.Examples.Color
          description: 'The fur color of the dog'
        -
          id: breed
          type: string
          description: 'The breed of the dog'
    modifiers:
      - public
    summary: 'Main constructor for the Dog class'
  -
    uid: com.Picorose.Examples.Dog.getColor()
    id: getColor()
    parent: com.Picorose.Examples.Dog
    langs:
      - php
    name: getColor()
    nameWithType: Dog->getColor()
    fullName: com\Picorose\Examples\Dog->getColor()
    type: Method
    namespace: com\Picorose\Examples
    assemblies:
      - php
    syntax:
      content: 'public function getColor(): Color'
      return:
        type: com.Picorose.Examples.Color
        description: 'The fur color of the dog'
    modifiers:
      - public
  -
    uid: com.Picorose.Examples.Dog.getBreed()
    id: getBreed()
    parent: com.Picorose.Examples.Dog
    langs:
      - php
    name: getBreed()
    nameWithType: Dog->getBreed()
    fullName: com\Picorose\Examples\Dog->getBreed()
    type: Method
    namespace: com\Picorose\Examples
    assemblies:
      - php
    syntax:
      content: 'public function getBreed(): string'
      return:
        type: string
        description: 'The breed of the dog'
    modifiers:
      - public
  -
    uid: com.Picorose.Examples.Dog.doesEat(IAnimal)
    id: doesEat(IAnimal)
    parent: com.Picorose.Examples.Dog
    langs:
      - php
    name: 'doesEat(IAnimal $other)'
    nameWithType: 'Dog->doesEat(IAnimal $other)'
    fullName: 'com\Picorose\Examples\Dog->doesEat(IAnimal $other)'
    type: Method
    namespace: com\Picorose\Examples
    assemblies:
      - php
    syntax:
      content: 'public function doesEat(IAnimal $other): bool'
      return:
        type: bool
        description: 'True if the animal would eat the animal'
      parameters:
        -
          id: other
          type: com.Picorose.Examples.IAnimal
          description: 'The animal to be eaten'
    modifiers:
      - public
    summary: 'Checks if the animal would eat another animal'
  -
    uid: com.Picorose.Examples.Dog.mixedVal
    id: mixedVal
    name: mixedVal
    type: Field
    assemblies:
      - php
    syntax:
      content: 'public mixed $mixedVal'
      return:
        type: mixed
  -
    uid: com.Picorose.Examples.Dog.type
    id: type
    name: type
    type: Field
    assemblies:
      - php
    syntax:
      content: 'public string $type = "Meh"'
      return:
        type: string
  -
    uid: com.Picorose.Examples.Dog.VARIABLE
    id: VARIABLE
    name: VARIABLE
    type: Field
    assemblies:
      - php
    syntax:
      content: 'const VARIABLE = "Blegh"'
references:
  -
    uid: com.Picorose.Examples.Human
    name: Human
    fullName: com\Picorose\Examples\Human
    nameWithType: Human
  -
    uid: string
    name: string
    fullName: string
    nameWithType: string
    isExternal: true
  -
    uid: com.Picorose.Examples.Color
    name: Color
    fullName: com\Picorose\Examples\Color
    nameWithType: Color
  -
    uid: com.Picorose.Examples.IAnimal
    name: IAnimal
    fullName: com\Picorose\Examples\IAnimal
    nameWithType: IAnimal
  -
    uid: bool
    name: bool
    fullName: bool
    nameWithType: bool
    isExternal: true
  -
    uid: com.Picorose.Examples.Pet.getOwner()
    name: getOwner()
    fullName: com\Picorose\Examples\Pet->getOwner()
    nameWithType: Pet->getOwner()
  -
    uid: com.Picorose.Examples.Pet.getName()
    name: getName()
    fullName: com\Picorose\Examples\Pet->getName()
    nameWithType: Pet->getName()
  -
    uid: com.Picorose.Examples.Pet.toArray()
    name: toArray()
    fullName: com\Picorose\Examples\Pet->toArray()
    nameWithType: Pet->toArray()
  -
    uid: mixed
    name: mixed
    fullName: mixed
    nameWithType: mixed
    isExternal: true
memberType: SeparatePages

Deploying to DocFX

If you don't have a DocFX project set up yet, you can follow these simple steps to get a basic project up and running with the yaml files generated from the ClassParser.

  • Download the DocFX executables. Make sure you download DocFX v2
  • Initialize a new DocFX project: docfx init -q
  • Generate yaml files for your classes and place them in the api folder of the docfx_project folder that was just created
  • Build the static site: docfx build docfx_project/docfx.json
  • Serve the static site with the builtin webserver: docfx serve docfx_project/_site
  • Your documentation will be available at http://localhost:8080/

PHP Xref

An xrefmap.yml file is available for native PHP references. This file makes sure that native php types such as string, mixed, mysqli_result etc. link to the relevant PHP documentation.

It is available via https://picorose.com/assets/uploads/xrefmap.yml or in the refs folder of this project.

To start using it, simply add a link to the xrefmap.yml file in the build -> xref section of your docfx.json file:

"build": {
  "xref": [ "https://picorose.com/assets/uploads/xrefmap.yml" ]
}

TODO

  • [ ] Support inline {@inheritDoc} tags
  • [ ] Support inline {@see} tags