[DOCUMENTATION] Add high level code walkthrough to developer docs

This commit is contained in:
Hugo Sales 2021-04-30 20:16:42 +00:00
parent 353595eb97
commit e9a96f1c9b
Signed by: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0
3 changed files with 42 additions and 31 deletions

View File

@ -1,5 +1,6 @@
# Summary # Summary
- [High level view](./high_level.md)
- [Architecture and Paradigms](./architecture.md) - [Architecture and Paradigms](./architecture.md)
- [Plugins](./plugins.md) - [Plugins](./plugins.md)
- [Event Handlers](./plugins/no_docker_shell.md) - [Event Handlers](./plugins/no_docker_shell.md)

View File

@ -1,19 +1,19 @@
### Entrypoint # GNU social at a high level
GNU social's entrypoint is the `public/index.php` script, which gets GNU social's execution begins at `public/index.php`, which gets
called by the webserver for all requests. This is handled by the called by the webserver for all requests. This is handled by the
webserver itself, which translates a `GET /foo` to `GET webserver itself, which translates a `GET /foo` to `GET
/index.php?p=foo`. This feature is called 'fancy URLs', as it was in V2. /index.php?p=foo`. This feature is called 'fancy URLs', as it was in V2.
The `index` script handles all the initialization of the Symfony The `index` script handles all the initialization of the Symfony
framework and social itself. It reads configuration from `.env` or any framework and social itself. It reads configuration from `.env` or any
`.env.*` file at the project root. The `index` script creates a `.env.*`, as well as `social.yaml` and `social.local.yaml` files at
`Kernel` object, which is defined on the `src/Kernel.php` file. This the project root. The `index` script creates a `Kernel` object, which
is the part where the code we control starts; the `Kernel` constructor is defined in `src/Kernel.php`. This is the part where the code we
creates the needed constants, sets the timezone to UTC and the string control starts; the `Kernel` constructor creates the needed constants,
encoding to UTF8. The other functions in this class get called by the sets the timezone to UTC and the string encoding to UTF8. The other
Symfony framework at the appropriate times. We will come back to this functions in this class get called by the Symfony framework at the
file. appropriate times. We will come back to this file.
### Registering services ### Registering services
@ -26,14 +26,14 @@ former event, as described in the docs:
> Request or return a Response early to stop the handling of the > Request or return a Response early to stop the handling of the
> request. > request.
The latter, is launched on the `bin/console` script is used. The latter, is launched when the `bin/console` script is used.
In both cases, these events call the `register` function, which In both cases, these events call the `register` function, which
creates static references for the logging, event and translation creates static references for the services such as logging, event and
services. This is done so these services can be used via static translation. This is done so these services can be used via static
function calls, which is much less verbose and more accessible than function calls, which is much less verbose and more accessible than
the way the framework recommends. This function also loads all the the way the framework recommends. This function also loads all the
Modules and Plugins, which like in V2, are components that aren't Components and Plugins, which like in V2, are modules that aren't
directly connected to the core code, being used to implement internal directly connected to the core code, being used to implement internal
and optional functionality respectively, by handling events launched and optional functionality respectively, by handling events launched
by various parts of the code. by various parts of the code.
@ -42,20 +42,22 @@ by various parts of the code.
Going back to the `Kernel`, the `build` function gets called by the Going back to the `Kernel`, the `build` function gets called by the
Symfony framework and allows us to register a 'Compiler Pass'. Symfony framework and allows us to register a 'Compiler Pass'.
Specifically, we register the `SchemaDefPass` from the Specifically, we register
`src/DependencyInjection/Compiler/SchemaDefPass.php` file, which adds `App\DependencyInjection\Compiler\SchemaDefPass` and
`App\DependencyInjection\Compiler\ModuleManagerPass`. The former adds
a new 'metadata driver' to Doctrine. The metadata driver is a new 'metadata driver' to Doctrine. The metadata driver is
responsible for loading database definitions. We keep the same method responsible for loading database definitions. We keep the same method
as in V2, which was that each 'Entity' has a `schemaDef` static as in V2, where each 'Entity' has a `schemaDef` static function which
function which returns an array describing the database. returns an array with the database definition. The latter handles the
loading of modules (components and plugins).
This definition is handled by the `SchemaDefDriver` class from This datbase definition is handled by the `SchemaDefPass` class, which
`src/Util/SchemaDefDriver.php` file, which extends `StaticPHPDriver` extends `Doctrine\Persistence\Mapping\Driver\StaticPHPDriver`. The
and replaces the methods `loadMetadata` with `schemaDef`. The function function `loadMetadataForClass` is called by the Symfony
`loadMetadataForClass` function is called by the Symfony framework for framework for each file in `src/Entity/`. It allows us to call the
each file in `src/Entity/`. It allows us to call the `schemaDef` `schemaDef` function and translate the array definition to Doctrine's
function and translate the array definition to Doctrine's internal internal representation. The `ModuleManagerPass` later uses this class
representation. to load the entity definitions from each plugin.
### Routing ### Routing
@ -66,17 +68,24 @@ routes with an interface similar to V2's `connect`, except it requires
an extra identifier as the first argument. This identifier is used, an extra identifier as the first argument. This identifier is used,
for instance, to generate URLs for each route. Each route connects an for instance, to generate URLs for each route. Each route connects an
URL path to a Controller, with the possibility of taking arguments, URL path to a Controller, with the possibility of taking arguments,
which are passed to the `__invoke` method of the respective which are passed to the `__invoke` method of the respective controller
controller. The controllers are defined in `src/Controller/` and are or the given method. The controllers are defined in `src/Controller/`
or `plugins/*/Controller` or `components/*/Controller` and are
responsible for handling a request and return a Symfony `Response` responsible for handling a request and return a Symfony `Response`
object (subject to change, in order to abstract HTML vs JSON output). object or an array that gets converted to one (subject to change, in
order to abstract HTML vs JSON output).
This array conversion is handled by `App\Core\Controller`, along with
other aspects, such as firing events we use. It also handles
responding with the appropriate requested format, such as HTML or
JSON, with what the controller returned.
### End to end ### End to end
The next steps are handled by the Symfony framework which creates a The next steps are handled by the Symfony framework which creates a
`Request` object from the HTTP request, and then a corresponding `Request` object from the HTTP request, and then a corresponding
`Response` is created by calling the `Kernel::handle` method, which `Response` is created by `App\Core\Controller`, which matches the
matches the appropriate route and thus calls it's controller. appropriate route and thus calls it's controller.
### Performance ### Performance
@ -85,4 +94,5 @@ and would be too slow. Fortunately, Symfony has a 'compiler' which
caches and optimizes the code paths. In production mode, this can be caches and optimizes the code paths. In production mode, this can be
done through a command, while in development mode, it's handled on done through a command, while in development mode, it's handled on
each request if the file changed, which has a performance impact, but each request if the file changed, which has a performance impact, but
obviously makes development easier. obviously makes development easier. In addition, we cache all the
module loading.

View File

@ -106,7 +106,7 @@ class Controller extends AbstractController implements EventSubscriberInterface
break; break;
case 'json': case 'json':
$event->setResponse(new JsonResponse($this->vars)); $event->setResponse(new JsonResponse($this->vars));
// no break break;
default: default:
throw new BadRequestHttpException('Unsupported format', null, 406); throw new BadRequestHttpException('Unsupported format', null, 406);
} }