diff --git a/docs/developer/src/SUMMARY.md b/docs/developer/src/SUMMARY.md index 6c49bac65c..07333c23a3 100644 --- a/docs/developer/src/SUMMARY.md +++ b/docs/developer/src/SUMMARY.md @@ -1,5 +1,6 @@ # Summary +- [High level view](./high_level.md) - [Architecture and Paradigms](./architecture.md) - [Plugins](./plugins.md) - [Event Handlers](./plugins/no_docker_shell.md) diff --git a/DOCUMENTATION/DEVELOPERS/code_walkthrough.md b/docs/developer/src/high_level.md similarity index 51% rename from DOCUMENTATION/DEVELOPERS/code_walkthrough.md rename to docs/developer/src/high_level.md index e57e9009b5..f7f9881385 100644 --- a/DOCUMENTATION/DEVELOPERS/code_walkthrough.md +++ b/docs/developer/src/high_level.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 webserver itself, which translates a `GET /foo` to `GET /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 framework and social itself. It reads configuration from `.env` or any -`.env.*` file at the project root. The `index` script creates a -`Kernel` object, which is defined on the `src/Kernel.php` file. This -is the part where the code we control starts; the `Kernel` constructor -creates the needed constants, sets the timezone to UTC and the string -encoding to UTF8. The other functions in this class get called by the -Symfony framework at the appropriate times. We will come back to this -file. +`.env.*`, as well as `social.yaml` and `social.local.yaml` files at +the project root. The `index` script creates a `Kernel` object, which +is defined in `src/Kernel.php`. This is the part where the code we +control starts; the `Kernel` constructor creates the needed constants, +sets the timezone to UTC and the string encoding to UTF8. The other +functions in this class get called by the Symfony framework at the +appropriate times. We will come back to this file. ### 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. -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 -creates static references for the logging, event and translation -services. This is done so these services can be used via static +creates static references for the services such as logging, event and +translation. This is done so these services can be used via static function calls, which is much less verbose and more accessible than 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 and optional functionality respectively, by handling events launched 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 Symfony framework and allows us to register a 'Compiler Pass'. -Specifically, we register the `SchemaDefPass` from the -`src/DependencyInjection/Compiler/SchemaDefPass.php` file, which adds +Specifically, we register +`App\DependencyInjection\Compiler\SchemaDefPass` and +`App\DependencyInjection\Compiler\ModuleManagerPass`. The former adds a new 'metadata driver' to Doctrine. The metadata driver is responsible for loading database definitions. We keep the same method -as in V2, which was that each 'Entity' has a `schemaDef` static -function which returns an array describing the database. +as in V2, where each 'Entity' has a `schemaDef` static function which +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 -`src/Util/SchemaDefDriver.php` file, which extends `StaticPHPDriver` -and replaces the methods `loadMetadata` with `schemaDef`. The function -`loadMetadataForClass` function is called by the Symfony framework for -each file in `src/Entity/`. It allows us to call the `schemaDef` -function and translate the array definition to Doctrine's internal -representation. +This datbase definition is handled by the `SchemaDefPass` class, which +extends `Doctrine\Persistence\Mapping\Driver\StaticPHPDriver`. The +function `loadMetadataForClass` is called by the Symfony +framework for each file in `src/Entity/`. It allows us to call the +`schemaDef` function and translate the array definition to Doctrine's +internal representation. The `ModuleManagerPass` later uses this class +to load the entity definitions from each plugin. ### 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, for instance, to generate URLs for each route. Each route connects an URL path to a Controller, with the possibility of taking arguments, -which are passed to the `__invoke` method of the respective -controller. The controllers are defined in `src/Controller/` and are +which are passed to the `__invoke` method of the respective controller +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` -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 The next steps are handled by the Symfony framework which creates a `Request` object from the HTTP request, and then a corresponding -`Response` is created by calling the `Kernel::handle` method, which -matches the appropriate route and thus calls it's controller. +`Response` is created by `App\Core\Controller`, which matches the +appropriate route and thus calls it's controller. ### 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 done through a command, while in development mode, it's handled on 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. diff --git a/src/Core/Controller.php b/src/Core/Controller.php index ab87dc9a19..062ecc4830 100644 --- a/src/Core/Controller.php +++ b/src/Core/Controller.php @@ -106,7 +106,7 @@ class Controller extends AbstractController implements EventSubscriberInterface break; case 'json': $event->setResponse(new JsonResponse($this->vars)); - // no break + break; default: throw new BadRequestHttpException('Unsupported format', null, 406); }