forked from GNUsocial/gnu-social
[DOCUMENTATION] Add high level code walkthrough to developer docs
This commit is contained in:
parent
d9a3ecb116
commit
120571fa42
@ -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)
|
||||||
|
@ -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.
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user