├── .gitignore
├── Back-end
├── API Hook.md
├── API_Ajax.md
├── API_actualizacion.md
├── API_referencias.md
├── APIrenderizacion.md
├── Api.md
├── Archivos.md
├── Batch.md
├── Cache.md
├── Commerce.md
├── Composer.md
├── Condiciones.md
├── Configuraciones.md
├── Consultas.md
├── Contenido_por_defecto.md
├── Debug.md
├── Drush.md
├── Email.md
├── Entidades.md
├── EntityTypeManager.md
├── Errores.md
├── Esquemas.md
├── Fechas.md
├── Formularios.md
├── InyeccionDependencias.md
├── Logs.md
├── MVC.md
├── Mensajes.md
├── Migraciones
│ ├── Migrate.md
│ ├── MigrateAPI.md
│ ├── d7-a-d8.md
│ └── importar-contenido.md
├── Multiidiomas.md
├── Nodos.md
├── PDF.md
├── Plugins
│ ├── API_Plugin.md
│ ├── FilterPlugin.md
│ └── LanguageNegotiation.md
├── Rest.md
├── Restricciones.md
├── Rutas.md
├── Schemas.md
├── Servicios.md
├── Sesiones
├── Sqlite.md
├── Taxonomias.md
├── TempStorage.md
├── Testeo.md
├── Tokens.md
├── Usuarios.md
├── Variables.md
├── Vistas.md
└── Webform.md
├── Contribucion
├── README.md
├── contribuir-modulo.md
├── corregir-parche.md
├── crear-un-parche.md
├── entorno.md
├── gitlab.md
├── merge-request.md
├── reroll.md
└── utilidades.md
├── DevOps
├── IDEs
│ ├── Atom.md
│ └── visualstudiocode.md
├── Seguridad.md
├── ansible.md
├── composer.md
├── docker.md
├── drush.md
├── git.md
├── kubernetes.md
├── lamp.md
├── lando.md
├── linux.md
├── mysql.md
├── php.md
├── redis.md
├── sqlite.md
├── ssh.md
└── xdebug.md
├── Ecosistema
├── SEO.md
├── integraciones.md
└── modulos.md
├── Front-end
├── Twig.md
├── bootstrap.md
├── javascript.md
├── jinja.md
├── librerias.md
├── preprocess.md
└── sub-temas.md
├── Modulos
└── drupal_vuejs
│ ├── drupal_vuejs.info.yml
│ ├── drupal_vuejs.libraries.yml
│ ├── drupal_vuejs.module
│ ├── drupal_vuejs.permissions.yml
│ ├── drupal_vuejs.routing.yml
│ ├── js
│ └── appvuejs.js
│ ├── src
│ └── Controller
│ │ └── drupalVuejsController.php
│ └── templates
│ └── twigTest.html.twig
├── README.md
└── Utiles
├── archivos
└── drush
├── console.md
├── doxygen.md
├── jarvis
├── initHostVirtual
└── restartDB
├── javascript.md
├── php.md
├── reactjs.md
├── sass.md
└── utiles.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignorar configuración IDEs.
2 | .idea
3 |
4 |
--------------------------------------------------------------------------------
/Back-end/API Hook.md:
--------------------------------------------------------------------------------
1 | API de Hookss
2 | ========
3 | Los hooks son funciones a las cuales te puedes colgar para modificar comportamientos de partes de Drupal
4 |
5 | #### Preguardado de una entidad
6 | ```php
7 | /**
8 | * Implements hook_entity_presave().
9 | */
10 | function nombre_modulo_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
11 | switch ($entity->bundle()) {
12 | case 'nombre_sistema_entidad':
13 | $gender = $entity->get('field_gender')->value;
14 | $entity->set('field_gender2', $cgender);
15 | break;
16 | //...
17 | }
18 | }
19 | ```
20 |
21 | #### Modificar un formulario
22 | ```php
23 | /**
24 | * Implements hook_form_alter().
25 | */
26 | function nombre_modulo_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
27 | if ($form_id == 'node_people_edit_form') {
28 | $form['field_is_single']['widget'][0]['value']['#attributes']['readonly'] = TRUE;
29 | //...
30 | return $form;
31 | }
32 | }
33 |
34 | /**
35 | * Implements hook_form_FORM_ID_alter().
36 | */
37 | function mombre_modulo_form_id_del_formulario_alter(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
38 | // Prepare form for using AJAX.
39 | $form['#attached']['library'][] = 'core/drupal.dialog.ajax';
40 | $form['caption'] = [
41 | '#type' => 'html_tag',
42 | '#tag' => 'div',
43 | '#value' => t('Want to join our community ?'),
44 | '#weight' => -25,
45 | '#attributes' => [
46 | 'class' => [
47 | 'newsletter-form-caption',
48 | 'a-block-title',
49 | 'a-block-title--size--small',
50 | ],
51 | ],
52 | ];
53 | //...
54 | }
55 |
56 | /**
57 | * Implements hook_webform_submission_form_alter().
58 | */
59 | function nombe_modulo_webform_submission_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
60 | // Disable inline form errors summary for all webforms.
61 | $form['#disable_inline_form_errors_summary'] = TRUE;
62 | }
63 |
64 | /**
65 | * Implements hook_webform_element_alter().
66 | */
67 | function nombre_modulo_webform_element_alter(array &$element, FormStateInterface $form_state, array $context) {
68 | if ($element["#webform_id"] == 'job_application--job_offer_title') {
69 | if (isset($_GET["job_offer"])) {
70 | $node = Node::load($_GET["job_offer"]);
71 | if ($node instanceof NodeInterface) {
72 | $element['#markup'] = t("To apply for the « @title » offer, please complete the following form :", ['@title' => $node->getTitle()]);
73 | }
74 | }
75 | }
76 | ```
77 |
78 | #### Modificar una view
79 | ```php
80 | /**
81 | * Implementation of hook_views_query_alter().
82 | */
83 | function nombre_modulo_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
84 | if ($view->id() == 'id_de_la_view') {
85 | $query->addField('node_field_data', 'nid', '', ['function' => 'groupby']);
86 | $query->addGroupBy('node_field_data.nid');
87 | }
88 | }
89 |
90 | /**
91 | * Implements hook_views_pre_render().
92 | */
93 | function nombre_modulo_views_pre_render(ViewExecutable $view) {
94 | // Update title for category view.
95 | if ($view->storage->id() == 'commerce_cart_block') {
96 | $category = Term::load($id_category);
97 | $curr_langcode = \Drupal::languageManager()->getCurrentLanguage(\Drupal\Core\Language\LanguageInterface::TYPE_CONTENT)->getId();
98 | $translated = \Drupal::service('entity.repository')->getTranslationFromContext($category, $curr_langcode);
99 | $view->setTitle($translated->getName());
100 | }
101 | }
102 | ```
103 |
104 | #### Modificar un bloque
105 | ```php
106 | /**
107 | * Implements hook_block_build_BASE_BLOCK_ID_alter().
108 | */
109 | function nombre_modulo_block_build_lang_drop_down_switcher_alter(array &$build, BlockPluginInterface $block) {
110 | $langcodes = _get_configurable_languages();
111 | $languages_disabled = 0;
112 |
113 | foreach ($langcodes as $configurableLanguage) {
114 | $disabled = $configurableLanguage->getThirdPartySetting('disable_language', 'disable');
115 | if (isset($disabled) && $disabled == 1) {
116 | $languages_disabled++;
117 | }
118 | }
119 |
120 | if ($languages_disabled == count($langcodes) || $languages_disabled == count($langcodes) - 1) {
121 | $build['#access'] = FALSE;
122 | }
123 | }
124 |
125 | function _get_configurable_languages() {
126 | $configurableLanguages = [];
127 |
128 | // Get all languages.
129 | $languages = \Drupal::languageManager()->getLanguages();
130 |
131 | // The language itself doesn't own the thirdPartySetting,
132 | // So we need to use its matching ConfigEntity
133 | // Getting the ConfigurableLanguageManager.
134 | $configManager = \Drupal::entityTypeManager()->getStorage('configurable_language');
135 | $configurableLanguages = $configManager->loadMultiple(array_keys($languages));
136 |
137 | return $configurableLanguages;
138 | }
139 | ```
140 |
141 | #### Modificar algo en el theme
142 | ```php
143 | /**
144 | * Implements hook_preprocess_HOOK().
145 | */
146 | function nombre_modulo_preprocess_block__system_branding_block(&$variables) {
147 | // @see asf_form_system_theme_settings_alter().
148 | $svg_images = [
149 | 'svg_logo_image' => theme_get_setting('svg_logo_image'),
150 | 'svg_logo_text' => theme_get_setting('svg_logo_text'),
151 |
152 | ];
153 | foreach ($svg_images as $key => $svg_image) {
154 | $file = $svg_image ? File::load($svg_image[0]) : NULL;
155 | if ($file) {
156 | $variables[$key] = [
157 | '#theme' => 'image',
158 | '#uri' => $file->getFileUri(),
159 | ];
160 | }
161 | }
162 | }
163 | ```
164 |
165 | #### Reparar un schema personalizado
166 | ```php
167 | /**
168 | * Implements hook_config_schema_info_alter().
169 | */
170 | function nombre_modulo_config_schema_info_alter(&$definitions) {
171 | // @todo: Remove once https://www.drupal.org/project/menu_multilingual/issues/2956990 is fixed.
172 | if (isset($definitions['block.settings.system_menu_block:*.third_party.menu_multilingual']['mapping']) && isset($definitions['block.settings.system_menu_block:*']['mapping'])) {
173 | $definitions['block.settings.system_menu_block:*']['mapping'] = array_merge($definitions['block.settings.system_menu_block:*']['mapping'], $definitions['block.settings.system_menu_block:*.third_party.menu_multilingual']['mapping']);
174 | }
175 | }
176 | ```
177 |
178 | #### Modificar un tipo de contenido
179 | ```php
180 | /**
181 | * Implements hook_entity_type_build().
182 | */
183 | function nombre_modulo_entity_type_build(array &$entity_types) {
184 | if (isset($entity_types['node'])) {
185 | $entity_types['node']->addConstraint('UniqueIdCatalog', []);
186 | }
187 | }
188 | ```
189 |
190 | #### Agregar una librería a una página
191 | ```php
192 | /**
193 | * Implements hook_page_attachments().
194 | */
195 | function nombre_modulo_page_attachments(array &$attachments) {
196 | // Gigya adds scripts in all pages so we add throbber script too.
197 | $attachments['#attached']['library'][] = 'nombre_modulo/nombre_libreria';
198 | }
199 | ```
200 |
201 | #### Modificar un widget
202 | ```php
203 | /**
204 | * Implements hook_field_widget_form_alter().
205 | */
206 | function nombre_modulo_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
207 | $field_definition = $context['items']->getFieldDefinition();
208 | $paragraph_entity_reference_field_name = $field_definition->getName();
209 |
210 | if ($paragraph_entity_reference_field_name == 'additionnal_informations') {
211 | $widget_state = WidgetBase::getWidgetState($element['#field_parents'], $paragraph_entity_reference_field_name, $form_state);
212 | $paragraph_instance = $widget_state['paragraphs'][$element['#delta']]['entity'];
213 | // Duration field should be invisible if type of contract != CDD.
214 | if ($paragraph_instance->bundle() == 'job_offer_informations') {
215 | if (isset($element['subform']['duration'])) {
216 | $dependee_field_name = 'type_of_contract';
217 | $selector = sprintf('select[name="%s[%d][subform][%s]"]', $paragraph_entity_reference_field_name, $element['#delta'], $dependee_field_name);
218 | $element['subform']['duration']['#states'] = [
219 | 'visible' => [
220 | $selector => ['value' => 'cdd'],
221 | ],
222 | ];
223 | }
224 | }
225 | }
226 | }
227 | ```
228 |
229 | #### Modifcar un menu operations
230 | ```php
231 | /**
232 | * Implements hook_entity_operation_alter().
233 | */
234 | function nombre_modulo_entity_operation_alter(array &$operations, EntityInterface $entity) {
235 | // Add 'Edit all' operation to webform submissions items.
236 | if ($entity->getEntityTypeId() === "webform_submission") {
237 | /* @var $edit_operation_url Drupal\Core\Url */
238 | $edit_operation_url = $operations['edit']['url'];
239 | if (isset($edit_operation_url)) {
240 | $url = \Drupal\Core\Url::fromRoute('entity.webform_submission.edit_form.all', $edit_operation_url->getRouteParameters());
241 | $operation = [
242 | 'title' => t('Edit all'),
243 | 'weight' => 0,
244 | 'url' => $url,
245 | ];
246 | array_push($operations, $operation);
247 | }
248 | }
249 | }
250 | ```
251 |
252 | #### Modificar o filtrar plugins por tipo y por consumidor
253 | ```php
254 | /**
255 | * Implements hook_plugin_filter_TYPE__CONSUMER_alter().
256 | */
257 | function nombre_modulo_plugin_filter_block__layout_builder_alter(&$definitions) {
258 | /* @var $user Drupal\user\Entity\User */
259 | $current_user = \Drupal::currentUser();
260 | $user = User::load($current_user->id());
261 | // User 'contributor' can't use share this block.
262 | if ($user->hasRole('contributor')) {
263 | unset($definitions['sharethis_widget_block']);
264 | }
265 | }
266 | ```
267 |
268 | #### Alterar las tareas de instalación - configuraciones
269 | ```php
270 | /**
271 | * Implements hook_install_tasks_alter().
272 | */
273 | function nombre_modulo_install_tasks_alter(&$tasks, $install_state) {
274 | // Moves the language config import task to the end of the install tasks so
275 | // that it is run after the final import of languages.
276 | $task = $tasks['sdd_install_import_language_config'];
277 | unset($tasks['sdd_install_import_language_config']);
278 | $tasks = array_merge($tasks, ['sdd_install_import_language_config' => $task]);
279 | }
280 | ```
281 |
282 | #### Quitar una pestaña del menu de tabs de webform
283 | ```php
284 | /**
285 | * Implements hook_local_tasks_alter().
286 | */
287 | function nombre_modylo_local_tasks_alter(&$local_tasks) {
288 | // Unset webform submissions because we replace it by a view page with tabs for each form.
289 | unset($local_tasks['entity.webform_submission.collection']);
290 | }
291 | ```
292 |
293 | ### Alterar los links de menús, campos de tipo link
294 | ```php
295 | /**
296 | * Implements hook_link_alter().
297 | *
298 | * Add target="_blank" to all external links.
299 | */
300 | function mi_modulo_link_alter(&$variables) {
301 | if ($variables['url']->isExternal()) {
302 | $webUri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]";
303 | /* @var $url Drupal\Core\Url */
304 | $url = $variables['url'];
305 | $linkUri = $url->toString();
306 | if (str_contains($linkUri, $webUri) === FALSE) {
307 | $variables['options']['attributes']['target'] = '_blank';
308 | $variables['options']['attributes']['rel'] = 'noopener';
309 | }
310 | }
311 | }
312 | ```
313 | ### Alterar el modo de vista de un nodo
314 | ```php
315 | /**
316 | * Implements hook_node_view().
317 | */
318 | function nombre_modulo_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
319 | if ($entity->bundle() == 'landing_page' && $view_mode == "teaser") {
320 | if (empty($build['hea'][0])) {
321 | $id_empty_image = 39;
322 | $media_entity = Media::load($id_empty_image);
323 |
324 | $build['hea']['#theme'] = 'field';
325 | $build['hea']['#title'] = 'Header image';
326 | $build['hea']['#label_display'] = 'hidden';
327 | $build['hea']['#view_mode'] = 'teaser';
328 | $build['hea']['#language'] = $entity->language()->getId();
329 | $build['hea']['#field_name'] = 'hea';
330 | $build['hea']['#field_type'] = 'entity_reference';
331 | $build['hea']['#field_translatable'] = FALSE;
332 | $build['hea']['#entity_type'] = 'node';
333 | $build['hea']['#bundle'] = 'landing_page';
334 | $build['hea']['#object'] = $entity;
335 | $build['hea']['#formatter'] = 'entity_reference_entity_view';
336 | $build['hea']['#is_multiple'] = FALSE;
337 | $build['hea']['#third_party_settings'] = [];
338 | $build['hea'][0] = [
339 | '#media' => $media_entity,
340 | '#view_mode' => 'card',
341 | '#cache' => [
342 | 'tags' => [
343 | '0' => "media:" . $id_empty_image,
344 | '1' => "media_view",
345 | ],
346 | 'contexts' => [
347 | '0' => "route.name.is_layout_builder_ui",
348 | '1' => "user.permissions",
349 | ],
350 | 'max-age' => -1,
351 | 'keys' => [
352 | '0' => "entity_view",
353 | '1' => "media",
354 | '2' => $id_empty_image,
355 | '3' => "card",
356 | ],
357 | 'bin' => "render",
358 | ],
359 | '#theme' => 'media',
360 | '#weight' => 0,
361 | '#pre_render' => [
362 | '0' => [
363 | '0' => \Drupal::entityTypeManager()->getViewBuilder('media'),
364 | '1' => 'build',
365 | ],
366 | ],
367 | ];
368 | $build['hea']['#weight'] = 0;
369 | }
370 | }
371 | }
372 | ```
373 |
374 | ### Aterar el form display de una entidad.
375 | ```php
376 | /**
377 | * Implements hook_entity_form_display_alte().
378 | */
379 | function mi_modulo_entity_form_display_alter(&$form_display, $context) {
380 | if ($context['entity_type'] == 'user' && $context['bundle'] == 'user') {
381 | $user = \Drupal::currentUser();
382 | $user_roles = $user->getRoles();
383 | if (array_intersect($user_roles, ['admin', 'webmaster'])) {
384 | $storage = \Drupal::service('entity_type.manager')->getStorage('entity_form_display');
385 | $form_display = $storage->load('user.user.default');
386 | }
387 | }
388 | }
389 |
390 | ```
391 | ENLACES Y FUENTES
392 | =================
393 | Lista de hooks
394 | - https://api.drupal.org/api/drupal/core!core.api.php/group/hooks/8.2.x
395 |
396 |
397 | Que son los hooks
398 | - https://drupalize.me/tutorial/what-are-hooks?p=2766
399 | - https://www.drupal.org/docs/creating-custom-modules/understanding-hooks
400 |
401 |
--------------------------------------------------------------------------------
/Back-end/API_Ajax.md:
--------------------------------------------------------------------------------
1 | API de ajax
2 | ========
3 |
4 | #### Enlaces ajax mediante la clase 'use-ajax'
5 | Trabajamos en el método que dibuja un bloque (build()).
6 | ```php
7 | public function build() {
8 | $build = [];
9 | $build[] = [
10 | '#theme' => 'container',
11 | '#children' => [
12 | '#markup' => '',
13 | ]
14 | ];
15 | $url = Url::fromRoute('hello.hide_block);
16 | $url->setOption('attributes', ['class' => 'use-ajax']);
17 | $build[] = [
18 | '#type' => 'link',
19 | '#url' => $url,
20 | '#title' => $this->t('Remove'),
21 | ]
22 | return $build;
23 | }
24 | ```
25 |
26 | La ruta para el método que va realizar el trabajo en drupal-php
27 | ```yml
28 | hello.hide_block:
29 | path: '/hide-block'
30 | defaults:
31 | _controller: \Drupal\mi_modulo\Controller\HelloController::hideBlock
32 | requirements:
33 | _permission: 'access content'
34 | ```
35 |
36 | El método en el Controlador
37 | ```php
38 | public function hideBlock(Request $request) {
39 | if (!$request->isXmlHttpRequest()) {
40 | throw new NotFoundHttpException();
41 | }
42 |
43 | $response = new AjaxResponse();
44 | $command = new RemoveCommand('.block-hello');
45 | $response->addCommand($command);
46 | return $response;
47 | }
48 | ```
49 |
50 | Nota: Se puede usar en Botones ajax mediante la clase 'use-ajax-submit'.
51 |
52 | #### Formularios AJAX
53 |
54 | Elemento de formulario que tiene un recargado ajax
55 | ```php
56 | $form['example_select'] = [
57 | '#type' => 'select',
58 | '#title' => $this->t('Example select field'),
59 | '#options' => [
60 | '1' => $this->t('One'),
61 | '2' => $this->t('Two'),
62 | '3' => $this->t('Three'),
63 | '4' => $this->t('From New York to Ger-ma-ny!'),
64 | ],
65 | '#ajax' => [
66 | 'callback' => '::myAjaxCallback', // don't forget :: when calling a class method.
67 | //'callback' => [$this, 'myAjaxCallback'], //alternative notation
68 | 'disable-refocus' => FALSE, // Or TRUE to prevent re-focusing on the triggering element.
69 | 'event' => 'change',
70 | 'wrapper' => 'edit-output', // This element is updated with this AJAX callback.
71 | 'progress' => [
72 | 'type' => 'throbber',
73 | 'message' => $this->t('Verifying entry...'),
74 | ],
75 | ]
76 | ];
77 |
78 | $form['output'] = [
79 | '#type' => 'textfield',
80 | '#size' => '60',
81 | '#disabled' => TRUE,
82 | '#value' => 'Hello, Drupal!!1',
83 | '#prefix' => '
',
84 | '#suffix' => '
',
85 | ];
86 |
87 | if ($selectedValue = $form_state->getValue('example_select')) {
88 | // Get the text of the selected option.
89 | $selectedText = $form['example_select']['#options'][$selectedValue];
90 | // Place the text of the selected option in our textfield.
91 | $form['output']['#value'] = $selectedText;
92 | }
93 | ```
94 |
95 | Método que realiza el remplazo en 'plugin-configuration-wrapper'
96 | ```php
97 | public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
98 | // Return the prepared textfield.
99 | return $form['output'];
100 | }
101 |
102 | ```
103 | #### Recomendaciones importantes
104 | - En formularios, los métodos validate() y submit() se ejecutan antes de los métodos ajax y se pueden usar para actualiazar los valores de form_state. Debido a que cuando se actualiza un elemento de formulario en los métodos ajax no se actualizan sus valores form_state.
105 | - En formularios, no es buena idea generar nuevos elementos de formulario en los métodos ajax. Esto provoca errores.
106 | - En formularios, lo más usual es generar todos los elementos en el método build() para luego manipular su renderizado mediante los métodos callback ajax, form_state y el método validate()
107 |
108 | Referencias
109 | ===
110 | Conceptops básicos
111 | - https://www.drupal.org/docs/drupal-apis/ajax-api/basic-concepts
112 |
113 | Documentación oficial de ajax en formularios - ejemplos
114 | - https://www.drupal.org/docs/drupal-apis/javascript-api/ajax-forms
115 |
116 | Lista de todos los métodos ajax que podemos usar desde php
117 | - https://api.drupal.org/api/drupal/core%21core.api.php/group/ajax/9.1.x
118 |
119 |
120 | Notas importantes sobre ajax a formularios mediante hook_form_alter
121 | - https://www.reddit.com/r/drupal/comments/c7bph8/adding_ajax_callback_to_form_element_using_hook/
--------------------------------------------------------------------------------
/Back-end/API_referencias.md:
--------------------------------------------------------------------------------
1 | API referencias
2 | ========
3 |
4 |
5 |
6 | Enlaces
7 | =================
8 | Documentación oficial
9 | https://api.drupal.org/api/drupal/8
10 |
11 | Documentación de la comunidad
12 | https://www.drupal.org/developing/api/8
13 |
14 | Clases de drupal 8
15 | https://api.drupal.org/api/drupal/classes/8
16 |
17 | Configuraciones
18 | https://www.drupal.org/developing/api/8/configuration
19 |
20 | Hoja resumida de codigo
21 | http://wizzlern.nl/sites/wizzlern.nl/files/artikel/drupal8_content_entity.pdf
22 |
23 | Watchdow drupal 8
24 | https://www.drupal.org/node/2270941
25 |
26 | Lo basico de programar en D8
27 | http://capgemini.github.io/drupal/drupal-8-in-2-steps/
28 |
29 | Webomelette
30 | http://www.webomelette.com/
31 |
32 | Event dispacher
33 | http://www.sitepoint.com/drupal-8-hooks-symfony-event-dispatcher/
34 |
35 | Entity query
36 | https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!Query!QueryInterface.php/function/QueryInterface%3A%3Acondition/8
37 |
38 | Entidades
39 | http://talks.shawnduncan.org/entity_talk/#/overview
40 |
41 | http://talks.shawnduncan.org/entity_talk/images/Entity.svg
42 |
43 | Recurso sobre entidades
44 | http://shawnduncan.org/entities-core-custom
45 |
46 | Programación orientada a objectos para Drupal 8 - php
47 | https://prakashdrupal.wordpress.com/2016/04/13/want-to-learn-drupal-8-custom-module/
48 |
49 | Programación MVC sobre Drupal 8
50 | https://gist.github.com/jmolivas/d29065493a91f16f35b2
51 |
52 | Seguimiento de cambios en el Core
53 | https://www.drupal.org/list-changes/drupal
54 |
55 | Configuraciones sobre Drupal 8
56 | http://hojtsy.hu/files/ConfigSchemaCheatSheet1.5.pdf
57 |
58 | Entidades traducibles en drupal 8
59 | https://vimeo.com/166918014
60 |
61 | Definición de librerias
62 | https://ffwagency.com/blog/managing-css-and-javascript-files-drupal-8-libraries
63 | https://www.drupal.org/theme-guide/8/assets
64 |
65 |
--------------------------------------------------------------------------------
/Back-end/APIrenderizacion.md:
--------------------------------------------------------------------------------
1 | API Renderización
2 | ========
3 |
4 |
5 |
6 |
7 |
8 | ENLACES Y FUENTES
9 | =================
10 | https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/group/theme_render/
11 |
--------------------------------------------------------------------------------
/Back-end/Api.md:
--------------------------------------------------------------------------------
1 | API codigo
2 | ========
3 |
4 | Cambiar el orden en que un módulo se implementa y sus hooks
5 | ```php
6 | // colocar en hook_install()
7 | module_set_weight('my_module', 123);
8 | ```
--------------------------------------------------------------------------------
/Back-end/Archivos.md:
--------------------------------------------------------------------------------
1 | ARCHIVOS
2 | ========
3 |
4 | #### Escribir en un archivo
5 | ```php
6 | $file = File::create([
7 | 'uid' => 1,
8 | 'filename' => 'nombre_archivo.txt',
9 | 'uri' => 'public://page/nombre_archivo.txt',
10 | 'status' => 1,
11 | ]);
12 | $file->save();
13 | $dir = dirname($file->getFileUri());
14 | if (!file_exists($dir)) {
15 | mkdir($dir, 0770, TRUE);
16 | }
17 | file_put_contents($file->getFileUri(), $content);
18 | $file->save();
19 | ```
20 |
21 | #### Referencias
22 | http://www.drupal8.ovh/en/tutoriels/47/create-a-file-drupal-8
23 |
--------------------------------------------------------------------------------
/Back-end/Batch.md:
--------------------------------------------------------------------------------
1 | Batch
2 | ===
3 |
4 | Drupal provee una API para ejecutar tareas pesadas sin que php retorne errores por capacidades de memoria.
5 |
6 |
7 | #### Ejemplo de código puesto su ejecución en batch.
8 | ```php
9 | //Verificar una lista de emails em batch.
10 | public function submitForm(array &$form, FormStateInterface $form_state) {
11 | $email_ids = $form_state->getValue('emailids');
12 | $emails = explode("\n",$email_ids);
13 |
14 | $batch = [
15 | 'title' => t('Sending emails...'),
16 | 'operations' => [],
17 | 'init_message' => t('Starting'),
18 | 'progress_message' => t('Processed @current out of @total.'),
19 | 'error_message' => t('An error occurred during processing'),
20 | 'finished' => '\Drupal\batch_example\DeleteNode::ExampleFinishedCallback',
21 | ];
22 | foreach ($emails as $key => $value) {
23 | $email = trim($value);
24 | $batch['operations'][] = ['\Drupal\batch_example\EmailCheck::checkEmailExample',[$email]];
25 | }
26 |
27 | batch_set($batch);
28 | }
29 | ```
30 |
31 | #### Referencias
32 | Documentación API
33 | - https://api.drupal.org/api/drupal/core%21includes%21form.inc/group/batch/8.2.x
34 |
35 | Ejemplo de uso
36 | - https://opensenselabs.com/blogs/tech/how-use-batch-api-drupal-8
--------------------------------------------------------------------------------
/Back-end/Cache.md:
--------------------------------------------------------------------------------
1 | Cache
2 | ===
3 |
4 | ### Operaciones sobre la cache
5 | ```php
6 | // Vaciar caches persistentes
7 | use Drupal\Core\Cache\Cache;
8 |
9 | foreach (Cache::getBins() as $service_id => $cache_backend) {
10 | $cache_backend->deleteAll();
11 | }
12 | ```
13 |
14 | ENLACES Y FUENTES
15 | =================
16 | https://api.drupal.org/api/drupal/core%21core.api.php/group/cache/8.2.x
17 |
18 | - Errores y casos comunes
19 | https://www.lullabot.com/articles/common-max-age-pitfalls-with-drupal-cache
--------------------------------------------------------------------------------
/Back-end/Commerce.md:
--------------------------------------------------------------------------------
1 | Commerce el ecosistema para hacer comercio electrónico de Drupal
2 | ========
3 |
4 | #### Manipular entidades programaticamente
5 | ```php
6 | // Obener productos
7 | $query = \Drupal::entityQuery('commerce_product')
8 | ->condition('status', 1);
9 | $and = $query->andConditionGroup();
10 | $and->condition('field_categoy', $category);
11 | $query->condition($and);
12 | if ($subcategory != 0) {
13 | $and = $query->andConditionGroup();
14 | $and->condition('field_categoy', $subcategory);
15 | $query->condition($and);
16 | }
17 | $product_ids = $query->execute();
18 | $products = [];
19 |
20 | foreach ($product_ids as $product_id) {
21 | $products[] = [
22 | 'id' => $product_id,
23 | ];
24 | }
25 |
26 |
27 | // Obtener producto por parametro
28 | $parameter = \Drupal::routeMatch()->getParameter('commerce_product');
29 | $product = \Drupal\commerce_product\Entity\Product::load((int)$parameter->id());
30 |
31 | // Cargar product variations
32 | $entity_manager = \Drupal::entityManager();
33 | $product_variation = $entity_manager->getStorage('commerce_product_variation')->load((int)$product->getVariationIds()[0]);
34 | $price_number = $product_variation->get('price')->getValue()[0]['number'];
35 | $price_currency = $product_variation->get('price')->getValue()[0]['currency_code'];
36 | ```
37 |
38 |
39 | #### Módulos recomendads
40 | Commerce Reporting
41 |
42 | Nos da reportes gráficos y en tablas de clientes, productos, pagos por periodos de tiempo.
43 | - https://www.drupal.org/project/commerce_reports
44 |
45 | Commerce Stock
46 |
47 | Permite gestionar el stock para las Tiendas.
48 | - https://www.drupal.org/project/commerce_stock
49 |
50 | ### Diagrama relación de entidades
51 | - https://docs.drupalcommerce.org/commerce2/developer-guide/core/relationships
52 |
53 |
54 | ENLACES Y FUENTES
55 | =================
56 | Documentación API para drupal 8 (commerce 2)
57 | - https://docs.drupalcommerce.org/commerce2/getting-started
58 |
59 | Recetas de código
60 | - https://docs.drupalcommerce.org/commerce2/developer-guide/products/product-management/code-recipes
61 |
62 | Código para agregar al carrito
63 | - https://www.valuebound.com/resources/blog/how-to-add-a-product-programmatically-to-drupal-commerce-cart
--------------------------------------------------------------------------------
/Back-end/Composer.md:
--------------------------------------------------------------------------------
1 | Composer
2 | ========
3 | #### Manejar varias version
4 | ```bash
5 | # Cambiar a la version 1
6 | composer self-update --1
7 |
8 | # Cambiar a la version 2
9 | composer self-update --2
10 |
11 | # Volver a la version anterior
12 | composer self-update --rollback
13 | ```
14 |
15 | #### Crear un nuevo proyecto
16 | ```bash
17 | # Version específica.
18 | composer create-project drupal/recommended-project:8.9.8 my_site_name_dir
19 |
20 | # Version recomendada
21 | composer create-project drupal/recommended-project my_site_name_dir
22 | ```
23 |
24 | #### Resolver dependencias de librerias js de módulos contribuidos
25 |
26 | Resolver dependencias haciendo un merge. Útil para proyectos en github
27 | ```bash
28 | composer require wikimedia/composer-merge-plugin
29 | ```
30 |
31 | Editar composer.json agregar en la sección "extra"
32 | ```json
33 | "merge-plugin": {
34 | "include": [
35 | "docroot/modules/contrib/webform/composer.libraries.json"
36 | ]
37 | },
38 | ```
39 |
40 | From now on, every time the "composer.json" file is updated, it will also read the content of "composer.libraries.json" file located at web/modules/contrib/webform/ and update accordingly.
41 |
42 | In order for the "composer.json" file to install all the libraries mentioned inside the "composer.libraries.json", from the Git bash composer update --lock
43 |
44 |
45 | #### Requerir un nuevo componente
46 |
47 | ```bash
48 | # Ver todas las versiones de un proyecto.
49 | composer show drupal/account_field_split --all
50 |
51 | # Versión en producción
52 | composer require drupal/adminimal_theme:^1.3
53 |
54 | # Alfa
55 | composer require drupal/domain_entity:^1.0@alpha
56 |
57 | # Beta
58 | composer require drupal/better_normalizers:^1@beta
59 |
60 | # Rama en desarrollo
61 | composer require drupal/flexslider:^dev
62 | composer require drupal/http_status_code:1.x-dev
63 | # Fork
64 | composer require drupal/entity_reference_facet_link:dev-3254358-can-not-update
65 |
66 | # Requerir un proyecto para un determinado ambiente (dev)
67 | composer require --dev phpunit/phpunit
68 | ```
69 |
70 | #### Actualizar un módulo, tema
71 |
72 | ```bash
73 | # Listar actualizaciones posibles.
74 | composer outdated "drupal/*"
75 |
76 | # Listar actualizaciones de seguridad.
77 | drush pm:security
78 |
79 | # Instalar actualizaciones
80 | composer update drupal/nombre_modulo --with-dependencies
81 | drush updatedb
82 | drush cache:rebuild
83 | drush config:export --diff
84 |
85 | # Actualiza módulo para apartado require-dev
86 | composer require --dev drupal/upgrade_status:^3.17 --with-all-dependencies
87 |
88 | # Actualizaciones con revisión previa de compatibilidad
89 | composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --no-update
90 | composer update --dry-run
91 | composer update
92 | composer install
93 | ```
94 |
95 | #### Remover un componente
96 |
97 | ```
98 | # composer remove drupal/config_filter
99 | ```
100 |
101 | #### Pulgins
102 | https://www.drupaleasy.com/blogs/ultimike/2020/06/composer-plugins-drupal-developers?utm_source=drupal-newsletter&utm_medium=email&utm_campaign=drupal-newsletter-20200625
103 |
104 |
105 | #### Problemas comunes
106 | ```bash
107 | # La memoria especificada para ejecución de php no es suficiente
108 | php -d memory_limit=-1 composer require
109 | ```
110 |
111 | ```bash
112 | # [ErrorException]
113 | # Undefined index: extra
114 | composer update zaporylie/composer-drupal-optimizations --no-plugins && composer update --lock
115 | ```
116 |
117 | #### Actualizar el core
118 | ```bash
119 | composer update drupal/core-recommended --with-dependencies
120 | composer update drupal/core --with-dependencies
121 |
122 | // Actualizar manualmente composer.json los valores roecommended luego
123 | composer update drupal/core "drupal/core-*" --with-all-dependencies
124 |
125 | ```
126 |
127 | - https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer#update-all-steps
128 | - https://www.drupal.org/docs/updating-drupal/update-drupal-core-via-composer
129 | - https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-to-drupal-9-or-higher
130 |
131 | #### Usar composer en un proyecto que fue instalado sin composer
132 | - Si el proyecto es Drupal 8.8.0 este ya tiene composer y sólo es necesario entonces instalar todos los módulos en la versión actual.
133 |
134 | ### Actualizar composer
135 | ```bash
136 | # Degrada a composer 1.
137 | sudo composer self-update --1
138 |
139 | # Actualizar a composer 2
140 | sudo composer self-update --2
141 | ```
142 |
143 | #### Instalar librería externa
144 | En `composer.json` agregar este código dentro de la sección `repositories`:
145 | ```json
146 | {
147 | "type": "package",
148 | "package": {
149 | "name": "library-magnific/magnific-popup",
150 | "version": "1.1.0",
151 | "type": "drupal-library",
152 | "source": {
153 | "url": "https://github.com/dimsemenov/Magnific-Popup",
154 | "type": "git",
155 | "reference": "1.1.0"
156 | }
157 | }
158 | },
159 | ```
160 | Ejecutar `composer require --prefer-dist library-magnific/magnific-popup:1.1.*` para instalar.
161 |
162 | ### Resolver problemas de compatibilidad.
163 | Agregar el MR de gitlab,
164 | ```yml
165 | "repositories": [
166 | {
167 | "type": "composer",
168 | "url": "https://packages.drupal.org/8",
169 | "exclude": [
170 | "drupal/rng"
171 | ]
172 | },
173 | {
174 | "type": "git",
175 | "url": "https://git.drupalcode.org/issue/rng-3218000.git"
176 | }
177 | ],
178 | ```
179 | Ejecutar comando:
180 | ```bash
181 | $ composer require drupal/rng:dev-8.x-1.x
182 | ```
183 |
184 | ENLACES Y FUENTES
185 | =================
186 | Resolver dependencias de webform
187 | - https://www.drupal.org/docs/8/modules/webform/webform-frequently-asked-questions/how-to-use-composer-to-install-libraries
188 |
189 | Todas las opciones de actualización
190 | - https://www.drupal.org/docs/updating-drupal
191 |
192 | Actualizando módulos y temas
193 | - https://www.drupal.org/docs/updating-drupal/updating-modules-and-themes-using-composer
194 |
195 | Para actualizar composer from 1 to 2
196 | - https://www.drupal.org/docs/develop/using-composer/preparing-your-site-for-composer-2
197 |
198 | Para actualizar un propyecto que fue instalado sin composer
199 | - https://www.drupal.org/docs/installing-drupal/add-composer-to-an-existing-site
200 |
201 | Guía completa drupal-composer
202 | - https://www.drupal.org/docs/develop/using-composer/using-composer-to-install-drupal-and-manage-dependencies
203 |
204 | Resolver problemas de compatibilidad
205 | - https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupal/creating-issue-forks-and-merge-requests#s-useissue-forks-to-makecompatibility-fixes-work-with-composer
206 |
207 | Composer update para d9 drupal/core-recommended
208 | - https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer
--------------------------------------------------------------------------------
/Back-end/Condiciones.md:
--------------------------------------------------------------------------------
1 | Condiciones
2 | ========
3 | Las condiciones se puede agregar en cualquier campo que lo requiera (panels, commerce cart, descuentos, bloques condicionales etc)
4 |
5 | #### Ejemplo condición extendida de base (usable desde commerce conditions)
6 | ```php
7 | namespace Drupal\extended_commerce\Plugin\Commerce\Condition;
8 |
9 | use Drupal\commerce\Plugin\Commerce\Condition\ConditionBase;
10 | use Drupal\Core\Entity\EntityInterface;
11 | use Drupal\Core\Form\FormStateInterface;
12 |
13 | /**
14 | * Provides a basic condition for orders.
15 | *
16 | * @CommerceCondition(
17 | * id = "custom_module_order_specific_customer",
18 | * label = @Translation("Specific customer"),
19 | * category = @Translation("Customer"),
20 | * entity_type = "commerce_order",
21 | * )
22 | */
23 | class OrderSpecificCustomer extends ConditionBase {
24 |
25 | /**
26 | * {@inheritdoc}
27 | */
28 | public function defaultConfiguration() {
29 | return [
30 | 'customer' => NULL,
31 | ] + parent::defaultConfiguration();
32 | }
33 |
34 | /**
35 | * {@inheritdoc}
36 | */
37 | public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
38 | $form = parent::buildConfigurationForm($form, $form_state);
39 |
40 | $form['customer'] = [
41 | '#type' => 'textfield',
42 | '#default_value' => $this->configuration['customer'],
43 | '#required' => TRUE,
44 | ];
45 |
46 | return $form;
47 | }
48 |
49 | /**
50 | * {@inheritdoc}
51 | */
52 | public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
53 | parent::submitConfigurationForm($form, $form_state);
54 |
55 | $values = $form_state->getValue($form['#parents']);
56 | $this->configuration['customer'] = $values['customer'];
57 | }
58 |
59 | /**
60 | * {@inheritdoc}
61 | */
62 | public function evaluate(EntityInterface $entity) {
63 | $this->assertEntity($entity);
64 | /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
65 | if ($customer_id = $order->getCustomerId()) {
66 | // Condition is TRUE only for customer with ID #2.
67 | return ($customer_id == $this->configuration['customer']);
68 | }
69 |
70 | return FALSE;
71 | }
72 |
73 | }
74 | ```
75 | #### Ejemplo condición extendida de plugin base (usable desde panels, etc)
76 | ```php
77 | currentRouteMatch = $current_route_match;
122 | }
123 |
124 | /**
125 | * {@inheritdoc}
126 | */
127 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
128 | return new static(
129 | $configuration,
130 | $plugin_id,
131 | $plugin_definition,
132 | $container->get('current_route_match')
133 | );
134 | }
135 |
136 | /**
137 | * {@inheritdoc}
138 | */
139 | public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
140 | $form['status_text'] = [
141 | '#type' => 'markup',
142 | '#markup' => $this->t('Node with custom_field status field is being viewed'),
143 | ];
144 |
145 | return parent::buildConfigurationForm($form, $form_state);
146 | }
147 |
148 | /**
149 | * {@inheritdoc}
150 | */
151 | public function summary() {
152 | return ($this->isNegated())
153 | ? $this->t('Node with custom_field status field is not being viewed')
154 | : $this->t('Node with custom_field status field is being viewed');
155 | }
156 |
157 | /**
158 | * {@inheritdoc}
159 | */
160 | public function evaluate() {
161 | $node = $this->currentRouteMatch->getParameter('node');
162 | return ($node && $node->hasField('custom_field') && $node->custom_field->value);
163 | }
164 |
165 | }
166 | ```
167 |
168 |
169 |
170 | ENLACES Y FUENTES
171 | =================
172 | Colección de condition plugins
173 | - https://www.drupal.org/project/condition_plugins
174 |
175 |
--------------------------------------------------------------------------------
/Back-end/Configuraciones.md:
--------------------------------------------------------------------------------
1 | Configuraciones
2 | ===
3 |
4 | #### Operaciones con el API
5 | ```php
6 | //Cron
7 | \Drupal::config('system.cron')->get('threshold.autorun')
8 | \Drupal::state()->get('system.cron_last')
9 |
10 | //Email
11 | \Drupal::config('user.mail')->get('register_admin_created.subject');
12 | \Drupal::config('user.mail')->get('register_admin_created.body');
13 |
14 | //Escribiendo configuraciones
15 | $config = \Drupal::service('config.factory')->getEditable('system.performance');
16 | $config->set('cache.page.enabled', 1); // Set a scalar value.
17 | $page_cache_data = array('enabled' => 1, 'max_age' => 5); // Set an array of values.
18 | $config->set('cache.page', $page_cache_data);
19 | $config->save();
20 |
21 | //Servicios
22 | $resource_id = 'product_resource';
23 | $resources = \Drupal::config('rest.settings')->get('resources') ?: array();
24 | $resources[$resource_id] = array(); // reset de resource configuration
25 | $method = "GET";
26 |
27 | $resources[$resource_id][$method] = array();
28 | $resources[$resource_id][$method]['supported_formats'] = array("json");
29 | $resources[$resource_id][$method]['supported_auth'] = array("cookie");
30 |
31 | \Drupal::configFactory()->getEditable('rest.settings')
32 | ->set('resources', $resources)
33 | ->save();
34 |
35 | //Sistema
36 | \Drupal::configFactory()->getEditable('system.site')
37 | ->set('page.404', 'not-found')
38 | ->save();
39 |
40 | ```
41 |
42 | Config Split
43 | ```bash
44 | # Drush 8 o anterior:
45 | drush config-split-import config_dev
46 |
47 | # Drush 9 o posterior:
48 | drush config-split:import config_dev
49 |
50 | ## Verificar la configuraciones sobreescritas.
51 |
52 | # Drush 8 o anterior:
53 | drush config-export
54 |
55 | # Drush 9 o posterior:
56 | drush config:export
57 |
58 | # Editar una configuración activa
59 | drush config-edit nombre.configuración
60 | ```
61 |
62 | ### Referencias
63 | Config split
64 | - https://www.drupal.org/docs/contributed-modules/configuration-split/creating-a-simple-split-configuration-dev-modules-only
65 | - https://www.specbee.com/blogs/how-to-split-configurations-across-different-sites-on-drupal-9?utm_source=drupal-newsletter&utm_medium=email&utm_campaign=drupal-newsletter-20210708
66 |
67 | Buena guía de módulos, comandos y algo de código.
68 | - https://www.daggerhartlab.com/drupal-8-configuration-management-with-config-split/
--------------------------------------------------------------------------------
/Back-end/Consultas.md:
--------------------------------------------------------------------------------
1 | Consultas
2 | ===
3 |
4 | #### Consultas mediante sql
5 | ```php
6 | $db = \Drupal::database();
7 |
8 | //Método 1
9 | $query = $db->select('k_product', 'p');
10 | $query->fields('p', ['idpr', 'name', 'type']);
11 | $data = $query->execute()->fetchAllAssoc('idpr', 'name', 'type');
12 |
13 | //Método 2
14 | // Dado:
15 | $sql = "SELECT idpr, name, code, detail FROM k_product";
16 | // Obtener un array asociativo simple
17 | $data = $db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
18 | // Obtener un array asociativo. Con 'idpr' como identificador de cada subarray asociativo
19 | $data = $db->query($sql)->fetchAllAssoc('idpr', 'FETCH_ASSOC');
20 |
21 | // Obtener sólo un dato puntual
22 | $sql = "SELECT idpr FROM k_product WHERE name = :name;";
23 | $id_product = $db->query($sql, array(':name' => 'Lapiz'))->fetchField(0);
24 |
25 | DEPRECADOS.
26 | //múltiples filas
27 | $result = db_query('SELECT id, qualifier, email, board, popup
28 | FROM {k_message}
29 | WHERE rule = :rid',
30 | array(':rid' => $idRule)
31 | );
32 |
33 | foreach ($result as $record) {
34 | $idMessage = $record->id;
35 | $qualifier = $record->qualifier;
36 | $emailMsg = $record->email;
37 | $boardMsg = $record->board;
38 | $popupMsg = $record->popup;
39 | }
40 |
41 | //optener valor de un sólo campo
42 | $addFactor = db_query('SELECT value FROM k_factor WHERE id = :id;', array(':id' => $id))->fetchField();
43 | ```
44 |
--------------------------------------------------------------------------------
/Back-end/Contenido_por_defecto.md:
--------------------------------------------------------------------------------
1 | Contenido por defecto
2 | ========
3 |
4 | #### 1. Obtener el módulo default_content y better normalizers
5 | ```bash
6 | $ composer require drupal/default_content:^1@alpha
7 | $ composer require drupal/better_normalizers:^1@beta
8 | ```
9 | NOTA: El módulo "Better normalizers" se utiliza para generar archivos "file" (ejemplo un svg)
10 |
11 | #### 2. Activar los módulos
12 | ```bash
13 | $ drush en -y default_content better_normalizers
14 | ```
15 |
16 | #### 3. Crear un módulo para contener los contenidos
17 | ```bash
18 | $ drush generate module-standard
19 | // Crear carpeta que va contener el contenido generado
20 | $ mkdir docroot/modules/custom//content
21 | ```
22 |
23 | #### 4. Crear los contenidos haciendo site building
24 | ```
25 | ...
26 | ```
27 |
28 | #### 5. Generar los contenidos para ser reutilizados usando comandos.
29 | ```bash
30 | $ drush dcer node
31 | $ drush dcer taxonomy_term
32 | $ drush dcer file
33 | $ drush dcer media
34 | $ drush dcer menu_link_content
35 | $ drush dcer block_content
36 | $ drush dcer user
37 | $ drush dcer commerce_store
38 | $ drush dcer commerce_product
39 | ```
40 |
41 | Comandos para genear contenidos customizando la ruta donde colocarlo.
42 | ```bash
43 | $ drush dcer node --folder=modules/custom//content
44 | ```
45 |
46 | #### 5. Desactivar los módulos para generar contenidos
47 | // Desactivar módulos default_content, better_normalizers
48 | ```bash
49 | $ drush pmu default_content better_normalizers
50 | ```
51 |
52 | ### Utilizando migrate_generator
53 | https://www.drupal.org/project/migrate_generator
54 | (por revizar)
55 |
56 | ENLACES Y FUENTES
57 | =================
58 | Documentación oficial
59 | - https://www.drupal.org/docs/8/modules/default-content-for-d8/overview
--------------------------------------------------------------------------------
/Back-end/Debug.md:
--------------------------------------------------------------------------------
1 | Depurar el código
2 | ========
3 |
4 | #### Xdebug en local
5 | Permite ver las variables y su contenido de manera eficiente y en tu editor de código favorito
6 |
7 | 1. Instalar
8 | ```
9 | $ sudo apt-get install php-xdebug
10 |
11 | // Configurar en php.ini
12 | html_errors = On
13 |
14 | // Configuraciones en php.ini opcionales
15 | display_errors = On
16 | display_startup_errors = On
17 | error_reporting = E_ALL
18 | ```
19 |
20 | 2. Configurar xdebug
21 | en /etc/php/[version_php]/mods-available/xdebug.ini
22 | ```
23 | zend_extension=/usr/lib/php/20190902/xdebug.so
24 | xdebug.remote_autostart = 1
25 | xdebug.remote_enable = 1
26 | xdebug.remote_handler = dbgp
27 | xdebug.remote_host = 127.0.0.1
28 | xdebug.remote_log = /tmp/xdebug_remote.log
29 | xdebug.remote_mode = req
30 | xdebug.remote_port = 9000
31 | ```
32 | 3. Reiniciar servicios
33 | ```
34 | $ service apache2 restart
35 | ```
36 |
37 | 4. Instalar plugin para el navegador web
38 | ```
39 | Plugin chrome
40 | https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc/related
41 | ```
42 |
43 | 4. Configurar phpStorm
44 | ```
45 | - Verificar si tenemos el proyecto con Xdebug
46 | Confurations > Languages & Framework > PHP > Debug > Validate
47 |
48 | - Configurar la conexión en "Edit configurations" (menú superior lado izquierdo de play)
49 | Crear desde Templates un "PHP Web Page"
50 | Colocar
51 | Start ULR: / (u otro url del proyecto)
52 | Browser: Chrome (u otro)
53 |
54 | En "server" dar click en "..."
55 | Host:mi_proyecto_local.com
56 | Port: 80
57 | Debugger: Xdebug
58 | Check "Use path mappings..."
59 | En "Absolute path on the server" colocar la ruta al index del proyecto. Ej: /var/www/html/mi_proyecto_local/docroot
60 |
61 | - Empezar a escuchar conexiones php debug
62 | Dar click en el icono telefono "Start listening"
63 |
64 | - Empezar a debuguear
65 | Navegar en el proyecto
66 | ```
67 |
68 | #### Xdebug en docker
69 |
70 |
71 | ENLACES Y FUENTES
72 | =================
73 | https://lucidar.me/en/aws-cloud9/how-to-install-and-configure-xdebug-on-ubuntu/
74 |
75 | https://dev.to/thamaraiselvam/configure-xdebug-php-7-nginx-any-linux-distribution-3ic0
76 |
77 | https://gist.github.com/RazaChohan/51bffc660d52eae8a75dd0f9503740bf
78 |
79 | https://blog.liip.ch/archive/2016/06/20/lets-debug-drupal-8.html
80 |
--------------------------------------------------------------------------------
/Back-end/Drush.md:
--------------------------------------------------------------------------------
1 | Drush
2 | ===
3 |
4 | Se pueden programar nuevos comandos para drush.
5 |
6 |
7 | #### Ejemplo comando
8 | ```php
9 | namespace Drupal\mi_modulo\Commands;
10 |
11 | use Drupal\mi_modulo\LocalsHandlerInterface;
12 | use Drush\Commands\DrushCommands;
13 |
14 | /**
15 | * Drush commands concerning centers.
16 | */
17 | class MiNuevoCommando extends DrushCommands {
18 |
19 | /**
20 | * The locals service handler.
21 | *
22 | * @var \Drupal\mi_modulo\LocalsHandlerInterface
23 | */
24 | protected $localsHandler;
25 |
26 | /**
27 | * Commands constructor.
28 | *
29 | * @param \Drupal\mi_modulo\LocalsHandlerInterface $locals_handler
30 | * The locals handler service.
31 | */
32 | public function __construct(LocalsHandlerInterface $locals_handler) {
33 | parent::__construct();
34 | $this->localsHandler = $locals_handler;
35 | }
36 |
37 | /**
38 | * Import Local nodes from Loclas service information.
39 | *
40 | * @param string $local_id
41 | * Local ID.
42 | *
43 | * @command mi_modulo-locals:import-locals
44 | *
45 | * @usage drush mi_modulo-locas:import-locals
46 | * Creates nodes for centers of default area 1.
47 | */
48 | public function importLocals($local_id = '1') {
49 | $locals = $this->centersHandler->initializeCenters([$local_id]);
50 | if (isset($locals['local_' . $local_id])) {
51 | $this->output()->writeln(
52 | 'An amount of ' . count($locals['area_' . $local_id]) . ' locals where successfully imported.'
53 | );
54 | }
55 | else {
56 | $this->output()->writeln('The entered Local ID "' . $local_id . '" did not match any result.');
57 | }
58 | }
59 |
60 | }
61 |
62 | ```
63 |
64 | #### Referencias
65 | Documentación API
66 | - https://api.drupal.org/api/drupal/core%21includes%21form.inc/group/batch/8.2.x
67 |
68 | Ejemplo de uso
69 | - https://opensenselabs.com/blogs/tech/how-use-batch-api-drupal-8
--------------------------------------------------------------------------------
/Back-end/Email.md:
--------------------------------------------------------------------------------
1 | EMAIL
2 | ========
3 | #### Envío de email por código
4 | ```php
5 | // En caso de tener que enviar un archivo adjunto.
6 | $file = file_save_data($output, $destination, FileSystemInterface::EXISTS_REPLACE);
7 | $file->setTemporary();
8 | $file->save();
9 | $this->fileName = $file->label();
10 | $attachment = [
11 | 'filecontent' => file_get_contents($destination),
12 | 'filename' => $file->label(),
13 | 'filemime' => 'application/pdf'
14 | ];
15 |
16 | // Obtener las configuraciones para enviar.
17 | $tempstore = \Drupal::service('tempstore.private');
18 | $store = $tempstore->get('views_bulk_operations_' . $this->view->id() . '_' . $this->view->current_display);
19 | $subject = $store->get('subject');
20 | $email = $store->get('email');
21 | $body = $store->get('body');
22 |
23 | // Enviar el email.
24 | $mail_manager = \Drupal::service('plugin.manager.mail');
25 | $lang_code = \Drupal::languageManager()->getCurrentLanguage()->getId();
26 | $params = [
27 | 'subject' => $subject,
28 | 'to' => $email,
29 | 'body' => $body,
30 | ];
31 | $params['attachments'][] = $attachment;
32 | $mail_manager->mail('nombre_modulo', 'clave_envio', $params['to'], $lang_code, $params, NULL, TRUE);
33 |
34 | // @Por verificar pero algunas veces se necesita este hook más
35 | /**
36 | * Implements hook_mail().
37 | */
38 | function mi_modulo_mail($key, &$message, $params) {
39 | $options = [
40 | 'langcode' => 'es',
41 | ];
42 |
43 | switch ($key) {
44 | case 'clave_envio':
45 | $message['from'] = \Drupal::config('system.site')->get('mail');
46 | $message['to'] = $params['to'];
47 | $message['subject'] = $params['subject'];
48 | $message['body'][] = $params['body'];
49 | break;
50 | }
51 | }
52 | ```
53 |
54 | #### SwiftMailer
55 | ```bash
56 | # Estando en la rais del proyecto drupal
57 | composer require drupal/swiftmailer
58 |
59 | # Instalar el módulo SwiftMailer
60 | drush en swiftmailer
61 |
62 | # Configurar en la ruta: /admin/config/swiftmailer/transport
63 | # Transport types puede estar en el de tu preferencia
64 | # En la pestaña mensajes elige HTML y desmarca "Respect provided e-mail format."
65 |
66 | # Instalar el módulo MailSystem
67 | drush en mailsystem
68 | # Configurar en la ruta admin/config/system/mailsystem
69 | # Formater y Sender deben estar en SwiftMailer, Theme puede estar en el Tema por defecto o en SwiftMailer
70 |
71 | # Customizar el template html
72 | # En la ruta /modules/swiftmailer/templates/swiftmailer.html.twig se encuentra el template base.
73 | ```
74 |
75 | #### Bug..
76 | Si aunque este todo bien configurado el sitio no logra mandar email html.. este hook lo resuelve
77 | ```php
78 | use Drupal\Core\Render\Markup;
79 |
80 | /**
81 | * Implements hook_mail_alter()
82 | * @return mixed
83 | */
84 | function nombreModulo_mail_alter(&$message) {
85 | $message['body'][0] = Markup::create($message['body'][0]);
86 | }
87 | ```
88 | Tambien funciona
89 | ```
90 | check_markup(
91 | $token->replace($settings->get('confirmation_body'), $data),
92 | $settings->get('confirmation_body_format')
93 | ),
94 | ```
95 |
96 |
97 | ENLACES Y FUENTES
98 | =================
99 | Documentación SwiftMailer
100 | - https://www.drupal.org/node/1590154
101 |
102 | Inspiración para le hook
103 | - http://code.tutsplus.com/tutorials/using-and-extending-the-drupal-8-mail-api-part-1--cms-23419
104 |
105 | - https://api.drupal.org/api/drupal/core!core.api.php/function/hook_mail_alter/8.2.x
106 |
107 | - https://www.drupal.org/node/2677530#comment-11226949
108 |
109 | Actualizado envio de email
110 | - https://www.lucius.digital/en/blog/sending-html-mails-drupal-89-programmatically-example-drupal-module-including-twig-template
111 |
--------------------------------------------------------------------------------
/Back-end/Entidades.md:
--------------------------------------------------------------------------------
1 | ENTIDADES
2 | ========
3 |
4 | #### Consultas mediante Entidades
5 |
6 | ```php
7 | // Crear entidad
8 | $values = [
9 | 'name' => 'Jose',
10 | 'lastname' => 'Lopez',
11 | ];
12 | $Person = Person::create($values);
13 | $Person->save();
14 | $id = $Person->id();
15 |
16 | //Eliminar entidad
17 | $Entity = NombreEntidad::load($id);
18 | $Entity->delete();
19 |
20 | // Actualizar una entidad
21 | $configuration = Configuration::load($id);
22 | $configuration->set('valuation_method', $valuationMethod);
23 | $configuration->set('costs_method', $costMethod);
24 | $configuration->save();
25 |
26 | // Obtener ids de una entidad con consulta con or condition.
27 | $storage = $this->entityTypeManager->getStorage('alternate_hreflang');
28 | $query = $storage->getQuery();
29 | $group = $query
30 | ->orConditionGroup()
31 | ->condition('url_x__uri', $url, '=')
32 | ->condition('url_a__uri', $url, '=')
33 | ->condition('url_b__uri', $url, '=');
34 | $ids = $query
35 | ->condition('status', TRUE, '=')
36 | ->condition($group)
37 | ->execute();
38 |
39 | // Obtener una entidad mediante consulta
40 | $ids = \Drupal::entityQuery('k_accountplan')
41 | ->condition('iden', $entity, '=')
42 | ->condition('idac', $account->getIdac(), '=')
43 | ->condition('idam', $accountingManagement, '=')
44 | ->sort('number', 'DESC')
45 | ->execute();
46 | $AccountPlan = AccountPlan::load(reset($ids));
47 |
48 | // Obtener multiples entidades mediante consulta
49 | $ids = \Drupal::entityQuery('k_accountingentry')
50 | ->condition('idvo', $voucher->getIdvo(), '=')
51 | ->execute();
52 | $Entries = AccountingEntry::loadMultiple($ids);
53 | foreach ($entries as $entrie) {
54 | ... hacer algo con las entidades ...
55 | }
56 |
57 | // Obtener entidades con tags (Busca las entidades que tienen el tag 'cats')
58 | $query = \Drupal::entityQuery('node')
59 | ->condition('status', 1)
60 | ->condition('field_tags.entity.name', 'cats');
61 | $nids = $query->execute();
62 |
63 | // Operadores de consulta
64 | '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS', 'ENDS_WITH'
65 | 'IN', 'NOT IN', 'IS', 'IS NOT': Esperan un $value en un array de textos del mismo tipo del campo.
66 | 'BETWEEN': Espera un $value en un array de 2 literales del mismo tipo del campo.
67 |
68 | // OR CONDITION
69 | $storage = $this->entityTypeManager->getStorage('node');
70 | // 2147483647 us timestamp in published_at field when no fill.
71 | $or_group = $storage->getQuery()->orConditionGroup()
72 | ->notExists('published_at')
73 | ->condition('published_at', 2147483647, '=');
74 | $query = $storage->getQuery()
75 | ->condition('type', 'node_type')
76 | ->condition($or_group);
77 | $node_ids = $query->execute();
78 |
79 |
80 | // Obtener datos de entidades foraneas
81 | $entity->idac->target_id;
82 | $entity->idac->entity->label();
83 |
84 | // Obtner valor de un atributo de la entidad
85 | $rule->get('variable')->value
86 |
87 | // Guardar imagenes en una entidad
88 | $data = file_get_contents('https://fb-s-b-a.akamaihd.net/h-ak-xpa1/v/t1.0-1/p200x200/15977045_10154309431871267_7175376318146668144_n.jpg?oh=d9e53d50dd85061ce909c3836aa52b09&oe=5925DCAC&__gda__=1499424910_0b04f8498e91f1bff0bbfb6555c8aada');
89 | $file = file_save_data($data, null, FILE_EXISTS_REPLACE);
90 |
91 | //create an entity
92 | $values = [
93 | 'name' => 'My new land',
94 | 'photo' => [ <=== this is the field name image of my custom entity
95 | 'target_id' => $file->id(),
96 | 'alt' => 'Hello world'
97 | ],
98 | ];
99 | $person = DefaultBien::create($values);
100 | $person->save();
101 | ```
102 |
103 | #### Codigos útiles
104 | ```php
105 | // Obtener el id del campo por defecto de una imagen media.
106 | $nids = \Drupal::entityQuery('node')->condition('type','')->execute();
107 | $entity = \Drupal::entityTypeManager()->getStorage('node')->load(reset($nids));
108 | $default_id_media = $entity->get('media')->getFieldDefinition()->getDefaultValue($entity);
109 | if ($default_id_media) {
110 | $default_id_media = reset($default_id_media)['target_id'];
111 | }
112 | ```
113 | #### Campos de Entidades
114 | ```php
115 | // String
116 | $fields['name'] = BaseFieldDefinition::create('string')
117 | ->setLabel(t('Name'))
118 | ->setDescription(t('The name of the PriceFactor entity.'))
119 | ->setSettings([
120 | 'default_value' => '',
121 | 'max_length' => 50,
122 | 'text_processing' => 0,
123 | ])
124 | ->setDisplayOptions('view', [
125 | 'label' => 'above',
126 | 'type' => 'string',
127 | 'weight' => -4,
128 | ])
129 | ->setDisplayOptions('form', [
130 | 'type' => 'string_textfield',
131 | 'weight' => -4,
132 | ])
133 | ->setDisplayConfigurable('form', TRUE)
134 | ->setDisplayConfigurable('view', TRUE);
135 |
136 | // Link
137 | $fields['url_test'] = BaseFieldDefinition::create('link')
138 | ->setLabel(t('URL test'))
139 | ->setDescription(t('URL link.'))
140 | ->setSettings([
141 | 'link_type' => LinkItemInterface::LINK_GENERIC,
142 | 'title' => DRUPAL_DISABLED,
143 | ])
144 | ->setDisplayOptions('form', [
145 | 'type' => 'link_default',
146 | 'weight' => 0,
147 | ])
148 | ->setDisplayConfigurable('form', TRUE);
149 |
150 |
151 | //Lista de strings (Select list)
152 | $fields['test'] = BaseFieldDefinition::create('list_string')
153 | ->setLabel(t('List'))
154 | ->setDescription(t('The list of something.'))
155 | ->setSettings([
156 | 'max_length' => 60,
157 | 'text_processing' => 0,
158 | 'allowed_values' => [
159 | 'key_1' => 'labee_1',
160 | ]
161 | ]
162 | ->setDefaultValue('')
163 | ->setDisplayOptions('view', [
164 | 'label' => 'above',
165 | 'type' => 'string',
166 | 'weight' => 0,
167 | ]
168 | ->setDisplayOptions('form', [
169 | 'type' => 'options_select',
170 | 'weight' => 0,
171 | ])
172 | ->setDisplayConfigurable('form', TRUE)
173 | ->setDisplayConfigurable('view', TRUE);
174 |
175 | // Lista de números
176 | iden lista de strings, poner 'list_integer' en lugar de 'list_string'
177 |
178 | //Decimal
179 | $fields['price'] = BaseFieldDefinition::create('decimal')
180 | ->setLabel(t('Price'))
181 | ->setDescription(t('The amount of the entity'))
182 | ->setDisplayOptions('view', [
183 | 'label' => 'above',
184 | 'type' => 'decimal',
185 | 'weight' => -3,
186 | ])
187 | ->setDisplayOptions('form', [
188 | 'type' => 'number',
189 | 'weight' => -3,
190 | ])
191 | ->setDisplayConfigurable('form', TRUE)
192 | ->setDisplayConfigurable('view', TRUE);
193 |
194 | //Integer
195 | $fields['enum'] = BaseFieldDefinition::create('integer')
196 | ->setLabel(t('Enumeration'))
197 | ->setDescription(t('The order'))
198 | ->setDisplayOptions('view', [
199 | 'label' => 'above',
200 | 'type' => 'integer',
201 | 'weight' => 0,
202 | ])
203 | ->setDisplayOptions('form', [
204 | 'type' => 'number',
205 | 'weight' => 0,
206 | ])
207 | ->setSetting('size', 'big');
208 | ->setDisplayConfigurable('form', TRUE)
209 | ->setDisplayConfigurable('view', TRUE);
210 |
211 | //Boolean (se torna tinyint en mysql)
212 | $fields['predefined'] = BaseFieldDefinition::create('boolean')
213 | ->setLabel(t('Predefined'))
214 | ->setDescription(t('Predefined'))
215 | ->setDisplayOptions('form', [
216 | 'type' => 'boolean_checkbox',
217 | 'settings' => [
218 | 'display_label' => TRUE,
219 | ],
220 | 'weight' => 0,
221 | ])
222 | ->setDisplayConfigurable('form', TRUE);
223 |
224 | //Fecha
225 | $fields['date_start'] = BaseFieldDefinition::create('timestamp')
226 | ->setLabel(t('Date start'))
227 | ->setDescription(t('The date start'))
228 | ->setDisplayOptions('view', [
229 | 'label' => 'adobe',
230 | 'type' => 'timestamp',
231 | 'weight' => 2,
232 | ])
233 | ->setDisplayOptions('form', [
234 | 'type' => 'datetime_timestamp',
235 | 'weight' => 2,
236 | ])
237 | ->setDisplayConfigurable('form', TRUE);
238 |
239 | //Text o String long
240 | $fields['description'] = BaseFieldDefinition::create('string_long')
241 | ->setLabel(t('Description'))
242 | ->setDescription(t('The description of the entity'))
243 | ->setTranslatable(TRUE)
244 | ->setSettings([
245 | 'default_value' => '',
246 | ])
247 | ->setDisplayOptions('view', [
248 | 'label' => 'above',
249 | 'type' => 'string',
250 | 'weight' => 4,
251 | ])
252 | ->setDisplayOptions('form', [
253 | 'type' => 'string',
254 | 'weight' => 4,
255 | ])
256 | ->setDisplayConfigurable('form', TRUE)
257 | ->setDisplayConfigurable('view', TRUE);
258 |
259 | //Referecia a otra entidad
260 | $fields['idstore'] = BaseFieldDefinition::create('entity_reference')
261 | ->setLabel(t('Store'))
262 | ->setDescription(t('The store the kardex'))
263 | ->setRequired(TRUE)
264 | ->setSetting('target_type', 'k_store')
265 | ->setSetting('handler', 'default')
266 | ->setDisplayOptions('view', [
267 | 'label' => 'above',
268 | 'type' => 'entity_reference',
269 | 'weight' => 0,
270 | ])
271 | ->setDisplayOptions('form', [
272 | 'type' => 'entity_reference_autocomplete',
273 | 'settings' => [
274 | 'match_operator' => 'CONTAINS',
275 | 'size' => 60,
276 | 'autocomplete_type' => 'tags',
277 | 'placeholder' => '_' . t('Store')
278 | ],
279 | 'weight' => 0,
280 | ])
281 | ->setDisplayConfigurable('form', TRUE)
282 | ->setDisplayConfigurable('view', TRUE);
283 |
284 | //Campo imagen
285 | $fields['photo'] = BaseFieldDefinition::create('image')
286 | ->setSetting('file_extensions', 'png')
287 | ->setSetting ('uri_scheme','public://photos')
288 | ->setLabel(t('Photo'))
289 | ->setDescription(t('Entity photo'))
290 | ->setDefaultValue('')
291 | ->setDisplayOptions('view', [
292 | 'label' => 'above',
293 | 'type' => 'file',
294 | 'weight' => -4,
295 | ])
296 | ->setDisplayOptions('form', [
297 | 'type' => 'file',
298 | 'weight' => -4,
299 | ])
300 | ->setDisplayConfigurable('form', TRUE)
301 | ->setDisplayConfigurable('view', TRUE);
302 |
303 | //Campo referenciado a taxonomias con botones de selección
304 | $fields ['category'] = BaseFieldDefinition::create ('entity_reference')
305 | ->setLabel(t( 'Category'))
306 | ->setDescription(t('Taxonomi term'))
307 | ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
308 | ->setSetting ('target_type','taxonomy_term')
309 | ->setTranslatable (TRUE)
310 | ->setDisplayOptions ('form', [
311 | 'type' => 'options_buttons',
312 | 'weight' => - 10 ,
313 | 'settings' => [
314 | 'match_operator' => 'CONTAINS' ,
315 | 'size' => '60' ,
316 | 'placeholder' => '' ,
317 | ],
318 | ])
319 | ->setDisplayConfigurable('form', TRUE)
320 | ->setDisplayConfigurable('view', TRUE);
321 |
322 | //Campo referenciado a taxonomias con autocomplete
323 | $fields ['category'] = BaseFieldDefinition::create ('entity_reference')
324 | ->setLabel(t( 'Category'))
325 | ->setDescription(t('Taxonomi term'))
326 | ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
327 | ->setSetting ('target_type','taxonomy_term')
328 | ->setTranslatable (TRUE)
329 | ->setDisplayOptions ('form', [
330 | 'type' => 'entity_reference_autocomplete',
331 | 'weight' => - 10 ,
332 | 'settings' => [
333 | 'match_operator' => 'CONTAINS' ,
334 | 'size' => '60' ,
335 | 'autocomplete_type' => 'tags' ,
336 | 'placeholder' => '' ,
337 | ],
338 | ])
339 | ->setDisplayConfigurable('form', TRUE)
340 | ->setDisplayConfigurable('view', TRUE);
341 | ```
342 |
343 |
344 | PROGRAMAR REGISTRO DE ENTIDADES EN TRANSACCIONES
345 | =======
346 | ```php
347 | $database = \Drupal::database();
348 | $transaction = $database->startTransaction();
349 | $id_branch = null;
350 | try {
351 | if(empty($id_branch)) {
352 | throw new \Exception('Empty: Branch Entity id.');
353 | }
354 | $Branch = Entities::load($id_branch);
355 | $branch_address = $Branch->getAddress();
356 |
357 | for ($i = 0; $i < 8000; $i++) {
358 | $values = [
359 | 'entity' => $id_branch,
360 | 'name' => 'Store ' . $i,
361 | 'address' => $branch_address,
362 | ];
363 | $Store = Store::create($values);
364 | $Store->save();
365 | }
366 |
367 | }
368 | catch (\Exception $e) {
369 | $transaction->rollback();
370 | watchdog_exception('nombre_modulo', $e, $e->getMessage());
371 | throw new \Exception( $e->getMessage(), $e->getCode(), $e->getPrevious());
372 | }
373 | ```
374 |
375 | ENLACES Y FUENTES
376 | =================
377 | Documentación oficial
378 | - https://api.drupal.org/api/drupal/8
379 |
380 | Documentación de la comunidad
381 | - https://www.drupal.org/developing/api/8
382 |
383 | Watchdow drupal 8
384 | - https://www.drupal.org/node/2270941
385 |
386 | Entidades
387 | - http://talks.shawnduncan.org/entity_talk/#/overview
388 | - http://talks.shawnduncan.org/entity_talk/images/Entity.svg
389 |
390 | Tipos de campos
391 | - http://bit.ly/1qhjSQ6
392 |
393 | Entidades traducibles
394 | - https://www.drupal.org/docs/develop/translating-custom-entities
--------------------------------------------------------------------------------
/Back-end/EntityTypeManager.md:
--------------------------------------------------------------------------------
1 | EntityTypeManager
2 | ========
3 |
4 | #### Servicio para realizar consultas a entidades
5 |
6 | Operar sobre el formuario de una entidad
7 | ```php
8 | protected function getBundleForm($entity_type_id, $bundle, $bundle_label, array $form, FormStateInterface $form_state, $bundle_count) {
9 | $entityType = $this->entityTypeManager->getDefinition($entity_type_id);
10 | $entity = $this->entityTypeManager->getStorage($entity_type_id)->create([
11 | $entityType->getKey('bundle') => $bundle,
12 | ]);
13 |
14 | if (!isset($form[$entity_type_id])) {
15 | $form[$entity_type_id] = [
16 | '#type' => 'container',
17 | '#tree' => TRUE,
18 | ];
19 | }
20 |
21 | // If there is no bundle label, the entity has no bundles.
22 | if (empty($bundle_label)) {
23 | $bundle_label = $entityType->getLabel();
24 | }
25 | $form[$entity_type_id][$bundle] = [
26 | '#type' => 'details',
27 | '#open' => ($bundle_count === 1),
28 | '#title' => $entityType->getLabel() . ' - ' . $bundle_label,
29 | '#parents' => [$entity_type_id, $bundle],
30 | ];
31 |
32 | $form_display = EntityFormDisplay::collectRenderDisplay($entity, 'bulk_edit');
33 | // Build entity form.
34 | $form_display->buildForm($entity, $form[$entity_type_id][$bundle], $form_state);
35 | // Get only the field moderation_state.
36 | $this->getModerationStateForm($form[$entity_type_id][$bundle]);
37 |
38 | return $form;
39 | }
40 |
41 | protected function getModerationStateForm(array &$form) {
42 | $field = 'moderation_state';
43 | foreach (Element::children($form) as $key) {
44 | if ($key != $field) {
45 | unset($form[$key]);
46 | }
47 | }
48 | }
49 |
50 | public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
51 | $storage = $form_state->getStorage();
52 | $bundle_data = $storage['moderation_entity_bundles_data'];
53 | $field = "name_of_field";
54 | foreach ($bundle_data as $entity_type_id => $bundles) {
55 | $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
56 | foreach ($bundles as $bundle => $label) {
57 | $form_clone = $form;
58 | $form_clone['#parents'] = [$entity_type_id, $bundle];
59 | $entity = $this->entityTypeManager->getStorage($entity_type_id)->create([
60 | $entity_type->getKey('bundle') => $bundle,
61 | ]);
62 | $form_display = EntityFormDisplay::collectRenderDisplay($entity, 'bulk_edit');
63 | // Extract form values into $entity.
64 | $form_display->extractFormValues($entity, $form_clone, $form_state);
65 | $this->configuration[$entity_type_id][$bundle][$field] = $entity->{$field}->getValue();
66 | }
67 | }
68 | $this->configuration['_add_values'] = $form_state->getValue('_add_values');
69 | }
70 | ```
71 |
72 | ENLACES Y FUENTES
73 | =================
74 | Documentación oficial
75 | https://api.drupal.org/api/drupal/8
76 |
77 | Documentación de la comunidad
78 | https://www.drupal.org/developing/api/8
79 |
--------------------------------------------------------------------------------
/Back-end/Errores.md:
--------------------------------------------------------------------------------
1 | Manejo de errores
2 | ===
3 |
4 | #### Error handler
5 | ```php
6 | ```
7 |
8 | Referencias
9 | ===
10 | - https://www.drupal.org/docs/develop/coding-standards/php-exceptions
--------------------------------------------------------------------------------
/Back-end/Esquemas.md:
--------------------------------------------------------------------------------
1 |
2 | Esquemas
3 | ===
4 |
5 | ENLACES Y FUENTES
6 | =================
7 | Documentación oficial
8 | + https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-schemametadata
--------------------------------------------------------------------------------
/Back-end/Fechas.md:
--------------------------------------------------------------------------------
1 | Fechas
2 | ===
3 |
4 | #### Fechas
5 | ```
6 | // Convertir una fecha a un formato de la isntancia Drupal
7 | format_date($rowKardex->getDate(), 'khipu_short'); //deprecado
8 | \Drupal::service('date.formatter')->format($Service->getDate(), 'khipu_short');
9 |
10 | // Fecha actual formateado para Drupal
11 | $date = date('Y-m-d H:i:s');
12 | new DrupalDateTime($date)
13 |
14 | // Conmvertir de formato europeo Y-m-d a un formato configurado en el sitio html_date
15 | use Drupal\Core\Datetime\DrupalDateTime;
16 |
17 | $time = DrupalDateTime::createFromFormat('Y-m-d', $date_string);
18 | $date_formatter = \Drupal::service('date.formatter');
19 | $date_converted = $date_formatter->format($time->getTimestamp(), 'html_date');
20 | ```
21 |
--------------------------------------------------------------------------------
/Back-end/Formularios.md:
--------------------------------------------------------------------------------
1 | FORMULARIOS
2 | ========
3 |
4 | #### Manejo
5 |
6 | ```php
7 | //Obtener todos los elementos de un form_state
8 | foreach ($form_state->getValues() as $key => $value) {
9 | drupal_set_message($key . ': ' . $value);
10 | }
11 | //Obtener un elemento de un form_state
12 | $searched = $form_state->getValue('nombre_elemento_formulario');
13 |
14 | ```
15 |
16 | #### Campos de formularios
17 | ```php
18 | // Date
19 | $form['date'] = [
20 | '#type' => 'date',
21 | '#default_value' => $year . "-" . $month . "-" . $day,
22 | '#weight' => 13,
23 | ];
24 |
25 | // Textfield con autocompletado
26 | $form['products'] = [
27 | '#type' => 'textfield',
28 | '#placeholder' => '_' . t('Item'),
29 | '#autocomplete_route_name' => 'k_product.active.autocomplete',
30 | '#weight' => 17,
31 | ];
32 |
33 | // Datetime
34 | $form['date_validity'] = [
35 | '#type' => 'datetime',
36 | '#date_date_element' => 'date',
37 | '#date_time_element' => 'time',
38 | '#required' => TRUE,
39 | '#default_value' => "",
40 | '#attributes' => [
41 | 'placeholder' => '_' . t('Validity date'),
42 | ],
43 | '#weight' => 15,
44 | ];
45 |
46 | // Select
47 | $form['payment'] = [
48 | '#type' => 'select',
49 | '#attributes' => [
50 | 'title' => t('Payment Method')
51 | ],
52 | '#options' => [
53 | 'CASH' => t('Cash'),
54 | 'CHECK' => t('Check'),
55 | 'TRANSFER' => t('Wire Transfer')
56 | ],
57 | '#default_value' => 'CASH',
58 | ];
59 |
60 | // Checkboxes
61 | $form['platforms'] = [
62 | '#title' => $this->t('Platforms:'),
63 | '#type' => 'checkboxes',
64 | '#description' => $this->t('Select platforms to use as social media links.'),
65 | '#options' => ['key_a'=> 'text a', 'key_b'=> 'text b', 'key_c'=> 'text c'],
66 | '#default_value' => ['key_a'],
67 | ];
68 |
69 | // Radios
70 | $form['frequency_options'] = [
71 | '#type' => 'radios',
72 | '#title' => $this->t('Select the type to frequency to use.'),
73 | '#options' => [
74 | 'visit_counts' => $this->t('Use visit counts frequency'),
75 | 'time_frequency' => $this->t('Use time frequency'),
76 | 'pages_counts' => $this->t('Use pages visitor counter frequency'),
77 | 'stay_time' => $this->t('Use visitor stay time frequency'),
78 | ],
79 | "#default_value" => 'visit_counts',
80 | '#weight' => -2,
81 | ];
82 |
83 |
84 | // Button
85 | $form['minus'] = [
86 | '#type' => "button",
87 | '#value' => "-",
88 | '#attributes' => [
89 | 'class' => ['addOperator'],
90 | ],
91 | '#weight' => 97,
92 | ];
93 |
94 | // Textfield
95 | $form['shortDescription'] = [
96 | '#type' => 'textfield',
97 | '#default_value' => $shortDescription,
98 | '#size' => 90,
99 | '#maxlength' => 90,
100 | '#attributes' => [
101 | 'placeholder' => '_' . t('Short Description'),
102 | ],
103 | '#weight' => 1000,
104 | ];
105 |
106 | // Número telefónico
107 | $form['phone_number'] = [
108 | '#type' => 'tel',
109 | '#title' => $this->t('Example phone'),
110 | ];
111 |
112 | // Número
113 | $form['page_counts'] = [
114 | '#type' => 'number',
115 | '#title' => $this->t('Visited page counter'),
116 | '#description' => $this->t("Examples:
117 | 0 = Show popup after each page visited
118 | 1 = Show popup on the first page visited
119 | n = Show popup on n page visited"),
120 | '#default_value' => 3,
121 | '#attributes' => [
122 | 'min' => 0,
123 | 'max' => 100,
124 | ],
125 | ];
126 |
127 | // Textarea
128 | $form['pr']['obs'] = [
129 | '#type' => 'textarea',
130 | '#placeholder' => '_' . t('Observation'),
131 | '#attributes' => ['title' => t('Observation')],
132 | ];
133 |
134 | // Texto procesado.
135 | 'confirmation_message' => [
136 | '#type' => 'processed_text',
137 | '#text' => '',
138 | '#format' => 'basic_html',
139 | ],
140 |
141 |
142 | // Hidden con ramas abiertas(arreglo multidimencional) enviadas cuando el formulario sea guardado.
143 | $form['plugin_configuration'] = [
144 | '#type' => 'hidden',
145 | '#tree' => TRUE,
146 | '#open' => TRUE,
147 | ]
148 | $form['plugin_configuration'][$id] = [
149 | '#process' => [[get_class($this), 'processPluginConfiguration']],
150 | '#plugin' => $plugin,
151 | ]
152 |
153 | // Nombre de sistema (machine name)
154 | $form['id'] = [
155 | '#type' => 'machine_name',
156 | '#default_value' => $importer->id(),
157 | '#machine_name' => [
158 | 'exists' => '\Drupal\products\Entity\Importer::load',
159 | ],
160 | '#disabled' => !$importer->isNew(),
161 | ];
162 |
163 | // Enlace url
164 | $form['url'] = [
165 | '#type' => 'url',
166 | '#default_value' => $importer->getUrl() instanceof Url ? $importer->getUrl()->toString() : '',
167 | '#title' => $this->t('Url'),
168 | '#description' => $this->t('The url to the import resource'),
169 | '#required' => TRUE,
170 | ];
171 |
172 | // Template twig en línea
173 | $form['answer'] = [
174 | '#type' => 'inline_template',
175 | '#template' => "{% trans %} Hello {% endtrans %} {{user_name}}",
176 | '#context' => [
177 | 'user_name' => $user_name,
178 | ],
179 | ];
180 |
181 | // Elementos tag html
182 | $form['title'] = [
183 | '#type' => 'html_tag',
184 | '#tag' => 'h2',
185 | '#value' => $this->t('Regret cancellation'),
186 | ];
187 | $form['intro'] = [
188 | '#type' => 'html_tag',
189 | '#tag' => 'p',
190 | '#value' => $this->t('Do you confirm that you want keep your membership %subscription instead of cancelling it on %date?', [
191 | '%subscription' => $subscription_label,
192 | '%date' => $date,
193 | ]),
194 | ];
195 |
196 | // Picker de color
197 | $form['icon_hovered'] = [
198 | '#type' => 'color',
199 | '#title' => $this->t('Icon hovered'),
200 | '#maxlength' => 8,
201 | '#size' => 8,
202 | '#default_value' => $data['icon_hovered'],
203 | ];
204 |
205 | ```
206 |
207 | #### Estados
208 | Permiten condicionar el comportamiento de un elemento de formulario a partir del estado otro elemento.
209 | ```php
210 | $form['boys'] = [
211 | '#type' => 'checkbox',
212 | '#title' => $this->t('Do you have boys?'),
213 | ];
214 |
215 | $form['boys_nomber'] = [
216 | '#type' => 'textfield',
217 | '#title' => $this->t('How many boys do you have?'),
218 | '#states' => [
219 | 'visible' => [
220 | 'input[name="boys"]' => ['checked' => TRUE],
221 | ]
222 | ]
223 | ];
224 |
225 | ```
226 | Estados:
227 | - visible
228 | - invisible
229 | - enabled
230 | - disabled
231 | - required
232 | - optional
233 | - checked
234 | - unchecked
235 | - collapsed
236 |
237 | Detonantes:
238 | - checked
239 | - empty
240 | - filled
241 | - unchecked
242 | - expanded
243 | - collapsed
244 | - value
245 |
246 |
247 | #### Webform
248 | Consultas
249 | ```php
250 | $submission_storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
251 | $ids_ws = $submission_storage->getQuery()
252 | ->accessCheck(FALSE)
253 | ->condition('uuid', $submission_uuid)
254 | ->execute();
255 | if (count($ids_ws) == 1) {
256 | $id_ws = reset($ids_ws);
257 | $webform_submission = $submission_storage->load($id_ws);
258 | $webform_submission_data = $webform_submission->getData();
259 |
260 | if ($webform_submission_data['numero_de_socio'] == $codigo_de_socio) {
261 | $email = $webform_submission_data['correo_electronico'];
262 | $whatsapp_number = $webform_submission_data['numero_celular_con_whatsapp'];
263 | $status = TRUE;
264 | }
265 | else {
266 | $status = FALSE;
267 | }
268 | }
269 |
270 |
271 | $select = \Drupal::service('database')
272 | ->select('webform_submission_data', 'wsd')
273 | ->fields('wsd', array('sid'))
274 | ->orderBy('wsd.sid', 'DESC')
275 | ->condition('wsd.webform_id', 'id_formulario', '=')
276 | ->condition('wsd.name', 'nombre_sistema_del_campo', '=')
277 | ->condition('wsd.value', $some_value, '=')
278 | ->execute();
279 | $results = $select->fetchAll(\PDO::FETCH_COLUMN);
280 |
281 | ```
282 |
283 | ENLACES Y FUENTES
284 | =================
285 | Documentación oficial
286 | - https://api.drupal.org/api/drupal/core%21core.api.php/group/form_api/9.1.x
287 |
288 |
289 | Implementar un formulario en un modal llamando desde otro formulario con ajax
290 | - https://www.drupal.org/project/drupal/issues/2934463
291 |
292 | Alterar un formulario extendiendolo
293 | - https://www.foreach.be/blog/how-manipulate-forms-drupal-8
294 |
295 | Sobreescribir la ruta pasando parametros en array
296 | - http://www.impraveen.com/override-route-controller-drupal-8
297 |
298 | Tablas con paginador
299 | - https://zanzarra.com/blog/drupal-custom-pager-and-table-header-sortable-without-sql-query
300 |
--------------------------------------------------------------------------------
/Back-end/InyeccionDependencias.md:
--------------------------------------------------------------------------------
1 | Inyección de dependencias
2 | ========
3 |
4 | #### Servicio para realizar consultas a entidades
5 |
6 | Llamar al servicio
7 | ```php
8 | use Drupal\Core\Entity\EntityTypeManagerInterface;
9 | ```
10 |
11 | Inyectar el servicio en el constructor.
12 | ```php
13 | * ...
14 | * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
15 | * Entity type manager.
16 | * ...
17 | */
18 | public function __construct(..., EntityTypeManagerInterface $entityTypeManager, ...) {
19 | parent::__construct(...);
20 | ...
21 | $this->entityTypeManager = $entityTypeManager;
22 | ...
23 | }
24 | ```
25 |
26 | Instanciar el servicio al momento de crear el objeto.
27 | ```php
28 | ...
29 | public static function create(..., ContainerInterface $container, ...) {
30 | return new static(
31 | ...,
32 | $container->get('entity_type.manager'),
33 | ...
34 | );
35 | }
36 |
37 |
38 | // Ejemplo de create sin necesidad de reescribir el constructor.
39 | public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
40 | $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
41 | $instance->entityTypeManager = $container->get('entity_type.manager');
42 | return $instance;
43 | }
44 | ```
45 |
46 | Utilizar el servicio.
47 | ```php
48 | $entityTypeDefinition = $this->entityTypeManager->getDefinition($entity_type_id);
49 | if ($bundle_key = $entityTypeDefinition->getKey('bundle')) {
50 | $results = $this->entityTypeManager->getStorage('node')->loadByProperties([
51 | 'nid' => $entity_ids
52 | ]);
53 | foreach ($results as $node) {
54 | $type = $node->getType();
55 | if (!isset($bundle_data[$entity_type_id][$type])) {
56 | $bundle_data[$entity_type_id][$type] = $bundle_info[$entity_type_id][$type]['label'];
57 | }
58 | }
59 | }
60 | ```
61 |
62 | ENLACES Y FUENTES
63 | =================
64 | Documentación oficial
65 | - https://api.drupal.org/api/drupal/8
66 |
67 | Documentación de la comunidad
68 | - https://www.drupal.org/developing/api/8
69 |
70 | La manera correcta de implementar
71 | - https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/dependency-injection-for-a-form
--------------------------------------------------------------------------------
/Back-end/Logs.md:
--------------------------------------------------------------------------------
1 | Logs
2 | ===
3 |
4 | #### Watchdog (log de drupal)
5 | ```
6 | //Guardar un texti en el log (Watchdog)
7 | \Drupal::logger('mi_modulo')->notice("Mi mensaje");
8 | \Drupal::logger('mi_modulo')->error("Mi mensaje");
9 | ```
10 |
--------------------------------------------------------------------------------
/Back-end/MVC.md:
--------------------------------------------------------------------------------
1 | MVC
2 | ========
3 | #### Ruta: en mimodulo/mimodulo.routing.yml
4 | ```yml
5 | mimodulo.nombre_de_la_ruta:
6 | path: /ruta/que-se-requiera
7 | defaults:
8 | _controller: Drupal\mimodulo\Controller\NombreControladorController::nombre_metodo
9 | _title: 'Aqui el título'
10 | requirements:
11 | _permission: mimodulo.nombre_del_permiso
12 | ```
13 |
14 | #### Permiso: en mimodulo/mimodulo.permissions.yml
15 | ```yml
16 | mimodulo.nombre_del_permiso:
17 | title: "Título del privilegio"
18 | description: "Descripción del privilegio"
19 | restrict access: true
20 |
21 | ```
22 |
23 | #### Hoock en el módulo: en mimodulo/mimodulo.module
24 | ```php
25 | function mimodulo_theme() {
26 | $theme['nombre_template'] = [
27 | 'variables' => [
28 | 'variable_1' => NULL,
29 | 'variable_n' => NULL
30 | ],
31 | 'template' => 'nombre_template',
32 | ];
33 | return $theme;
34 | }
35 | ```
36 |
37 | #### Controlador: en mimodulo/src/Controller/NombreControladorController.php
38 | ```php
39 | 'nombre_template',
68 | '#variable_1' => $x,
69 | '#variable_n' => $y,
70 | '#cache' => [
71 | 'max-age' => 0,
72 | ],
73 | ];
74 | }
75 |
76 | }
77 | ```
78 |
79 | #### Template: en mimodulo/templates/nombre_template.html.twig
80 | ```html
81 |
82 |
83 |
{{ audio }}
84 |
{% trans %} List of {{ variable_1 }} {% endtrans %}
85 |
86 |
87 | {% for item in variable_n %}
88 | - {{ item.name }}
89 | {% endfor %}
90 |
91 |
92 |
93 | ```
94 |
95 |
96 |
97 | ENLACES Y FUENTES
98 | =================
99 |
--------------------------------------------------------------------------------
/Back-end/Mensajes.md:
--------------------------------------------------------------------------------
1 | Mensajes
2 | ===
3 |
4 | #### Mensajes a la interface del usuario
5 | ```php
6 | //Mensajes del sistema
7 | \Drupal::messenger()->addMessage(t('An error occurred and processing did not complete.'), 'error');
8 |
9 | \Drupal::messenger()->addStatus(t('This is a successful message.'));
10 | \Drupal::messenger()->addWarning(t('This is a warning message.'));
11 | \Drupal::messenger()->addError(t('This is an error message.'));
12 | ```
13 |
14 | #### Mensajes al sistema de logs (Whatchdog)
15 | ```php
16 | // Noticias
17 | \Drupal::logger('mi_modulo')->notice($message);
18 |
19 | // Errores
20 | \Drupal::logger('mi_modulo')->error($message);
21 | ```
--------------------------------------------------------------------------------
/Back-end/Migraciones/Migrate.md:
--------------------------------------------------------------------------------
1 | Migrate
2 | ========
3 |
4 | #### Ejemplos de uso de plugins.
5 |
6 | Obtener el arbol de términos de una taxonomía.
7 | ```
8 | ```
9 |
10 |
11 |
12 | ENLACES Y FUENTES
13 | =================
14 | Documentación oficial
15 | - https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins
16 |
17 | Lista de los plugins
18 | - https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/list-of-core-migrate-process-plugins
19 |
20 | Explicacion de migration_lookup, entity_lookup, entity_generate
21 | - https://understanddrupal.com/articles/understanding-entitylookup-and-entitygenerate-process-plugins-migrate-tools
--------------------------------------------------------------------------------
/Back-end/Migraciones/MigrateAPI.md:
--------------------------------------------------------------------------------
1 | Migrate Plus
2 | ========
3 |
4 |
5 |
6 | #### Enlaces y fuentes.
7 | Migrate API
8 | - https://www.drupal.org/docs/drupal-apis/migrate-api
9 |
10 | Migrando usando query sql para obtener los datos fuente
11 | - https://www.drupal.org/docs/8/api/migrate-api/migrate-source-plugins/migrating-data-from-a-sql-source
12 |
13 | Ejemplos de migraciones: nodos, taxonomias, terminos, usuarios, archivos e imágenes, media, configuraciones, commerce.
14 | - https://www.drupal.org/docs/drupal-apis/migrate-api/migrate-destination-plugins-examples
15 |
16 | Ejemplos básicos de process
17 | - https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/migrate-process-overview
18 |
19 | Lista de plugins para process
20 | - https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/list-of-core-migrate-process-plugins
--------------------------------------------------------------------------------
/Back-end/Migraciones/d7-a-d8.md:
--------------------------------------------------------------------------------
1 | Migrar un sitio completo de drupal 7 a drupal 8
2 | ========
3 |
4 | #### Resumen del proceso
5 | ```
6 | Preparar sitio D7 > Prepara sitio D8 > Migrar > Configuraciones manuales.
7 | ```
8 |
9 | #### Preparar D7 para ser migrado.
10 | ```
11 | 1. Tener el sitio en local.
12 | 2. Identificar los módulos contribuidos a ser migrados.
13 | admin/reports/updates
14 | Para cada módulo contestar
15 | Necesito este módulo en D8?
16 | Si => Está el módulo incluido en el core de D8?
17 | Si => Utilizarlo.
18 | No => Existe este módulo para D8?
19 | Si => Utilizarlo.
20 | No => Existe otro módulo para D8 que cumpla la misma función?
21 | Si => Agregarlo manualmente.
22 | No => Resignar o implementar una solución custom. Sin embargo posiblemente esta funcionalidad ya no está vigente.
23 | 3. Revizar y conocer los problemas conocidos que tiene actualmente el proceso en
24 | https://www.drupal.org/docs/8/upgrade/known-issues-when-upgrading-from-drupal-6-or-7-to-drupal-8#s-drupal-7-to-8
25 | 4. Actualizar el core y todos los módulos contribuidos.
26 | 5. Verificar el acceso público(navegador) a los archivos públicos (public files)
27 | ```
28 |
29 | #### Preparar D8 par la migración.
30 | ```
31 | 1. Tener una instalación limpia(sin contenido ni configuraciones adicionadas).
32 | 2. Tener acceso a la base de datos de D7 y D8 desde el mismo host.
33 | En D8 configurar settings.php
34 | $databases['default']['default'] = [
35 | 'database' => 'd8db',
36 | 'username' => 'd8user',
37 | 'password' => 'd8pass',
38 | 'prefix' => '',
39 | 'host' => 'localhost',
40 | 'port' => '3306',
41 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
42 | 'driver' => 'mysql',
43 | ];
44 |
45 | $databases['migrate']['default'] = [
46 | 'database' => 'd7db',
47 | 'username' => 'd7user',
48 | 'password' => 'd7pass',
49 | 'prefix' => '',
50 | 'host' => 'localhost',
51 | 'port' => '3306',
52 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
53 | 'driver' => 'mysql',
54 | ];
55 | 3. Si se necesitan migrar archivos privados de D7
56 | Estos deben ser accesibles desde D8 y se deben configurar file_private_path en settings.php antes de corres el upgrade.
57 | 4. Instalar Drush 8 o 9 en el proyecto.
58 | Si has instalado drupal mediante composer, yá tienes drush como una dependencia en composer.json
59 | Si nó puedes ejecutar:
60 | $ composer require drush/drush
61 | 5. Instalar los siguientes módulos:
62 | - migrate (core)
63 | - migrate_drupal (core)
64 | - migrate_drupal_ui - Opcional, si se va hacer la migración por UI.
65 | - migrate_drupal_multilingual - Opcional, si es un sitio multiidiomas.
66 | - migrate_upgrade - Soporte para comandos drush de actualización de versión de drupal.
67 | - migrate_plus - Extensiones útiles al core de migrate.
68 | - migrate_tools - Comandos drush a utilizar en la migración.
69 | 6. Habilitar todos los módulos homologados de D7 en D8.
70 | 7. Colocar el sitio en modo mantenimiento.
71 | ```
72 |
73 | #### Migrar mediante navegador web.
74 | ```
75 | Recomendado si eres novato en migraciones con Drupal.
76 | 1. Ir a la interface gráfica: /upgrade
77 | Seguir el procedimiento indicado.
78 | ```
79 |
80 | #### Migrar mediante DRUSH.
81 | ```
82 | Es la manera más robusta y veloz, pero requiere módulos adicionales y configuraciones.
83 |
84 | UTILIZANDO COMANDOS DIRECTOS
85 | 2. Generar las migraciones usando migrate-upgrade.
86 | Ver la lista de migraciones posibles.
87 | $ drush migrate-status
88 |
89 | Ejecutar todas las migraciones.
90 | drush migrate-import --all
91 |
92 | Generar la migración completa en el sitio D7 desde el espacio D8
93 | $ drush migrate-upgrade
94 |
95 | Si se necesita sólo migrar las configuraciones.
96 | $ drush migrate-upgrade --legacy-db-url=mysql://user:password@server/db --legacy-root=http://url-del-sitio-d7.com --configure-only
97 |
98 | Ejecutar migraciones selectivamente.
99 | drush migrate-import
100 |
101 |
102 | UTILIZANDO MANIFIESTOS
103 | 1. Instalar el módulo migrate_manifest
104 |
105 | Obtener la lista completa de migraciones en un archivo yml
106 | # drush migrate-template-list //drush 8
107 | # drush migrate:template:list //drush 9
108 |
109 | 2. Colocar el archivo yml en en un lugar accesible por drush. (de preferencia dentro del versionamiento de git)
110 |
111 | 3. Asegurarse de que todos los módulos usados en el manifiesto de migración existen y están habilitados en D8.
112 |
113 | 4. Ejecutar la las migraciones especificadas en el manifiesto.
114 | $ drush migrate-manifest --legacy-db-url=mysql://d7user:d7pass@localhost/drupal_7 manifest.yml
115 | ```
116 |
117 | #### Configuraciones manuales.
118 | ```
119 | Luego de migrar el contenido y las configuraciones. Es muy posible que hayan módulos que instalar, configuraciones que completar.
120 | ```
121 |
122 | ENLACES Y FUENTES
123 | =================
124 | Documentación oficinal de drupal
125 | - https://www.drupal.org/docs/8/upgrade/upgrading-from-drupal-6-or-7-to-drupal-8-and-newer
126 |
127 | Lista de módulos útiles para la migración
128 | - https://www.drupal.org/docs/8/upgrade/drupal-8-migrate-modules
129 |
130 | Actualizar mediante navegador web
131 | - https://www.drupal.org/docs/8/upgrade/upgrade-using-web-browser
132 |
133 | Actualizar mediante drush
134 | - https://www.drupal.org/docs/8/upgrade/upgrade-using-drush
135 |
136 |
--------------------------------------------------------------------------------
/Back-end/Migraciones/importar-contenido.md:
--------------------------------------------------------------------------------
1 | Migrar contenido
2 | ========
3 | #### Módulos involucrados.
4 | ```
5 | migrate - Framework de migraciones hacia Drupal(nodes, users, files, terms, comments) desde otras fuentes.
6 | migrate_tools - Kit de herramientas para ejecutar y administrar migraciones (status, import, rollback, stop, reset-status, messages, fiedls-source)
7 | migrate_plus - Extensiones al core de migrate (Configuration entities, extensiones del API como PREPARE_ROW, etc.)
8 | migrate_source_csv - Funcionalidad completa para importar archivos CSV.
9 | config_devel - Ayuda a configrar el entorno para importaciones y exportaciones automáticas.
10 | ```
11 | #### Proceso.
12 | ```
13 | Crear el tipo de contenido.
14 | Crear un módulo nuevo.
15 | Crear la estructura de archivos.
16 | Crear el archivo de datos csv.
17 | Crear el archivo de importación yml.
18 | Testear la migración (comandos drush)
19 | ```
20 | #### Comandos drush.
21 | ```
22 | Lista de todas las migraciones disponibles
23 | $ drush ms
24 |
25 | Realizar la importación de una migración
26 | $ drush mi
27 | ```
28 | #### Todo lo que se puede hacer.
29 | ```
30 | - Importar archivos pdf, imágenes, etc.
31 | - Importar en diferentes tipos de campos.
32 | - Importar en entidades relacionadas.
33 | - Combinaciones de plugibs estándar (explode, default_value, concat, etc.)
34 | - Crear plugins propios.
35 | ```
36 |
37 | ENLACES Y FUENTES
38 | =================
39 | Buen video explicativo que muestra como usar migrate
40 | https://www.youtube.com/watch?v=zZLL02GkP9E&t=1372s
41 |
--------------------------------------------------------------------------------
/Back-end/Multiidiomas.md:
--------------------------------------------------------------------------------
1 | Multiidiomas
2 | ========
3 | #### Configurar un sitio multi-idiomas
4 | ```md
5 | Instalar los módulos:
6 | - Configuration Translation.- Traducir las configuraciones. (Ttulo de un bloque, etc)
7 | - Content translation.- Traducir entidades de contenido. (Nodos, Media, Taxonomías, etc)
8 | - Interface translation.- Traducir la interface de usuario.
9 | - Language.- Configurar los idiomas disponibles y su aplicación al contenido.
10 |
11 | 1. Agregar idiomas.
12 | - /admin/config/regional/language
13 |
14 | 2. Configurar detección y selección.
15 | - /admin/config/regional/language/detection
16 |
17 | 3. Agregar el selector de idiomas.
18 | - Utilizar el bloque "Language switche"
19 |
20 | 4. Configurar elementos que van a ser traducibles.
21 | - /admin/config/regional/content-language
22 | - Lista de entidades que van a ser traducibles.
23 | - Es necesaro elegir cuales(content, taxonomies, etc) y sus elementos internos como los campos.
24 |
25 | 5. Traducir la interface gráfica:
26 | - /admin/config/regional/translate
27 | Permite traducir todos los textos del código fuente de drupal.
28 | - Configuración YML.
29 | - Código PHP.
30 | - Código Javascript.
31 |
32 | 6. Traducir configuración.
33 | - /admin/config/regional/config-translation
34 | Views, Bloques, Formularios, Tipos de contenidos, Formatos de fecha, Estilos de imágen, etc.
35 | ```
36 |
37 | #### Programar etiquetas en otros idiomas
38 |
39 | ```php
40 | // En php
41 | t('Instalación', array(), array('langcode' => 'es', 'context' => 'khipu' ))
42 |
43 | // En javascript
44 | Drupal.t('Delirant'))
45 | Drupal.t('Mayo', {}, {context: "Calendario", 'langcode': 'es'});
46 | ```
47 |
48 | ```twig
49 | // En twig
50 | {{ 'Free carita gift box'|t }}
51 |
52 |
57 |
58 |
61 |
62 |
63 | ```
64 |
65 | ```yml
66 | // En yml
67 | quotation.proposal:
68 | path: '/quotations/proposal'
69 | defaults:
70 | _form: '\Drupal\inventory_io\Form\ProposalForm'
71 | _title: 'Propuesta'
72 | _title_context: 'khipu'
73 | langcode: es
74 | requirements:
75 | _permission: quotation.proposal
76 | ```
77 |
78 | #### Manipulación programática
79 | Utilizar version traducida de una entidad.
80 |
81 | ```php
82 | $category = Term::load($id_category);
83 | $curr_langcode = \Drupal::languageManager()->getCurrentLanguage(\Drupal\Core\Language\LanguageInterface::TYPE_CONTENT)->getId();
84 | $translated = \Drupal::service('entity.repository')->getTranslationFromContext($category, $curr_langcode);
85 | ```
86 |
87 | Utilizar el manejador de lenguaje del core
88 | ```php
89 | $language_manager = \Drupal::languageManager();
90 | $site_default_langcode = $language_manager->getDefaultLanguage()->getId();
91 |
92 | // Obtener las configuraciones de un lenguage
93 | $config_name = basename($file_name, '.yml');
94 | $config = $language_manager->getLanguageConfigOverride($langcode, $config_name);
95 | // Ejemplo
96 | $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
97 | $config_name = basename('role_expire_notification.config', '.yml');
98 | $config = \Drupal::languageManager()->getLanguageConfigOverride($langcode, $config_name);
99 | $configuration_values = $config->get('role_expire_notification_points');
100 | ```
101 |
102 |
103 | ENLACES Y FUENTES
104 | =================
105 | Documentación traducción de código drupal
106 | - https://www.drupal.org/developing/api/8/localization
107 |
108 | Documentación traducción twig
109 | - http://symfony.com/doc/current/book/translation.html
110 |
--------------------------------------------------------------------------------
/Back-end/Nodos.md:
--------------------------------------------------------------------------------
1 | Nodos
2 | ========
3 | #### Query para obtener datos
4 | ```php
5 | // Obtener un nodo con consulta.
6 | $node_storage = $this->entityTypeManager->getStorage('node');
7 | $ids = $node_storage->getQuery()
8 | ->condition('title', $source_title)
9 | ->condition('type', 'quiz')
10 | ->execute();
11 | if (!empty($ids)) {
12 | $node_id = reset($ids);
13 | $node = $node_storage->load($node_id);
14 | }
15 |
16 | // Obtener el entity_type_manager sin injectar como servicio.
17 | $node_storage = \Drupal::entityTypeManager()->getStorage('node');
18 |
19 |
20 | // Obtener todos los nodos de un tipo de contenido
21 | $nids = \Drupal::entityQuery('node')->condition('type','my_custom_type')->execute();
22 | $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
23 |
24 | ```
25 |
26 |
27 | ENLACES Y FUENTES
28 | =================
29 |
--------------------------------------------------------------------------------
/Back-end/PDF.md:
--------------------------------------------------------------------------------
1 | PDF
2 | ========
3 |
4 | #### Generar archivo PDF
5 |
6 | ```php
7 | use Dompdf\Dompdf;
8 | use Drupal\Core\Link;
9 | use Drupal\Core\Url;
10 |
11 |
12 | /** @var \Drupal\Core\Template\TwigEnvironment $twig */
13 | $twig = \Drupal::service('twig');
14 | $dompdf = new Dompdf();
15 | $url = \Drupal::request()->getSchemeAndHttpHost();
16 |
17 | // Predefinimos el destino del archivo para acceso público.
18 | $wrapper = 'public';
19 | $rand = substr(hash('ripemd160', uniqid()), 0, 8);
20 | $filename = 'nombre_del_archivo'. '-' . $rand . '.' . 'pdf';
21 | $destination = $wrapper . '://' . $filename;
22 |
23 | $dompdf->loadHtml($twig->render('@nombre_modulo_theme/folder_del_template/nombre_template.html.twig', [
24 | 'parametro_1_para_twig' => 'valor_1',
25 | 'parametro_3_para_twig' => 'valor_2',
26 | ]));
27 | $dompdf->render();
28 |
29 | sendToFileWithPredestination($dompdf->output(), $destination);
30 |
31 | function sendToFileWithPredestination(string $output, string $destination) {
32 | if (!empty($output) && !empty($destination)) {
33 | $file = file_save_data($output, $destination, FileSystemInterface::EXISTS_REPLACE);
34 | $file->setTemporary();
35 | $file->save();
36 |
37 | // Si fuese nesecario sacar un enlace al archivo.
38 | $file_url = Url::fromUri(
39 | file_create_url($file->getFileUri()),
40 | [
41 | 'attributes' => ['target' => '_blank'],
42 | 'absolute' => TRUE,
43 | ]
44 | );
45 | $link = Link::fromTextAndUrl($this->t('Click here'), $file_url);
46 | $this->messenger()->addStatus($this->t('Export file created, @link to download.', ['@link' => $link->toString()]));
47 | }
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/Back-end/Plugins/API_Plugin.md:
--------------------------------------------------------------------------------
1 | Plugin API
2 | ========
3 |
4 |
5 |
6 | ### Enlaces
7 |
8 | Documentación oficial
9 | - https://www.drupal.org/docs/drupal-apis/plugin-api
10 |
--------------------------------------------------------------------------------
/Back-end/Plugins/FilterPlugin.md:
--------------------------------------------------------------------------------
1 | FilterPlugin
2 | ========
3 |
4 | #### Filtro aplicable a un campo para agregar target_blank a todos los enlaces del contenido
5 | ```
6 | namespace Drupal\mi_modulo\Plugin\Filter;
7 |
8 | use Drupal\Component\Utility\Html;
9 | use Drupal\filter\FilterProcessResult;
10 | use Drupal\filter\Plugin\FilterBase;
11 | use Drupal\Core\Url;
12 |
13 | /**
14 | * Provides a ExternalLinkFilter filter.
15 | *
16 | * @Filter(
17 | * id = "external_link",
18 | * title = @Translation("External links processor"),
19 | * description = @Translation("Updates links with neccessary attribute."),
20 | * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE
21 | * )
22 | */
23 | class ExternalLinkFilter extends FilterBase {
24 |
25 | /**
26 | * {@inheritdoc}
27 | */
28 | public function process($text, $langcode) {
29 | $result = new FilterProcessResult($text);
30 | if (strpos($text, 'href=') !== FALSE) {
31 | $dom = Html::load($text);
32 | $xpath = new \DOMXPath($dom);
33 | foreach ($xpath->query('//a[@href]') as $element) {
34 | $link_uri = $element->getAttribute('href');
35 | if ($link_uri == '') {
36 | $link_uri = Url::fromRoute('')->toString();
37 | $element->setAttribute('href', $link_uri);
38 | }
39 | else {
40 | $base_uri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
41 | if (str_contains($link_uri, $base_uri) === FALSE) {
42 | $element->setAttribute('target', '_blank');
43 | $element->setAttribute('rel', 'noopener');
44 | }
45 | }
46 | }
47 | $result->setProcessedText(Html::serialize($dom));
48 | }
49 |
50 | return $result;
51 | }
52 |
53 | }
54 | ```
55 |
--------------------------------------------------------------------------------
/Back-end/Plugins/LanguageNegotiation.md:
--------------------------------------------------------------------------------
1 | Laanguage negotiation
2 | ========
3 |
4 | #### Filtro aplicable a un campo para agregar target_blank a todos los enlaces del contenido
5 | ```
6 | namespace Drupal\mi_modulo\Plugin\LanguageNegotiation;
7 |
8 | use Drupal\language\LanguageNegotiationMethodBase;
9 | use Symfony\Component\HttpFoundation\Request;
10 |
11 | /**
12 | * Custom class for identifying language.
13 | *
14 | * @LanguageNegotiation(
15 | * id = Drupal\mi_modulo\Plugin\LanguageNegotiation\LanguageNegotiationAnonymous::METHOD_ID,
16 | * weight = -99,
17 | * name = @Translation("Anonymous Language always English"),
18 | * description = @Translation("Language based on anonymous restriction to view always the website an English."),
19 | * )
20 | */
21 | class LanguageNegotiationAnonymous extends LanguageNegotiationMethodBase {
22 |
23 | /**
24 | * The language negotiation method id.
25 | */
26 | const METHOD_ID = 'language-anonymous';
27 |
28 | /**
29 | * {@inheritdoc}
30 | */
31 | public function getLangcode(Request $request = NULL) {
32 | if ($this->currentUser->isAnonymous()) {
33 | $langcode = 'en';
34 | return $langcode;
35 | }
36 | }
37 |
38 | }
39 | ```
--------------------------------------------------------------------------------
/Back-end/Rest.md:
--------------------------------------------------------------------------------
1 | REST
2 | ========
3 |
4 | #### Generación mediante la consola
5 | ```
6 | // Genera la clase que permite gestionar un servicio mediante los métodos GET, PUT, POST, DELETE, PATCH, HEAD, OPTIONS
7 | $ drupal generate:plugin:rest:resource
8 | Cuando pida 'Enter the plugin rest resource url' se puede poner /ruta/{parametros}
9 | ```
10 |
11 | ### Habilitar el recurso
12 | ```
13 | Instalar el módulo REST UI
14 | https://www.drupal.org/project/restui
15 |
16 | - Habilitar el recurso.
17 | /admin/config/services/rest
18 |
19 | - Activar privilegios para los roles indicados.
20 | /admin/people/permissions
21 | ```
22 |
23 | ### Acceder al recurso
24 | ```
25 | Por URL
26 | /dblog/1?_format=json
27 |
28 | Usando postman
29 |
30 | ```
31 |
32 | ### Ejemplo conexión uso rest post desde Python
33 | ```Python
34 | import requests
35 | import json
36 |
37 | user_drupal = "algun_usuario"
38 | pass_drupal = "alguna_clave"
39 | url_base = 'http://www.misitio.com'
40 |
41 | # Logueo en drupal. El logueo se debe realizar una sola vez, luego con esta sesión se debe realizar las operaciones.
42 | user_datas = {"name":user_drupal,"pass":pass_drupal}
43 | data_json = json.dumps(user_datas)
44 | response_login = requests.post(url_base + '/user/login?_format=json', data=data_json)
45 | data_result = json.loads(response_login.text)
46 | csrf_token = data_result['csrf_token']
47 |
48 | # Enviar un json para registro mediante post
49 | data = {
50 | "voucher":
51 | {
52 | "class":"normal",
53 | "date":1508891700,
54 | "gloss":"Asiento de prueba",
55 | "type":"INCOME",
56 | "entry_subtype":"PAYMENT",
57 | "state":"REGISTERED"
58 | }
59 | }
60 | data_json = json.dumps(data)
61 | header = {'Content-Type':'application/json','X-CSRF-Token':csrf_token}
62 |
63 | client = requests.session()
64 | client.headers.update(header)
65 | client.auth = (user_drupal,pass_drupal)
66 |
67 | response_post = client.post(url_base + '/url_al_servicio_post?_format=json', data=data_json)
68 | print (response_post.text)
69 | ```
70 |
71 | #### Referencias
72 | ```
73 | Ejmplo con GET y POST
74 | https://github.com/DrupalBolivia/RESTFul-web-services/blob/master/rest_example/src/Plugin/rest/resource/RestExampleResource.php
75 |
76 | Documentación
77 | https://www.drupal.org/docs/8/api/restful-web-services-api/restful-web-services-api-overview
78 | ```
79 |
80 |
--------------------------------------------------------------------------------
/Back-end/Restricciones.md:
--------------------------------------------------------------------------------
1 | Restricciones
2 | ===
3 |
4 | #### Referencias
5 | ```
6 | Documentación oficial.
7 | - https://www.drupal.org/docs/drupal-apis/entity-api/entity-validation-api/defining-constraints-validations-on-entities-andor-fields
8 | ```
9 |
--------------------------------------------------------------------------------
/Back-end/Rutas.md:
--------------------------------------------------------------------------------
1 | Rutas
2 | ========
3 | #### Obtener rutas del proyecto
4 | Obtener el host. Ej: drupal9.local
5 | ```php
6 | $host = \Drupal::request()->getHost();
7 | ```
8 |
9 | Obtener ruta base completa. Ej: https://drupal8.local
10 | ```php
11 | $base_uri = \Drupal::request()->getSchemeAndHttpHost();
12 | ```
13 |
14 | Obtener la ruta actual
15 | ```php
16 | $current_path = \Drupal::service('path.current')->getPath();
17 | ```
18 |
19 | #### Crear una ruta
20 | En el archivo miarchivo.routing.yml
21 | ```yml
22 | sale.onlyform.add:
23 | path: '/sales/sales-add'
24 | defaults:
25 | _form: '\Drupal\sales\Form\addsaleForm'
26 | _title: 'Sales'
27 | requirements:
28 | _permission: sale.onlyform.add
29 | ```
30 | En el archivo miarchivo.permission.yml
31 | ```yml
32 | sale.onlyform.add:
33 | title: 'Add Sale'
34 | description: 'Add Sale'
35 | restrict access: true
36 | ```
37 | #### Crear urls
38 | ```php
39 | use Drupal\Core\Url;
40 | $Url = new Url($route_name, $params);
41 |
42 | // O mediante el método estático de la url
43 | $url = Url::fromRoute($route_name, $params)
44 | // Ejemplo
45 | $url = Url::fromRoute('view.glossary_terms.glossary_page', ['arg_0' => 'all'])->toString();
46 | ```
47 | #### Obtener una url
48 | ```php
49 | // Obtener la ruta actual
50 | $currentRoute = \Drupal::routeMatch();
51 |
52 | // o usando como base el nombre de la ruta
53 | $path = Url::fromRoute($route_name);
54 |
55 | // Sin una ruta como base
56 | use Drupal\Core\Url;
57 | $Url = Url::fromUri('internal:/mypath/to/style.css');
58 | ```
59 |
60 | #### Obtener nombre routing de la ruta actual
61 | ```php
62 | $url_object = \Drupal::service('path.validator')->getUrlIfValid(\Drupal::service('path.current')->getPath());
63 | $route_name = $url_object->getRouteName();
64 | ```
65 |
66 | #### Parametros
67 | ```php
68 | // Obtener un parametro
69 | $currentRoute = \Drupal::routeMatch();
70 | $query = $currentRoute->getParameter('nombre_parametro');
71 |
72 | // Vs
73 |
74 | $query = \Drupal::request()->query->get('name');
75 | ```
76 |
77 | #### Redireccionamiento
78 | ```php
79 | use Symfony\Component\HttpFoundation\RedirectResponse;
80 |
81 | $response = new RedirectResponse("quotation?id=" . $idQuotationClient);
82 | $response->send();
83 |
84 | $path = Url::fromRoute('mi_nombre_ruta')->toString();
85 | $response = new RedirectResponse($path);
86 | $response->send();
87 |
88 | // Para rutas externas usar TrustedRedirectResponse
89 | ```
90 |
91 | ### route_name de vistas
92 | ```
93 | view.VIEW_MACHINE_NAME.PAGE_MACHINENAME
94 | view.$view_id.$display_id"
95 | ```
96 |
97 |
98 | #### Referencias
99 | - Posibilidades de las rutas:
100 | https://www.drupal.org/node/2092643
101 |
102 | - Cheatsheet
103 | https://cryptic.zone/blog/drupal-8-cheatsheet-developers
104 |
105 | - Redireccionamiento
106 | https://x-team.com/blog/drupal-goto/
107 |
108 | - Links, URLs, URIs
109 | https://www.hashbangcode.com/article/drupal-9-programmatically-creating-and-using-urls-and-links
110 |
--------------------------------------------------------------------------------
/Back-end/Schemas.md:
--------------------------------------------------------------------------------
1 | Schemas
2 | ========
3 |
4 | #### Debug con drush
5 | Ver todas las incidencias
6 | ```
7 | $ drush config:inspect
8 | ```
9 |
10 | Ver detalle de una configuración
11 | ```
12 | $ drush config:inspect --detail page_manager.page_variant.site_template-default
13 | ```
14 |
15 | #### Reparar el mapping
16 | ```
17 | function mi_modulo_config_schema_info_alter(&$definitions) {
18 | // @todo: Remove once https://www.drupal.org/project/menu_multilingual/issues/2956990 is fixed.
19 | if (isset($definitions['block.settings.system_menu_block:*.third_party.menu_multilingual']['mapping']) && isset($definitions['block.settings.system_menu_block:*']['mapping'])) {
20 | $definitions['block.settings.system_menu_block:*']['mapping'] = array_merge($definitions['block.settings.system_menu_block:*']['mapping'], $definitions['block.settings.system_menu_block:*.third_party.menu_multilingual']['mapping']);
21 | }
22 | }
23 | ```
24 |
25 | ENLACES Y FUENTES
26 | =================
27 | Documentación oficial
28 | https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-schemametadata
29 |
30 |
--------------------------------------------------------------------------------
/Back-end/Servicios.md:
--------------------------------------------------------------------------------
1 | SERVICIOS
2 | ========
3 |
4 | #### Acceder a un servicio
5 | ```php
6 | // Listar todos los servicios disponibles.
7 | \Drupal::getContainer()->getServiceIds()
8 |
9 | $my_service = \Drupal::service('my_service_name');
10 |
11 | // Dentro un controlador se puede acceder mediante su contenedor
12 | class MyController extends ControllerBase {
13 | public function myMethod() {
14 | $container = $this->container();
15 | $my_service = $container->get('my_service_name');
16 | }
17 | }
18 |
19 | // Llamando a los métodos estáticos de la clase Drupal para acceder a algunos servicios
20 | \Drupal::entityManager();
21 | \Drupal::database();
22 | \Drupal::urlGenerator();
23 | \Drupal::translation();
24 | ```
25 | #### Inyectar servicios
26 | ```
27 | // en desarrollo
28 | ```
29 |
30 | CREAR SERVICIOS
31 | ===
32 |
33 | #### Ruta
34 | En services.yml
35 | ```
36 | services:
37 | mymodule.myservice:
38 | class: Drupal\my_module\MyService
39 | arguments: ['@entity.query']
40 | ```
41 | #### Clase
42 | En services.yml
43 | ```
44 | class MyService {
45 | protected $entityQuery;
46 |
47 | public function __construct(QueryFactory $entity_query) {
48 | $this->entityQuery = $entity_query;
49 | }
50 | }
51 | ```
52 |
53 | INYECTAR SERVICIOS
54 | ===
55 | ```php
56 | use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
57 | use Symfony\Component\DependencyInjection\ContainerInterface;
58 | use Drupal\Core\Entity\Query\QueryFactory;
59 |
60 | class MyController extends ControllerBase implements ContainerInjectionInterface {
61 | protected $entityQuery;
62 |
63 | /**
64 | * Constructor. Stores injected services.
65 | */
66 | public function __construct(QueryFactory $entity_query) {
67 | $this->entityQuery = $entity_query;
68 | }
69 |
70 | /**
71 | * {@inheritdoc}
72 | */
73 | public static function create(ContainerInterface $container) {
74 | return new static(
75 | $container->get('entity.query')
76 | );
77 | }
78 | }
79 | ```
80 |
81 | #### Referencias
82 | Cheatsheet
83 | - https://cryptic.zone/blog/drupal-8-cheatsheet-developers
84 |
85 | Sobrescribir servicios
86 | - https://www.bounteous.com/insights/2017/04/19/drupal-how-override-core-drupal-8-service/
87 |
--------------------------------------------------------------------------------
/Back-end/Sesiones:
--------------------------------------------------------------------------------
1 | Sesiones
2 | ========
3 | #### Privadas
4 | ```
5 | ...
6 | ```
7 |
8 | #### Compartidas
9 | ```
10 | ...
11 | ```
12 |
13 | ENLACES Y FUENTES
14 | =================
15 | Buen resumen:
16 | https://atendesigngroup.com/blog/storing-session-data-drupal-8
17 |
--------------------------------------------------------------------------------
/Back-end/Sqlite.md:
--------------------------------------------------------------------------------
1 | Sqlite
2 | ========
3 |
4 | Comandos
5 | ```
6 | // Acceder a la consila
7 | $ sqlite3
8 | $ drush sql:cli
9 |
10 | // Ayuda
11 | $ .help
12 |
13 | // Ver bases de datos
14 | $ .databases
15 | $ .dbinfo
16 |
17 | // Salir
18 | $ .exit
19 | ```
--------------------------------------------------------------------------------
/Back-end/Taxonomias.md:
--------------------------------------------------------------------------------
1 | Taxonomías
2 | ========
3 |
4 | #### Trozos de código para obtener programaticamente.
5 | Optener el id de vocuabulario de un término
6 | ```php
7 | $vocabulary_id = $term->bundle();
8 | ```
9 |
10 | Obtener el arbol de términos de una taxonomía.
11 | ```php
12 | $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree(
13 | 'id_vocabulario',
14 | 0, // id del termino padre(tid). "0" para obterner todos.
15 | 1, // Nivel del término. "1" Es es el primer nivel
16 | TRUE // Obtener la entidad del termino entera o un Stdclass.
17 | );
18 | ```
19 |
20 | Obtener todos los terminos padre de un término.
21 | ```php
22 | $ancestors = \Drupal::service('entity_type.manager')->getStorage("taxonomy_term")->loadAllParents($tid);
23 | $list = [];
24 | foreach ($ancestors as $term) {
25 | $list[$term->id()] = $term->label();
26 | }
27 | ```
28 |
29 | Obtener el padre directo de un término.
30 | ```php
31 | $parent = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadParents($termId);
32 | $parentEntity = reset($parent);
33 | $parent_term_id = array_key_first($parent)
34 | ```
35 |
36 |
37 | ENLACES Y FUENTES
38 | =================
39 | Términos y niveles.
40 | - https://boylesoftware.com/blog/drupal-8-get-taxonomy-terms-level/
41 |
--------------------------------------------------------------------------------
/Back-end/TempStorage.md:
--------------------------------------------------------------------------------
1 | TempStorage
2 | ========
3 |
4 | #### Manejo
5 |
6 | ```php
7 |
8 | // Para poner valores en tempstorage
9 | $tempstore = \Drupal::service('tempstore.private');
10 | $store = $tempstore->get('nombre_de_colección');
11 | $store->set('key_name', $value);
12 |
13 | // Para recuperar los valores en tempstorage
14 | $tempstore = \Drupal::service('tempstore.private');
15 | $store = $tempstore->get('nombre_de_colección');
16 | $value = $store->get('key_name');
17 |
18 | // Eliminar dato. De todas maneras el dato será removido en una semana.
19 | $store->delete('key_name');
20 | ```
21 |
--------------------------------------------------------------------------------
/Back-end/Testeo.md:
--------------------------------------------------------------------------------
1 | TESTEO
2 | ========
3 |
4 | ####
5 |
6 |
7 | ENLACES Y FUENTES
8 | =================
9 |
10 | Test funcional
11 | - https://glamanate.com/blog/do-you-need-functional-test?utm_source=drupal-newsletter&utm_medium=email&utm_campaign=drupal-newsletter-20200910
--------------------------------------------------------------------------------
/Back-end/Tokens.md:
--------------------------------------------------------------------------------
1 | Tokens
2 | ========
3 |
4 | #### Crear nuevos tokens
5 | En el archivo mi_modulo.tokens.inc
6 | ```php
7 | /**
8 | * @file
9 | * Contains functions related to tokens for Siblu.
10 | */
11 |
12 | use Drupal\Core\Render\BubbleableMetadata;
13 |
14 | /**
15 | * Implements hook_token_info().
16 | */
17 | function mi_modulo_token_info() {
18 | $types['mi_modulo_product'] = [
19 | 'name' => t('Product'),
20 | 'description' => t('Tokens related to current product.'),
21 | ];
22 |
23 | $product = [
24 | 'manager' => [
25 | 'name' => t('Commerce product manager'),
26 | ],
27 | 'phone_number' => [
28 | 'name' => t('Commerce product manager phone number'),
29 | ],
30 | ];
31 |
32 | return [
33 | 'types' => $types,
34 | 'tokens' => [
35 | 'siblu_product' => $product,
36 | ],
37 | ];
38 | }
39 |
40 | /**
41 | * Implements hook_tokens().
42 | */
43 | function mi_modulo_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
44 | $replacements = [];
45 |
46 | if ($type == 'mi_modulo_product') {
47 | $product = \Drupal::request()->attributes->get('commerce_product');
48 | if (empty($product)) {
49 | return $replacements;
50 | }
51 | foreach ($tokens as $name => $original) {
52 | switch ($name) {
53 | case 'manager':
54 | case 'phone_number':
55 | if (!$product->{$name}->isEmpty()) {
56 | $replacements[$original] = $product->{$name}->value;
57 | }
58 | break;
59 |
60 | }
61 | }
62 | }
63 |
64 | return $replacements;
65 |
66 | }
67 |
68 |
69 | ```
70 |
71 |
--------------------------------------------------------------------------------
/Back-end/Usuarios.md:
--------------------------------------------------------------------------------
1 | Usuarios
2 | ========
3 | #### Usuario actual
4 | ```php
5 | // Obtener usuario actual
6 | $user = \Drupal::currentUser();
7 | // Verificar si el usuario tiene un permiso
8 | \Drupal::currentUser()->hasPermission("id_del_permiso")
9 |
10 | // Verificar si un usuario tiene un rol
11 | $current_user = \Drupal::currentUser();
12 | $user = User::load($current_user->id());
13 | $has_role = $user->hasRole('contributor');
14 | ```
15 |
16 | ### Usuario esta logueado
17 | ```php
18 | // Usuario actual está autentitcado
19 | $logged_in = \Drupal::currentUser()->isAuthenticated();
20 |
21 | // Usuario actual es anónimo
22 | \Drupal::currentUser()->isAnonymous();
23 | ```
24 |
25 | #### Crear usuarios
26 | ```php
27 | $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
28 | $user = \Drupal\user\Entity\User::create();
29 |
30 | // Configuraciones de campos clave
31 | $user->setPassword('clave');
32 | $user->enforceIsNew();
33 | $user->setEmail('email');
34 | $user->setUsername('nombre_usuario');
35 |
36 | // Configuraciones opcionales
37 | $user->set("init", 'email');
38 | $user->set("langcode", $language);
39 | $user->set("preferred_langcode", $language);
40 | $user->set("preferred_admin_langcode", $language);
41 |
42 | $user->activate();
43 |
44 | //Guardar usuario
45 | $res = $user->save();
46 | ```
47 |
48 | #### Loguear usuario
49 | ```php
50 | $account = user_load_by_name('nombre_usuario');
51 | user_user_login($account);
52 | user_login_finalize($account);
53 | ```
54 |
55 | #### Desloguear usuario
56 | ```php
57 | user_logout();
58 | ```
59 |
60 | #### Recuperar todos los usuarios y hacer consultas
61 | ```php
62 | $idsUsers = \Drupal::entityQuery('user')->execute();
63 | $users = User::loadMultiple($idsUsers);
64 | foreach ($users as $user) {
65 | foreach ($user->get("roles") as $rol) {
66 | if ($rol->getValue()['target_id'] == "client_manager") {
67 | ...
68 | }
69 | }
70 | }
71 | ```
72 |
73 | #### Recuperar un usuario
74 | ```php
75 | $user = User::load($idUser);
76 |
77 | ```
78 |
79 | #### Cerrar sesión de un usuario
80 | ```php
81 | user_login_finalize($user);
82 | ```
83 |
84 | #### Asignar privilegios a un rol
85 | ```php
86 | $role = \Drupal\user\Entity\Role::load('authenticated');
87 | $role->grantPermission('access comments');
88 | $role->save();
89 | ```
90 |
91 | #### Validar la contraseña de un usuario
92 | ```php
93 | $password = 'clave a validar';
94 | $database = \Drupal::database();
95 | $query = $database->query("SELECT pass FROM {users_field_data} WHERE uid = :uid;", [':uid' => $user->id()]);
96 | $current_password = $query->fetchAssoc()['pass'];
97 | $pass = $this->passwordHasher->check($password, $current_password);
98 | $result = 'failure';
99 | if ($pass) {
100 | $result = 'success';
101 | }
102 | ```
103 |
104 |
105 | ENLACES Y FUENTES
106 | =================
107 | Módulo User
108 | https://api.drupal.org/api/drupal/core!modules!user!user.module/8
109 |
110 | User.php
111 | https://api.drupal.org/api/drupal/core!modules!user!src!Entity!User.php/class/User/8
112 |
113 | Roles de usuario
114 | https://api.drupal.org/api/drupal/core!core.api.php/group/user_api/8
115 |
--------------------------------------------------------------------------------
/Back-end/Variables.md:
--------------------------------------------------------------------------------
1 | Variables
2 | ===
3 |
4 | #### Variables de estado
5 | ```php
6 | // Obtener un valor
7 | $value = \Drupal::state()->get('name_variable');
8 |
9 | // Obtener un valor con valor por defecto en caso e no encontrar un valor.
10 | $value = \Drupal::state()->get('name_variable', valor_por_defecto);
11 |
12 | // Colocar un valor
13 | \Drupal::state()->set('name_variable', valor_variable);
14 | ```
15 |
16 |
--------------------------------------------------------------------------------
/Back-end/Vistas.md:
--------------------------------------------------------------------------------
1 | Vistas
2 | ===
3 |
4 | Recuperar una vista la configuración de un display
5 | ```php
6 | use Drupal\views\Views;
7 |
8 | $view = Views::getView('gestion_des_formulaires');
9 | $view->setDisplay('page_2');
10 | $display = $view->getDisplay();
11 |
12 | if (isset($display->options['filter_groups']['operator'])) {
13 | $operator = $display->options['filter_groups']['operator'];
14 | $filter_operators = $display->options['filter_groups']['groups'];
15 | foreach ($display->options['filters'] as $filter) {
16 | if ($filter['exposed']) {
17 | //...
18 | }
19 | }
20 | }
21 | ```
22 |
23 | #### Filtros
24 | Crear un filtro expuesto mediante plugins
25 | - https://www.axelerant.com/resources/team-blog/creating-a-custom-exposed-view-filter-in-drupal-8-to-use-with-workflow-states
26 | Agregar - customizar elementos del formulario del plugin.
27 | - https://www.drupal.org/project/drupal/issues/2852299
28 |
29 | Crear un filtro expuesto mediante hooks
30 | - http://www.ermohitbansal.com/2019/08/31/how-we-can-create-custom-exposed-filter-in-views-and-fetch-results-accordingly-in-drupal-8/
31 |
32 | Modificar filtro expuesto ajax mediante hook_form_alter + javascript
33 | - https://leanderlindahl.se/filter-content-in-a-drupal-8-view-with-ajax/
34 | - http://www.softdecoder.com/blog/dynamically-filter-content-drupal-view
35 |
36 | #### Obtener datos
37 | Obtener los datos de una vista programaticamente
38 | - https://jbloomfield.codes/2018/09/24/drupal-8-getting-data-from-viewfield.html
39 |
40 | #### Manipular view
41 | Ejecutar una vista programaticamente
42 | - https://www.trivali.be/blog/drupal-8-execute-a-view-programmaticaly
43 |
44 | Customizar crear propio paginador
45 | - http://djevans.info/article/creating-views-pager-plugins-drupal-8
46 | - https://blog.werk21.de/en/2017/04/21/programmatically-change-views-pager-type-or-options
47 |
48 | Ejemplos de los principales hooks
49 | - https://drupalium.com/articles/insert-replace-delete-rows-from-view-results
--------------------------------------------------------------------------------
/Back-end/Webform.md:
--------------------------------------------------------------------------------
1 | WEBFORM
2 | ========
3 |
4 |
5 | ####
6 | Consultas
7 | ```php
8 | $submission_storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
9 | $ids_ws = $submission_storage->getQuery()
10 | ->accessCheck(FALSE)
11 | ->condition('uuid', $submission_uuid)
12 | ->execute();
13 | if (count($ids_ws) == 1) {
14 | $id_ws = reset($ids_ws);
15 | $webform_submission = $submission_storage->load($id_ws);
16 | $webform_submission_data = $webform_submission->getData();
17 |
18 | if ($webform_submission_data['numero_de_socio'] == $codigo_de_socio) {
19 | $email = $webform_submission_data['correo_electronico'];
20 | $whatsapp_number = $webform_submission_data['numero_celular_con_whatsapp'];
21 | $status = TRUE;
22 | }
23 | else {
24 | $status = FALSE;
25 | }
26 | }
27 |
28 | $select = \Drupal::service('database')
29 | ->select('webform_submission_data', 'wsd')
30 | ->fields('wsd', array('sid'))
31 | ->orderBy('wsd.sid', 'DESC')
32 | ->condition('wsd.webform_id', 'id_formulario', '=')
33 | ->condition('wsd.name', 'nombre_sistema_del_campo', '=')
34 | ->condition('wsd.value', $some_value, '=')
35 | ->execute();
36 | $results = $select->fetchAll(\PDO::FETCH_COLUMN);
37 |
38 | ```
39 |
40 | Actualización.
41 | ```php
42 | $submission_storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
43 | $ids = $submission_storage->getQuery()
44 | ->accessCheck(FALSE)
45 | ->condition('webform_id', 'id_del_webform')
46 | ->execute();
47 | if (count($ids) > 0) {
48 | foreach ($ids as $id) {
49 | $submission = $submission_storage->load($id);
50 | $data = $submission->getData();
51 | // Remove unused wich_session.
52 | if ($data['wich_formation'] != 'Bootcamp Ma Collection' && !empty($data['wich_session'])) {
53 | $submission->setElementData('wich_session', '');
54 | $submission->save();
55 | }
56 | }
57 | }
58 | ```
59 |
60 | ENLACES Y FUENTES
61 | =================
62 |
63 | Crear y actualizar envios de webform
64 | - https://www.drupal.org/docs/8/modules/webform/webform-cookbook/how-to-programmatically-create-and-update-a-submission
--------------------------------------------------------------------------------
/Contribucion/README.md:
--------------------------------------------------------------------------------
1 | CONTRIBUIR
2 | =================
3 |
4 | #### Parches que necesitan ser actualizados "Reroll"
5 | https://bit.ly/2QoEMyU
6 |
7 | #### Partes del código que se necesitan remplazar-deprecar "Kill includes"
8 | https://bit.ly/2Eiq8SL
9 |
10 | #### Herramientas útiles
11 | Para revizar que el código cumple los standares
12 |
13 | PHPlint https://www.drupal.org/node/2571965
14 |
15 | CSS lint https://www.drupal.org/node/1190252
16 |
17 | Coding standards https://www.drupal.org/node/1886770
18 |
19 | JS lint https://www.drupal.org/node/2490140
20 |
21 | Doc page https://www.drupal.org/node/1955232
22 |
23 | Buscar código en todos los proyectos contribuidos http://grep.xnddx.ru/
24 |
25 | #### Referencias
26 | Cómo realizar re-roll
27 | https://www.drupal.org/patch/reroll
28 |
29 | Documentación etiquetas que pueden tener las issues
30 | https://www.drupal.org/issue-tags
31 |
--------------------------------------------------------------------------------
/Contribucion/contribuir-modulo.md:
--------------------------------------------------------------------------------
1 | Crear un módulo y contribuirlo
2 | ========
3 |
4 | Crear el proyecto en drupal.org
5 | 1. Ir a https://www.drupal.org/project/user
6 | 2. Crear en el link "Add a new project"
7 |
8 | Subir el código al repositorio oficial de drupal
9 | ```bash
10 | mkdir total_visitor_counter
11 | cd total_visitor_counter
12 | git init
13 | git checkout -b 1.0.x
14 | echo "Total visitor counter" > README.txt
15 | git add README.txt
16 | git commit -m "Initial commit."
17 | git remote add origin git@git.drupal.org:project/total_visitor_counter.git
18 | git push origin 1.0.x
19 | ```
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Contribucion/corregir-parche.md:
--------------------------------------------------------------------------------
1 | Resolver problemas en un parche
2 | ========
3 | ```
4 | Se trata de resolver problemas de testeo, problemas detectados y/o comentados.
5 | ```
6 |
7 |
8 | #### Pasos previos
9 | ```
10 | 1. Identificar una issue con la estado "Needs work"
11 | https://www.drupal.org/project/issues/search/drupal?status%5B%5D=13&version%5B%5D=8.x
12 |
13 | 2. Encontrar una issue en la que se sienta capaz que se puede resolver los problemas en el parche subido.
14 |
15 | 3. Actualizar el core
16 | $ git checkout 8.7.x
17 | $ git pull --rebase
18 |
19 | 4. Descargar el parche en el comentario más reciente
20 | ```
21 |
22 | #### Resolver los problemas
23 | ```
24 | 1. Ir a la issue y copiar la fecha en el comentario del parche descargado
25 |
26 | 2. Ver el log de commits de esa fecha
27 | $ git log --before="12 November 2018 at 12:15"
28 |
29 | 3. Tomar los primeros 9 caracteres del código del primer commit e ir a este
30 | $ git checkout -b test-branch 749f569c6
31 |
32 | 4. Aplicar el parche
33 | $ git apply --index 2599228-93.patch
34 |
35 | 5. Commit del parche
36 | $ git commit -m "Applying patch from issue 2599228 comment 12852422"
37 |
38 | 6. Intenta hace pull de todos los cambios que han sido hechos desde el commit del parche.
39 | $ git rebase 8.7.x
40 |
41 | Si hay conflictos: Realizar los conflictos del rebase.
42 | https://www.drupal.org/node/2723783
43 |
44 | Si no hay conflictos
45 | - RESOLVER LOS PROBLEMAS EN EL PARCHE
46 | $ git add -p
47 | $ git commit -m "Solving problem at patch from issue 2599228 comment 12852422"
48 | - Crear un parche con un diff de tu branch local (test-branch) sobre la rama principal:
49 | $ git diff -M 8.7.x test-branch > numero_issue-numero_comentario.patch
50 | Verificar si el parche creado es correcto
51 | $ git checkout 8.7.x
52 | $ git apply --check numero_issue-numero_comentario.patch
53 | (no output)
54 | Crear un interdiff
55 | $ interdiff viejo.patch nuevo.patch > interdiff_[numero_comentario_viejo]-[numero_comentario_nuevo].txt
56 | ```
57 | #### Referencias
58 | ```
59 | Interdiff
60 | https://www.drupal.org/documentation/git/interdiff
61 | ```
62 |
--------------------------------------------------------------------------------
/Contribucion/crear-un-parche.md:
--------------------------------------------------------------------------------
1 | Crear un parche
2 | ========
3 | ```
4 | Se trata de resolver problemas en una issue de drupal y crear un parche.
5 | ```
6 |
7 | ```
8 | Clonar el repositorio del proyecto con la issue:
9 | De https://www.drupal.org/project/lightning_workflow/git-instructions copiar:
10 | $ git clone --branch 8.x-3.x https://git.drupalcode.org/project/lightning_workflow.git
11 | $ cd lightning_workflow
12 | $ git checkout -b nombre_rama_nueva
13 |
14 | Modificar el código del módulo resolviendo el issue en cuestión.
15 | ...
16 |
17 | Crear el parche con la sulución:
18 | $ git add -p
19 | $ git commit -m "...."
20 | $ git diff -M 8.x-3.x nombre_rama_nueva > numero_issue-numero_comentario.patch
21 |
22 | Verificar si el parche creado es correcto
23 | $ git checkout 8.x-3.x
24 | $ git apply --check numero_issue-numero_comentario.patch
25 | (no output)
26 |
27 | Aplicar el parche para verificar el correcto funcionamiento
28 | $ git checkout 8.x-3.x
29 | $ git apply --index numero_issue-numero_comentario.patch
30 |
--------------------------------------------------------------------------------
/Contribucion/entorno.md:
--------------------------------------------------------------------------------
1 | Entorno
2 | ========
3 | #### Docker con mysql, apache, tests unitarios en DOCKSAL
4 | ```
5 | Para drupal 8
6 | https://github.com/docksal/drupal8-contrib
7 |
8 | Clonar el repositorio
9 | $ git clone git@github.com:docksal/drupal8-contrib.git drupal8
10 |
11 | Para drupal 9
12 | https://github.com/docksal/drupal9-contrib
13 | Clonar el repositorio
14 | $ git clone git@github.com:docksal/drupal9-contrib.git
15 |
16 |
17 | Levantar el entorno
18 | $ cd >carpeta>
19 | $ fin init
20 |
21 | Ejecutar tests unitarios
22 | $ fin bash
23 | $ cd docroot
24 | $ vendor/bin/phpunit -c core modules/contrib/domain/domain/tests/src/Functional/Views/ActiveDomainDefaultArgumentTest.php
25 |
26 | ```
27 |
28 | #### Docker con sqlite + correr tests unitarios
29 | ```
30 | Descargar el core de drupal
31 | https://www.drupal.org/project/drupal/git-instructions
32 |
33 | Descargar Makefile para correr un docker de drupal sobre sqlite
34 | https://gist.github.com/andypost/f8e359f2e80cb7d4737350189f009646#file-makefile
35 |
36 | Ejecutar composer
37 | $ composer install
38 |
39 | Ejecutar ambiente docker
40 | $ make -s up
41 | Revisar en: http://localhost:8080/
42 |
43 | Ejecutar los tests de un módulo. Ejemplo Taxonomy
44 | $ make t t=core/modules/taxonomy/tests/src/Unit/Menu/TaxonomyLocalTasksTest.php
45 | ```
46 | #### Entorno local + correr tests unitarios + verificación estándares del código
47 | ```
48 | Descargar el core de drupal y colocar en una carpeta local que levante un host normal como sueles hacerlo en tu entorno.
49 | https://www.drupal.org/project/drupal/git-instructions
50 |
51 | Entrar en la carpeta de drupa y ejecutar composer
52 | $ composer install
53 |
54 | Instalar drupal (puede ser desde el navegador)
55 |
56 | ENTORNO PARA TESTGS UNITARIOS
57 | Activar entorno para ejecutar tests unitarios
58 | $ mkdir sites/default/simpletest
59 | $ chmod 777 -R sites/default/simpletest
60 | $ cp core/phpunit.xml.dist core/phpunit.xml
61 |
62 | Configurar el archivo phpunit.xml modificando las variables de entorno
63 |
64 |
65 |
66 | Ejecutar los tests: Ejemplo
67 | vendor/bin/phpunit --configuration core core/tests/Drupal/KernelTests/Core/Bootstrap/GetFilenameTest.php
68 |
69 | ENTORNO PARA VERIFICACIÓN DE ESTÁNDARES DEL CÓDIGO
70 | $ composer global require drupal/coder
71 | $ set PATH $PATH $HOME/.config/composer/vendor/bin
72 | $ phpcs --config-set installed_paths ~/.config/composer/vendor/drupal/coder/coder_sniffer
73 | $ phpcs -i
74 | Debe mostrar "The installed coding standards are Zend, PSR12, PSR1, Squiz, PSR2, MySource, PEAR, DrupalPractice and Drupal"
75 | $ phpcs --standard=Drupal /ruta_a_carpeta_o_archivo/
76 | ```
77 | ENLACES Y FUENTES
78 | =================
79 | Ejecutar tests unitarios
80 | - https://www.drupal.org/docs/8/phpunit/running-phpunit-tests
81 |
82 | Estándares del código
83 | - https://www.drupal.org/node/1419988
84 |
85 | Trabajar con git y gitlab
86 | - https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupal/creating-issue-forks-and-merge-requests?utm_source=Drupal+Project+Maintainers&utm_campaign=ed227e9b0b-EMAIL_CAMPAIGN_2020_09_10_08_14_COPY_03&utm_medium=email&utm_term=0_42888f3d61-ed227e9b0b-298566141
87 |
--------------------------------------------------------------------------------
/Contribucion/gitlab.md:
--------------------------------------------------------------------------------
1 | Contribuir gitlab
2 | ========
3 |
4 | - Ejemplo issue que contribuye mediante gitlab
5 | https://www.drupal.org/project/simple_popup_blocks/issues/3211543
6 |
7 | - Cómo cobtribuir mediante gitlab
8 | https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupal/creating-issue-forks-and-merge-requests
--------------------------------------------------------------------------------
/Contribucion/merge-request.md:
--------------------------------------------------------------------------------
1 | Merge Request (Gitlab)
2 | ========
3 |
4 | Guía en video:
5 |
6 | https://www.youtube.com/watch?v=NIWCXE-aM6Y&utm_source=Drupal+Project+Maintainers&utm_campaign=99c7712471-EMAIL_CAMPAIGN_2020_12_01_05_33&utm_medium=email&utm_term=0_42888f3d61-99c7712471-298566141
--------------------------------------------------------------------------------
/Contribucion/reroll.md:
--------------------------------------------------------------------------------
1 | Actualización de parches (Reroll)
2 | ========
3 |
4 | ```
5 | Se trata de actualizar soluciones que han quedado incompatibles con cambios recientes en el código.
6 | ```
7 |
8 | #### Pasos previos
9 | ```
10 | 1. Filtrar issues que tienen necesidad de Reroll. Escoger una.
11 | https://www.drupal.org/project/issues/search/drupal?issue_tags=Needs+reroll
12 |
13 | 2. Confirmar que el parche necesita reroll
14 |
15 | Actualizar el core
16 | $ git checkout 8.8.x
17 | $ git pull --rebase
18 |
19 | Descargar el parche
20 |
21 | Verficiar el parche
22 | $ git apply --check nombre-archivo.patch
23 | Si el resultado es vacio el parche no necesita ser actualizado.
24 | - Quitar el tag: "Needs reroll"
25 | - Dejar un comentario "I could apply the patch, so no reroll is needed."
26 | Si el resultado es que se necesita el reroll:
27 | Dejar un comentario avisando que se está empezando a hacer el reroll y asignarse la tarea mientras dure el trabajo.
28 | ```
29 |
30 | #### Actualización de parches (Reroll)
31 | ```
32 | 1. Ir a la issue y copiar la fecha en el comentario del parche descargado
33 |
34 | 2. Ver el log de commits de esa fecha
35 | $ git log --before="12 November 2018 at 12:15"
36 |
37 | 3. Tomar los primeros 9 caracteres del código del primer commit e ir a este
38 | $ git checkout -b test-branch 749f569c6
39 |
40 | 4. Aplicar el parche
41 | $ git apply --index 2599228-93.patch
42 |
43 | 5. Commit del parche
44 | $ git commit -m "Applying patch from issue 2599228 comment 12852422"
45 |
46 | 6. Intenta hace pull de todos los cambios que han sido hechos desde el commit del parche.
47 | $ git rebase 8.8.x
48 |
49 | Si hay conflictos: Resolver los conflictos del rebase.
50 | https://www.drupal.org/node/2723783
51 |
52 | Si no hay conflictoss
53 | - Crear un parche con un diff de tu branch local (test-branch) sobre la rama principal:
54 | $ git diff -M 8.7.x test-branch > breve_descripción-nro_caso-nro_comentario.patch
55 | Verificar si el parche creado es correcto
56 | $ git checkout 8.7.x
57 | $ git apply --check breve_descripción-nro_caso-nro_comentario.patch
58 | (no output)
59 | ```
60 |
61 | ENLACES Y FUENTES
62 | =================
63 | Reroll
64 | https://www.drupal.org/contributor-tasks/reroll
65 |
--------------------------------------------------------------------------------
/Contribucion/utilidades.md:
--------------------------------------------------------------------------------
1 | Utilidades para contribuir
2 | ========
3 |
4 | Buscar dentro del código de todos los proyectos contribuidos a drupal
5 | - http://grep.xnddx.ru/
6 |
--------------------------------------------------------------------------------
/DevOps/IDEs/Atom.md:
--------------------------------------------------------------------------------
1 | ATOM
2 | ===
3 | ```
4 | ¿Porque atomon?
5 | - ATOM presenta infinita libertad debido a que es un editor libre de codigo abierto.
6 | - Existen muchos paquetes disponibles que hacen que no se tenga nada que envidiar a editores como PHPStorm, Sublime, Eclipse.
7 | ```
8 | INSTALACIÓN
9 | ==
10 | ```
11 | $ curl -L https://packagecloud.io/AtomEditor/atom/gpgkey | sudo apt-key add -
12 | $ sudo sh -c 'echo "deb [arch=amd64] https://packagecloud.io/AtomEditor/atom/any/ any main" > /etc/apt/sources.list.d/atom.list'
13 | $ sudo apt-get update
14 | $ sudo apt-get install atom
15 | ```
16 |
17 | PAQUETES RECOMENDADOS
18 | ==
19 | ```
20 | Autocompletar código php que tiene dependencias composer
21 | atom-autocomplete-php
22 |
23 | Ir a la definición de una variable, clase o función
24 | goto-definition
25 |
26 | Hacer ctrl+click en un texto y te envia a su definición (ctrl+shift desde teclado)
27 | hyperclick
28 | js-hyperclick
29 | php-hyperclick
30 | ```
31 |
32 | REFERENCIAS
33 | ==
34 | ```
35 | https://atom.io
36 | ```
37 |
--------------------------------------------------------------------------------
/DevOps/IDEs/visualstudiocode.md:
--------------------------------------------------------------------------------
1 | VISUAL STUDIO CODE
2 | ===
3 | ```
4 | ¿Porque Visual Studio Code?
5 | Es ligero y presenta todas las funcionalidades que a un programador le ahorran tiempo y esfuerzo:
6 | - Autocompleta código: php, js, html, css
7 | - Reconoce el formato del código: php, js, html, css, twig, htaccess
8 | - Soporta snipets.
9 | - Marca el versionamiento del código git.
10 | - Con ctrl-click se dirige directamente al código que implementa una funcionalidad.
11 | - Cuando se escribe código autocompleta las librerías que lo contienen PHP-Drupal
12 | ```
13 |
14 | INSTALACIÓN
15 | ==
16 | ```
17 | Desgargar .deb de https://code.visualstudio.com/
18 | $ sudo dpkg -i code_1.26.1-1534444688_amd64.deb
19 | ```
20 |
21 | PAQUETES RECOMENDADOS
22 | ==
23 | ```
24 | PHP:
25 | PHP Intelephense: Autocompletar y refactorizar código (promete ser el más veloz y completo!)
26 | PHP debug: Debuguear con XDebug
27 |
28 | TWIG
29 | Twig Language: Sintaxis, snippets, autocompletado de twig y html
30 |
31 | HTML CSS
32 | Html Snipets: Autocompletado de código html incluido html 5
33 | Html Css Support: Autocompletado de clases, ids, archivos remotos.
34 |
35 | DRUPAL
36 | Drupal 8 Twig Snippets: Las funciones más comunes para enlazar drupal-twig
37 | Drupal 8 Snippets: Los hooks
38 | Drupal 8 Javascript Snippets: Las funciones más comunes para enlazar drupal-js
39 |
40 | GIT
41 | Git History: Ver el log, historial de un archivo, comparar ramas y commits
42 |
43 | JS
44 | (¿Que recomiendas?)
45 |
46 | DOCKER
47 | Docker (Microsoft): Sintaxis, comandos y tip (on hover) para archivos dockerfile y docker-compose
48 |
49 | ```
50 |
51 | REFERENCIAS
52 | ==
53 | ```
54 | Página oficial
55 | https://code.visualstudio.com/
56 |
57 | Utilización con Drupal
58 | https://www.drupal.org/docs/develop/development-tools/configuring-visual-studio-code
59 |
60 | Recomendaciónes para trabajar con php
61 | https://code.visualstudio.com/docs/languages/php
62 |
63 | ```
64 |
--------------------------------------------------------------------------------
/DevOps/Seguridad.md:
--------------------------------------------------------------------------------
1 | Seguridad
2 | ===
3 |
4 | ### Configuración de permisos
5 | ```
6 | Permisos
7 | sites -> 755
8 | sites/default -> 755
9 | sites/default/files -> 775
10 | sites/default/settings.php -> 444
11 | sites/default/services.yml -> 444
12 | ```
13 |
--------------------------------------------------------------------------------
/DevOps/composer.md:
--------------------------------------------------------------------------------
1 | COMPOSER
2 | ========
3 |
4 | #### Instalar Composer globalmente (pre-requisito)
5 | ```bash
6 | curl -sS https://getcomposer.org/installer | php
7 | sudo mv composer.phar /usr/local/bin/composer
8 | # Para fedora, aws EC2
9 | ln -s /usr/local/bin/composer /usr/bin/composer
10 |
11 | #Evitar el corte por tiempo de espera excesivo
12 | "config": {
13 | "process-timeout": 0,
14 | },
15 | ```
16 |
17 |
18 | ENLACES Y FUENTES
19 | =================
20 | Composer y drupal
21 | - https://www.amazeelabs.com/en/drupal-composer-recipes
22 |
23 | Buenas prácticas composer
24 | - https://www.lullabot.com/articles/drupal-8-composer-best-practices
25 |
26 | Template composer
27 | - https://github.com/drupal-composer/drupal-project
28 |
--------------------------------------------------------------------------------
/DevOps/docker.md:
--------------------------------------------------------------------------------
1 | DOCKER
2 | ========
3 | #### Instalar docker en ubuntu 18.04
4 | ```bash
5 | # Desinstalar versiones antiguas de docker
6 | $ sudo apt-get -y remove docker docker-engine docker.io
7 | $ sudo apt-get update
8 |
9 | # Instalar paquetes necesarios para la instalación
10 | $ sudo apt-get install -y apt-transport-https software-properties-common ca-certificates curl wget
11 |
12 | # Agregar clave GPG para el repositorio de Docker
13 | $ wget https://download.docker.com/linux/ubuntu/gpg
14 | $ sudo apt-key add gpg
15 | $ sudo apt-get update
16 |
17 | # Agregar el repositorio docker a las fuentes APT
18 | $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"
19 |
20 | # Actualizar la base de datos de paquetes
21 | $ sudo apt-get update
22 |
23 | # Asegurarse de que se va instalar docker del repositorio oficial y no del por defecto de ubuntu
24 | $ apt-cache policy docker-ce
25 | #Esto desplegará algo como esto:
26 | Output of apt-cache policy docker-ce
27 | docker-ce:
28 | Installed: (none)
29 | Candidate: 18.03.1~ce~3-0~ubuntu
30 | Version table:
31 | 18.03.1~ce~3-0~ubuntu 500
32 | 500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages
33 | Note que docker-ce no está instalado y toma como candidato una versión de repositorio oficial para Ubuntu 18.04 (bionic).
34 |
35 | # Instalar Docker
36 | $ sudo apt-get -y install docker-ce
37 |
38 | # Verificar la instalación de docker
39 | $ sudo systemctl status docker
40 |
41 | # Decirle al sistema que arranque siempre con docker
42 | $ sudo systemctl start docker
43 | $ sudo systemctl enable docker
44 |
45 | # Verificar que docker funciona correctamente
46 | $ sudo docker run hello-world
47 |
48 | # Opcional: Agregar usuario al grupo docker para evitar esribir sudo todo el tiempo
49 | $ sudo usermod -aG docker
50 | # Aplicar la membresía al grupo
51 | $ su -
52 | # Confirmar que el usuario se encuentra en el grupo de docker
53 | $ id -nG
54 |
55 | # Instalar docker-compose
56 | # Desactivar fish
57 | $ bash
58 | # Instalar
59 | $ sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
60 | $ sudo chmod +x /usr/local/bin/docker-compose
61 | #Revisar si se encuentra bien instalado
62 | $ docker-compose --version
63 | ```
64 |
65 |
66 | #### Instalar docker en ubuntu 16.04
67 | ```bash
68 | Crear una cuenta de usuario que no sea root, con privilegios de sudo
69 | $ adduser docker
70 | $ usermod -aG sudo docker
71 |
72 | Actualizar la base de datos de paquetes
73 | $ sudo apt-get update
74 |
75 | Agregar la clave GPG para el repositorio oficial de Docker al sistema
76 | $ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
77 |
78 | Agregar el repositorio Docker a fuentes APT
79 | $ sudo apt-add-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main'
80 |
81 | Actualizar la base de datos de paquetes
82 | $ sudo apt-get update
83 |
84 | Verificar que está a punto de instalar desde el repositorio de Docker en lugar del repositorio predeterminado de Ubuntu
85 | $ apt-cache policy docker-engine
86 |
87 | Instalar Docker
88 | $ sudo apt-get install -y docker-engine
89 |
90 | Comprobar que docker se está ejecutando
91 | $ sudo systemctl status docker
92 |
93 | Opcional: Agregar usuario al grupo docker para evitar esribir sudo todo el tiempo
94 | $ sudo usermod -aG docker
95 |
96 | Instalar Docker compose
97 | $ sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
98 | $ sudo chmod +x /usr/local/bin/docker-compose
99 | Verificar versión instalada
100 | $ docker-compose --version
101 |
102 | Instalar comando make
103 | $ sudo apt-get install make
104 | ```
105 |
106 | #### Montar drupal y ejecutarlo
107 | ```bash
108 | Bajar contenedor oficial de drupal ()
109 | $ docker pull drupal
110 |
111 | Ejecutar drupal con base de datos SQLite
112 | $ docker run --name some-drupal -p 8080:80 -d drupal
113 |
114 | Ver en el navegador esta instancia:
115 | http://localhost:8080
116 |
117 | ```
118 |
119 |
120 |
121 | ENLACES Y FUENTES
122 | =================
123 | Instalar docker en ubuntu 16.04
124 | https://www.digitalocean.com/community/tutorials/como-instalar-y-usar-docker-en-ubuntu-16-04-es
125 |
126 | Instalar docker en ubuntu 18.04
127 | https://www.itzgeek.com/how-tos/linux/ubuntu-how-tos/how-to-install-docker-on-ubuntu-18-04-lts-bionic-beaver.html
128 | https://linuxconfig.org/how-to-install-docker-on-ubuntu-18-04-bionic-beaver
129 |
130 | Contenedor oficial de drupal
131 | https://hub.docker.com/_/drupal/
132 |
133 | Comandos de docker
134 | https://docs.docker.com/engine/reference/commandline/docker/
135 |
136 | Entorno drupal con las herramientas más útiles
137 | https://cloud.wodby.com/stackhub/ada51e9b-2204-45ee-8e49-a4151912a168/overview
138 |
139 | Montar docker en windows wsl
140 | https://dev.to/felipecrs/simply-run-docker-on-wsl2-3o8
--------------------------------------------------------------------------------
/DevOps/drush.md:
--------------------------------------------------------------------------------
1 | DRUSH
2 | ========
3 |
4 | #### Instalar
5 | ```bash
6 | # Visitar https://github.com/drush-ops/drush/releases y descargar drush.phar (8.x recomendado).
7 |
8 | # Verificar archivo.
9 | php drush.phar core-status
10 |
11 | # Renombrar `drush` por `php drush.phar`. y mover archivo $PATH.
12 | chmod +x drush.phar
13 | sudo mv drush.phar /usr/local/bin/drush
14 |
15 | # Opcional. Habilita alias
16 | drush init
17 | ```
18 |
19 | #### Comandos más útiles
20 | ```bash
21 | # Ver log de errores
22 | drush watchdog-show
23 |
24 | # Actualizar un proyecto drupal: saca backup, actualiza el código y actualiza la base de datos
25 | drush up
26 |
27 | # Lista de módulos activos que no son del core.
28 | drush pm-list --type=Module --no-core --status=enabled
29 |
30 | # Cambiar la contraseña de un usuario
31 | drush user-password USERNAME --password="SOMEPASSWORD"
32 |
33 | # Reconstruir rutas
34 | drush ev '\Drupal::service("router.builder")->rebuild();'
35 |
36 | # loguear como admin
37 | drush uli --uri local.misitio.com
38 |
39 | # Ver todos los servicios
40 | drush devel-container-services
41 |
42 | # verificar una configuración activa
43 | drush cget nombre_configuracion
44 |
45 | # Manejar hook_update
46 | drush php-eval "echo drupal_get_installed_schema_version('siblu_field');"
47 | drush php-eval "echo drupal_set_installed_schema_version('siblu_field', '8004');"
48 | drush updb -y
49 |
50 | # Deploy
51 | drush deploy
52 |
53 | Drush deploy ejecuta:
54 | drush updatedb --no-cache-clear
55 | drush cache:rebuild
56 | drush config:import
57 | drush cache:rebuild
58 | drush deploy:hook
59 |
60 | # Search API
61 | drush search-api:rebuild-tracker && drush search-api:index
62 | drush crons
63 |
64 | ```
65 | # Comandos base de datos
66 | ```bash
67 | # actualizar base de datos
68 | drush updb -y
69 |
70 | # Entrar modo consola a la base de datos
71 | $ drush sql-cli
72 |
73 | # Sacar backup de la base de datos.
74 | $ drush sql-dump
75 | $ drush sql-dump > default.sql
76 |
77 | # importar contenido por defecto
78 | drush default-content:import-all
79 | ```
80 |
81 | # Comandos usuarios
82 | ```bash
83 | # Crear usuario
84 | drush user-create
85 |
86 | # Cambiar de clave usuario
87 | drush user-password
88 |
89 | # Agregar rol a usuario
90 | drush user-add-role
91 |
92 | # Bloquear un usuario
93 | drush user-block
94 |
95 | # Desbloquear un usuario
96 | drush user-unblock
97 |
98 | # Desloguear todos los usuarios
99 | drush sql-query 'TRUNCATE TABLE sessions;'
100 |
101 | # Desloguear un usuario en específico
102 | drush sql-query 'DELETE FROM sessions WHERE uid = 2;'
103 | ```
104 |
105 | # Comandos para manipular configuraciones
106 | ```bash
107 | # Editar configuración activa
108 | drush config-edit
109 |
110 | # importar configuraciones
111 | drush cim -y
112 |
113 | # exportar configuraciones
114 | drush cex
115 | ```
116 |
117 | # Comandos gestion del sitio
118 | ```bash
119 | # Sitio en modo mantenimiento
120 | drush state:set system.maintenance_mode 1 --input-format=integer
121 | drush state:set system.maintenance_mode 0 --input-format=integer
122 | ```
123 |
124 | #### REFERENCIAS
125 | ```
126 | Comandos más utilizados
127 | - https://orga.cat/posts/most-useful-drush-commands
128 |
129 | Instalar drush 8 (Drupal 8 + Drupal 7)
130 | - wget http://files.drush.org/drush.phar
131 |
132 | Comandos base de datos
133 | - https://drushcommands.com/drush-8x/sql/
134 | ```
135 |
--------------------------------------------------------------------------------
/DevOps/git.md:
--------------------------------------------------------------------------------
1 | GIT
2 | ===
3 | ```bash
4 | # Instalación en sistemas debian, ubuntu
5 | sudo apt-get install git
6 |
7 | # Configuración de usuario
8 | git config --global user.name usuario
9 | git config --global user.email usuario@correo.com
10 | git config --global core.editor emacs
11 | git config --list
12 |
13 | # Configuración estilo de fin de línea para linux-mac: Auto modifica CTRL (Windows) a LF (Unix)
14 | git config --global core.autocrlf input
15 |
16 | # Generar las llaves pública y privada
17 | ssh-keygen -t rsa -C usuario@correo.com
18 |
19 | # Ignorar archivos o carpetas para el versionamiento
20 | # 1. Crear un archivo .gitignore en la rais de la carpeta versionada
21 | # 2. Escribir en el archivo .gitignore los archivos y carpetas a ignorar. Por ejemplo
22 | # .idea/
23 | # .gitignore
24 |
25 | # Perder todos los cambios que no fueron commiteados
26 | git checkout -f
27 |
28 | # Crear una rama o branch nueva
29 | git branch crazy-experiment
30 | git checkout crazy-experiment
31 | #... codificar cambios ...
32 | git add -A
33 | git commit -m "message..."
34 | git push origin crazy-experiment
35 |
36 | # Agregar y Quitar archivos (Equivalente git add, git rm juntos)
37 | git add -u
38 |
39 | # Añadir porciones de cambios dentro de cada archivo al stage de cambios
40 | git add -p
41 |
42 | # Quitar archivos
43 | git rm
44 |
45 | # Cambiar de nombre una rama
46 | git branch -m
47 | # Si estas en la rama que deseas cambiar de nombre
48 | git branch -m
49 |
50 | # Deshacer cambios del pull mas reciente
51 | git reset --hard
52 |
53 | # Retrocedemos al último commit y perdemos todos los cambios hechos.
54 | git reset --hard HEAD~1
55 |
56 | # Retrocedemos a el último commit y no perdemos los cambiosn hechos; apareceran pendientes de hace commit
57 | git reset --soft HEAD~1
58 |
59 | # Cancelar commit (antes de hacer push)
60 | git reset --hard HEAD~1
61 |
62 | # Reponer archivo eliminado que no ha sido comiteado
63 | git checkout HEAD
64 |
65 | # Ver cambios de un commit
66 | git show
67 |
68 | # Visualizar una rama existente
69 | git checkout crazy-experiment
70 |
71 | # Ver el historial gráficamente
72 | git log --graph --full-history --all --pretty=format:"%h%x09%d%x20%s"
73 |
74 | # Ver el historial de un archivo
75 | git log /ruta/archivo
76 |
77 | # Ver el historial de un usuario
78 | git log --author="vacho"
79 |
80 | # Ver el historia de cada línea de codigo de un archivo
81 | git blame /ruta/archivo
82 |
83 | # Ver el historial de un trozo de código
84 | git log --all -p -STrozo_de_codigo
85 |
86 | # Mezclar una rama con el master
87 | git checkout master
88 | git merge crazy-experimient
89 |
90 | # Agregamos una rama delante del master
91 | git checkout master
92 | git rebase crazy-experimient
93 |
94 | # Eliminar un branch
95 | git branch -D crazy-experiment
96 | git push origin :crazy-experiment
97 |
98 | # Ver aportes de líneas a un archivo
99 | git blame /ruta/archivo
100 |
101 | # Ver cambios en un archivo
102 | git diff /ruta/archivo
103 |
104 | # Ver cambios entre 2 commits
105 | git diff --name-only SHA1 SHA2
106 |
107 | # Arreglar el último commit en lugar de un nuevo commit
108 | # editamos hola.py y main.py
109 | git add hola.py
110 | git commit
111 | # añadir los cambios de main.py en el último commit
112 | git add main.py
113 | git commit --amend --no-edit
114 |
115 | # Hacer merge de un específico commit de una rama en otra rama (donde se esta trábajando)
116 | git cherry-pick
117 |
118 | # Lista de los commits que tienen un texto
119 | git log --all --grep=''
120 |
121 | # Restaurar un archivo borrado que no ha sido commiteado
122 | # Restaura el estado del archivo en index
123 | git reset --
124 | # Salida del cambio hecho en el archivo en index
125 | git checkout --
126 |
127 | #Ignorar un archivo en el repositorio sin .gitignore
128 | git update-index --skip-worktree /sites/default/settings.php
129 |
130 | ```
131 |
132 | Trabajar como fork de un repositorio y actualizar
133 | ===
134 | ```bash
135 | # Mostrar repositorios remotos
136 | git remote -v
137 |
138 | # Eliminar repositorios
139 | git remote rm
140 |
141 | # Añadir repositorio remoto, llamarlo "upstream":
142 | git remote add upstream https://github.com/whoever/whatever.git
143 |
144 | # Añadir repositorio remoto, para usarlo en repo github
145 | git remote add origin git@github.com:usuario_github/nombre_mi_proyecto.git
146 |
147 | # Extraer todos los branchs
148 | git fetch upstream
149 |
150 | # Estar seguro de que se está en el branch master
151 | git checkout master
152 |
153 | # Reescribir todos los commits
154 | git rebase upstream/master
155 |
156 | # Juntar 2 o más commits en uno. N viene a ser el número de commits que deseas juntar.
157 | git rebase --interactive HEAD~N
158 | # Luego en la edición tienes que cambiar por en cada línea de commit que deseas juntar.
159 |
160 | ```
161 |
162 | Montar repositorio para trabajar en remoto
163 | ===
164 | ```bash
165 | # En la carpeta a versionar:
166 | git init
167 |
168 | # habilitamos la posibilidad de hacer push
169 | $ git config receive.denyCurrentBranch ignore
170 |
171 | # Git manejará los finales de línea linux-windows
172 | git config --global core.autocrlf true
173 | git config --global core.whitespace cr-at-eol
174 |
175 | git add .
176 | git commit -m "inicio"
177 | git checkout -f
178 |
179 | # Evitar hacer git checkout -f todo el tiempo
180 | cd .git/hooks
181 | vim post-receive
182 | # Colocar las siguientes 2 líneas
183 | #!/bin/sh
184 | GIT_WORK_TREE=../ git checkout -f
185 | chmod +x post-receive
186 |
187 | # Para clonar
188 | git clone ssh://nombre_cuenta@ip_servidor:puerto/ruta_a_la_carpeta
189 |
190 | ```
191 | Ignorar archivos de un repositorio
192 | ===
193 | ```bash
194 | # Crear un .gitignore con la ruta relativa a las carpetas o archivos a omitir
195 | git rm -r --cached .
196 | git add .
197 | git commit -m "reiciniamos git"
198 | ```
199 |
200 | Ver reportes gráficos del repositorio.
201 | ===
202 | ```bash
203 | # ver el historial de cambios de un archivo
204 | gitk nombre_archivo.extension
205 | ```
206 |
207 | Deshacer cambios como rebases.
208 | ===
209 | ```bash
210 | git reflog
211 | # Supongamos que el commit más viejo es HEAD@{5} en el log log:
212 | git reset --hard "HEAD@{5}"
213 | ```
214 | Juntar los 2 commits finales en uno mismo.
215 | ===
216 | ```bash
217 | # Si estas en el commit_1 y quieres mergear el commit_2" en el commit_1.
218 | git rebase -i HEAD~2
219 | # Lo cual muestra en el editor la lista de todos los commits para hacer rebase.
220 | # Veras 2 líneas que comienzan con "pick".
221 | # Cambiar la primera palabra de la segunda línea de "pick" a "squash".
222 | # Guardar el archivo.
223 | ```
224 |
225 | Revisar el log de commits.
226 | ===
227 | ```bash
228 | # ver el historial de cambios.
229 | git log
230 |
231 | # ver sólo los archivos modificados.
232 | git diff-tree --no-commit-id --name-only -r
233 |
234 | # Ver el detalle de los cambios en un archivo.
235 | git show
236 | ```
237 |
238 | Omitir archivo previamente agregado.
239 | ===
240 | ```bash
241 | echo debug.log >> .gitignore
242 | git rm --cached debug.log
243 | rm 'debug.log'
244 | git commit -m "Start ignoring debug.log"
245 | ```
246 |
247 | Editar .gitignore
248 | ===
249 | ```bash
250 | -- Hacer cambios en .gitignore
251 | git rm -r --cached .
252 | git add .
253 | git commit -m "..."
254 |
255 | ```
256 |
257 |
258 | REFERENCIAS
259 | ---
260 | Reponer archivos eliminados
261 | - https://www.git-tower.com/learn/git/faq/restoring-deleted-files
262 |
263 | - https://www.atlassian.com/git/tutorials/merging-vs-rebasing/conceptual-overview
264 |
265 | - http://www.codigogratis.com.ar/como-utilizar-git-con-hostgator/
266 |
267 | Fin de línea
268 | - https://stackoverflow.com/questions/5834014/lf-will-be-replaced-by-crlf-in-git-what-is-that-and-is-it-important
269 |
--------------------------------------------------------------------------------
/DevOps/lamp.md:
--------------------------------------------------------------------------------
1 | LAMP
2 | ===
3 | ```bash
4 | #UBUNTU 16.04 con php 7 y mysql 5.7.x
5 | # Instalar Apache/httpd
6 | sudo apt-get install apache2
7 | # Ver log de errores de apache
8 | vim /var/log/apache2/error.log
9 |
10 | # Instalar MariaDB o mysql
11 |
12 | # MariaDB
13 | sudo apt-get install wget software-properties-common dirmngr ca-certificates apt-transport-https -y
14 | sudo apt update
15 | sudo apt install mariadb-server mariadb-client
16 | sudo mysql_secure_installation
17 | # Mysql
18 | sudo apt-get install mysql-server mysql-client
19 | sudo mysql_secure_installation
20 |
21 | # Habilitar que el usuario root puede loguearse por consola y web
22 | sudo mysql -u root
23 | ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'mi_clave';
24 |
25 | # PHP multiversion
26 | sudo apt -y install software-properties-common
27 | sudo add-apt-repository -y ppa:ondrej/php
28 | sudo apt update
29 | sudo apt install php7.4
30 | sudo apt install php8.1
31 | sudo apt-get install php-cli
32 | sudo apt-get install libapache2-mod-php
33 |
34 | # Buscar paquetes php a instalar
35 | sudo apt-cache search php
36 |
37 | # Paquetes útiles php
38 | sudo apt-get install php-mysql
39 | sudo apt-get install php-gd
40 | sudo apt-get install php-curl
41 | sudo apt-get install php-cgi
42 | sudo apt-get install php-pear
43 | sudo apt-get install php-mcrypt
44 | sudo apt-get install php7.0-mbstring
45 | sudo apt-get install php-mbstring
46 | sudo apt-get install php-gettext
47 | sudo apt-get install php-bcmath
48 | sudo apt-get install php-dom
49 |
50 | # Desinstalar php completamente
51 | sudo apt-get purge 'php*'
52 | sudo apt-get autoclean
53 | sudo apt-get autoremove
54 |
55 | # Levantar/Detener/Reiniciar servicios(apache2/httpd/mysql)
56 | sudo service apache2 [start/stop/restart]
57 |
58 | # Permitir que el usuario funcione como apache
59 | sudo chown -R usuario:usuario html
60 | sudo usermod -a -G www-data usuario
61 | sudo adduser usuario www-data
62 |
63 | # Deshabilitar que apache levante con el sistema operativo
64 | sudo systemctl disable apache2
65 | # Levantar apache
66 | sudo service apache2 start
67 | ```
68 |
69 | Rutas amistosas: mod_rewrite
70 | ===
71 | ```bash
72 | # UBUNTU
73 | sudo a2enmod rewrite
74 | # En /etc/apache2/sites-available/000-default.conf
75 |
76 | AllowOverride All
77 |
78 | ```
79 | Hosts virtuales
80 | ===
81 | ```bash
82 | # UBUNTU
83 | # Crear archivo midominio.conf
84 | sudo vim /etc/apache2/sites-available/midominio.conf
85 |
86 | # Dentro del archivo copiar, adaptar y guardar
87 |
88 | ServerName www.midominio.com
89 | ServerAlias midominio.com *midominio.com
90 | DocumentRoot /var/www/html/midominio
91 |
92 |
93 | # Crear el link simbólico estando en /etc/apache2/sites-available
94 | sudo a2ensite midominio.conf
95 |
96 | # Agregar los hosts en el archivo
97 | sudo vim etc/hosts
98 |
99 | # Escribir:
100 | 127.0.0.1 midominio.com www.midominio.com
101 |
102 | # Reiniciar apache
103 | sudo service apache2 restart
104 |
105 | # Opcional: Deshabilitar el sitio
106 | sudo a2dissite midominio.com
107 | sudo service apache2 restart
108 | ```
109 |
110 | PHPMYADMIN
111 | ===
112 | ```bash
113 | # UBUNTU
114 | sudo apt-get install phpmyadmin
115 | # crear enlace simbólico
116 | sudo ln -s /usr/share/phpmyadmin /var/www/html
117 | # cambiar el tiempo maximo de session (1440 segundos por defecto)
118 | # Settings->Features->General->Login cookie validity
119 | #Cambiar en php.ini
120 | session.gc_maxlifetime = MismoValorConfigurado
121 | ```
122 |
123 | Optimizar php
124 | ===
125 | ```bash
126 | # UBUNTU
127 | # En /etc/php/7.0/apache2/php.ini
128 | realpath_cache_size = 1024k
129 | realpath_cache_ttl = 3600
130 | max_execution_time = 3600
131 | max_input_time = 3600
132 | memory_limit = 256M
133 | post_max_size = 56M
134 | upload_max_filesize = 256M
135 | # Para ambiente de desarrollo es bueno tener todos los mensajes menos algunos
136 | error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
137 | ```
138 |
139 | Optimizar mysql
140 | ===
141 | ```bash
142 | # En /etc/mysql/my.cnf
143 |
144 | [mysqld]
145 | query_cache_size = 64M
146 | query_cache_type = ON
147 | max_allowed_packet = 128M
148 | max_connections = 100
149 |
150 | innodb_buffer_pool_size = 3072M
151 | innodb_log_file_size = 1024M
152 | innodb_flush_method = O_DIRECT
153 | innodb_log_buffer_size = 128M
154 | innodb_flush_log_at_trx_commit = 2
155 | sync_binlog = 0
156 | innodb_thread_concurrency = 4
157 | ```
158 |
159 | Referencias
160 | ====
161 | Drupal al sur
162 | - http://drupalalsur.org/videos/optimizar-php-y-mysql-para-drupal-7
163 |
164 | Optimizar mysql
165 | - http://www.speedemy.com/17-key-mysql-config-file-settings-mysql-5-7-proof/
166 |
167 | Instalar php multiversion
168 | - https://www.digitalocean.com/community/tutorials/how-to-install-php-7-4-and-set-up-a-local-development-environment-on-ubuntu-18-04
169 |
170 | Instalar mariabd
171 | - https://www.digitalocean.com/community/tutorials/how-to-install-mariadb-on-ubuntu-22-04
172 |
--------------------------------------------------------------------------------
/DevOps/lando.md:
--------------------------------------------------------------------------------
1 | LANDO
2 | ========
3 | #### Instalar lando en ubuntu 18.04
4 | ```
5 | Instalar docker
6 |
7 | Descargar archivo instalador para posteriormente insgalarlo
8 | https://github.com/lando/lando/releases
9 |
10 | ```
11 |
12 | ENLACES Y FUENTES
13 | =================
14 | Instalar lando
15 | - https://docs.devwithlando.io/installation/installing.html
16 |
17 | Empezar con LANDO
18 | - https://docs.devwithlando.io/started.html
19 |
20 | Un ejemplo de entorno para D8, d9
21 | - https://www.jidr.one/lando-para-desarrollo-drupal
--------------------------------------------------------------------------------
/DevOps/linux.md:
--------------------------------------------------------------------------------
1 | Administración sistema operativo
2 | ===
3 | ```bash
4 | # Version sistema Operativo
5 | cat /etc/*-release
6 | # Ver memoria utilizada
7 | free
8 | free -m
9 | # Ver los recursos usados por el sistemma
10 | top
11 | htop
12 | # Ver todos los procesos
13 | ps
14 | pstree
15 | # Ejemplos:
16 | ps -A | grep firefox
17 | pgrep firefox
18 | # Matar un proceso dandol el id
19 | kill
20 | # Monitor de procesos en tiempo real: cpu, memoria, capas de red, prioridad, etc
21 | atop
22 | # muestra el tamaño aprox. en GB
23 | df -h
24 | # muestra el tamaño aprox. en nodos
25 | df -i
26 | # Espacio de disco en todas las unidades
27 | df -TH
28 | ```
29 |
30 | Gestión usuarios
31 | ===
32 | ```bash
33 | # Listar usuarios locales
34 | cut -d: -f1 /etc/passwd
35 | # Listar todos los grupos de usuario formato Grupo:Contraseña:ID_Grupo(GID):Lista de usuarios
36 | cat /etc/group
37 | # Agregar usuario y crear su propio grupo
38 | sudo useradd nombre_usuario
39 | # Asignar el usuario al grupo del root
40 | usermod -aG sudo nombre_usuario
41 | # Asignar el usuario al grupo de apache
42 | usermod -aG www-data nombre_usuario
43 | ```
44 |
45 | Gestion de archivos
46 | ===
47 | ```bash
48 | # Ver los permisos de un archivo/carpeta en modo numérico
49 | find carpeta/archivo -printf '%m %p\n'
50 | # Limpiar todo el contenido de un archivo (para limpiar logs)
51 | truncate -s0 error_log
52 | # Ver el peso de una carpeta/archivo recursivamente
53 | du -sh nombre_carpeta
54 | # Calcula el tamaño real de los directorios
55 | du -h --max-depth=1
56 | # Descomprimir tar.gz
57 | tar -xzvf nombre_archivo.tar.gz
58 | # Comprimir tar.gz
59 | tar -zcvf nombre_archivo.tar.gz nombre_carpeta
60 | # Comprimir 7z
61 | 7z a FacturasAExcepcionar.7z FacturasAExcepcionar.txt
62 | # Descomprimir .gz
63 | gunzip nombre_archivo.gz
64 | # Accesos carpeta
65 | cd carpeta
66 | cd ..
67 | # Mover archivos
68 | mv carpeta nueva_carpeta
69 | mv archivo.extension archivo_nuevo.extension
70 | # Copiar archivos
71 | cp -R carpeta nueva_carpeta
72 | cp archivo archivo_nuevo
73 | # Listar archivos
74 | ls
75 | ls /ruta/carpeta
76 | # archivos ocultos
77 | ls -a
78 | # ver propiedades de los archivos
79 | ls -l
80 | # combinamos propiedades y archivos ocultos
81 | ls -la
82 |
83 | # Cambiar permisos
84 | # chmod 775 -R /ruta/carpeta
85 | # 4->lectura
86 | # 2->escritura
87 | # 1->ejecución
88 |
89 | # Cambiar permisos a sólo directorios.
90 | find -type d -print0 |xargs -0 chmod 755
91 |
92 | # Cambiar dueño
93 | chown usuario:grupo /ruta/carpeta
94 | # Crear enlace simbólicos (soft)
95 | ln -s /ruta/carpeta/ nombre_enlace
96 | # Remover enlace simbólico (soft)
97 | unlink nombre_enlace
98 | # Posibilitar que un archivo se ejecute desde cualquier lugar llamando desde la consola
99 | mv archivo.phar /usr/local/bin/nombre_comando
100 | # Buscar en el contenido de los archivos
101 | grep -lir "texto buscado"
102 | # Buscar en el contenido de los archivos con retorno parcial del contenido
103 | grep -r "texto buscado"
104 | # Buscar en determinados tipos de archivos
105 | grep -lir 'langcode' --include \*.schema.yml
106 | ```
107 | Redes
108 | ===
109 | ```bash
110 | #Lista todas las interfaces de red y su estado
111 | rfkill list all
112 |
113 | #Instalar open ssh para permitir acceso remoto
114 | https://www.cyberciti.biz/faq/ubuntu-linux-install-openssh-server/
115 | ```
116 |
117 | Gestion Ubuntu
118 | ===
119 | ```bash
120 | # Instalar .deb mediante consola
121 | sudo dpkg -i google-chrome-stable_current_i386.deb
122 |
123 | # Trabajar con la consola en múltiples ventanas
124 | sudo apt-get install screen
125 | screen
126 | # Dividir horizontalmente
127 | ctrl a + shift s
128 | # Dividir verticalmente
129 | ctrl a + shift \
130 | # Cambiar de ventana
131 | ctrl a + tab
132 | # Establecer misma sesión en la ventana
133 | ctrl a + 0-9
134 | # Establecer nueva sesión en la ventana
135 | ctrl a + c
136 | # Redimencionar la ventana
137 | ctrl a :resize enter
138 | # Remover una region
139 | ctrl+a :remove
140 |
141 | #FISH: Utilitario que incrementa la eficiencia con el trabajo en la consola
142 | # Instalar
143 | sudo apt-get install fish
144 |
145 | # Configurar
146 | fish_config
147 |
148 | # Establecer fish como el shell por defecto del sistema operativo.
149 | chsh -s /usr/bin/fish
150 |
151 | # Sin embargo, en Fish, se encadena comandos con ";" en lugar de "&&" por lo que si necesitas concatenar puedes salirte momentaneamente de fish
152 | $ fish bash
153 | ó
154 | $ bash
155 | # Para volver
156 | fish
157 |
158 | # Warp: una utilidad para la terminal que incluyo autocompletar, bloques, ia, drive.
159 | https://www.warp.dev/
160 |
161 | # Descargar un archivo de internet
162 | wget http://www.nombreweb.com/archivo.ext
163 |
164 | # Reparar sistema de paquetería cuando estan rotos
165 | sudo apt-get -f install
166 | sudo dpkg --configure -a
167 | sudo apt-get autoremove
168 | sudo apt-get clean
169 | sudo rm /var/lib/apt/lists/* -vf
170 | sudo apt-get update
171 | ```
172 |
173 | Servidor email para envío sólamente desde php
174 | ===
175 | ```bash
176 | # Instalamos sendmail
177 | sudo apt-get install sendmail
178 | # Configuramos sendmail (se pone Si a las preguntas)
179 | sudo sendmailconfig
180 | # Editamos el archivo hosts
181 | sudo vim /etc/hosts
182 |
183 | # Ponemos este contenido en el principio del archivo. Comentando si hay algo similar
184 | # 127.0.0.1 localhost localhost.localdomain your_domain_name_here.com
185 | # Ejemplo real:
186 | # 127.0.0.1 localhost localhost.devtest.com skynet
187 | # Reiniciamos apache
188 |
189 | # AYUDAS:
190 | # Obtener el nombre del host (your_domain_name_here.com)
191 | hostname
192 | ```
193 |
194 |
195 | Buscar y reemplazar
196 | ===
197 | ```bash
198 | # Buscar archivos por patrón de nombre:
199 | find /path -type f -iname '*name*'
200 | # Buscar directorios por patrón de nombre:
201 | find /path -type d -iname '*name*'
202 |
203 | # Buscar recursivamente por debajo de directorio actual dentro de archivos por patrón:
204 | grep -rie 'bank'
205 |
206 | # Buscar archivos por nombre y reemplazar por otra palabra (tener cuidado, probar antes comando anterior):
207 | find /path -type f -exec sed -i 's/bank/Bank/g' {} \;
208 | ```
209 |
210 | Conectar entre servidores
211 | ===
212 | ```bash
213 | # Copiar archivo de un servido a tu equipo
214 | sudo scp -P 2222 nombres_usuario@ip_servidor:/ruta_al_archivo /ruta_destino
215 | ```
216 |
217 | Aplicaciones útiles para desarrollo
218 | ===
219 | - Kazam
220 | Permite grabar screenshots, videos de areas de la pantalla.
221 |
222 | - Kompare
223 | Permite comparar 2 carpetas, de manera muy similar a git.
224 |
225 |
226 | Referencias
227 | ===
228 | Screen
229 | - http://www.pixelbeat.org/lkdb/screen.html
230 |
231 | Corregir los permisos de los archivos
232 | - http://boomshadow.net/tech/fixes/fixperms-script/
233 | - https://forums.cpanel.net/threads/fix-permissions-in-accounts.73414/
234 |
235 | Acceso remoto a servidor por linea de comandos
236 | - http://www.hypexr.org/linux_scp_help.php
237 |
238 | Enviar emails desde php
239 | - http://lukepeters.me/blog/getting-the-php-mail-function-to-work-on-ubuntu
240 | - https://gist.github.com/adamstac/7462202
241 |
--------------------------------------------------------------------------------
/DevOps/mysql.md:
--------------------------------------------------------------------------------
1 | MYSQL
2 | =====
3 | ## Comandos gestion
4 | ```bash
5 | # Reiniciar mysql (ubuntu)
6 | $ service mysql restart
7 | # Reiniciar mysql (fedora)
8 | $ /etc/init.d/mysqld restart
9 | ```
10 |
11 | ## Comandos administrativos
12 | ```bash
13 | # Ingresar con usario y clave
14 | $ mysql --user=user_name --password=user_password db_name;
15 | # V
16 | $ mysql -u user_name -puser_password db_name;
17 |
18 | # Mostrar bases de datos y tablas
19 | $ SHOW databases;
20 | $ SHOW tables;
21 |
22 | # Crear bases de datos
23 | $ CREATE database db_name;
24 |
25 | # Usar una bases de datos
26 | $ USE db_name;
27 | //una vez que se esta con una base de datos seleccionada se puede ejecutar sql.
28 |
29 | # Salir
30 | $ quit;
31 |
32 | # Crear usuario
33 | $ CREATE USER 'db_user'@'localhost' IDENTIFIED BY 'user_password';
34 | $ SELECT * FROM mysql.user;
35 |
36 | # Asignar clave a un usuario (ejemplo al usuario root)
37 | $ mysql -u root
38 | SET PASSWORD FOR 'root'@'localhost' = PASSWORD('clave');
39 | SET PASSWORD FOR 'root'@'127.0.0.1' = PASSWORD('clave');
40 | SET PASSWORD FOR 'root'@'%' = PASSWORD('clave');
41 |
42 | # Cambiar de clave
43 | $ mysql -u user_name -p'user_password' new_password
44 |
45 | # Eliminar usuario
46 | $ DROP USER db_user:
47 |
48 | # Privilegios a una base de datos en específico
49 | $ GRANT ALL PRIVILEGES ON db_name.* to 'db_user'@'localhost';
50 | $ FLUSH PRIVILEGES;
51 |
52 | # Privilegios a todas las bases de datos
53 | $ GRANT ALL PRIVILEGES ON *.* TO 'db_user'@'localhost' WITH GRANT OPTION;
54 | $ FLUSH PRIVILEGES;
55 |
56 | # Otorgar control total
57 | $ GRANT ALL ON *.* TO 'koalasof'@'localhost' WITH GRANT OPTION;
58 |
59 | # Ver privilegios
60 | $ show grants for bd_user@db_host
61 |
62 | # Sacar backup
63 | $ mysqldump --user=[uname] --password=[pwd] [dbname] > [backupfile.sql]
64 |
65 | # Restaurar backup
66 | $ mysql --user=[uname] --password=[pwd] [db_to_restore] < [backupfile.sql]
67 |
68 | ```
69 | ## Comandos básicos
70 | ```bash
71 | # Eliminar todos los registros de una tabla
72 | $ TRUNCATE TABLE
73 | ```
74 | ## Estados y configuraciones de la base de datos
75 | ```bash
76 | #Ver de una tabla en específico
77 | $ SHOW TABLE STATUS LIKE 'k_caeb';
78 | #Ver de los campos de una tabla
79 | $ SELECT COLUMN_NAME, TABLE_NAME, CHARACTER_SET_NAME, COLUMN_TYPE COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'bdcli_octopus_technologies' AND TABLE_NAME = 'k_caeb';
80 | #Ver de la base de datos
81 | $ SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'bdman_sistema';
82 | ```
83 | ## Comandos avanzados
84 | ```bash
85 | #Eliminar varias bases de datos
86 | $ mysql> SELECT CONCAT('DROP DATABASE ',schema_name,' ;') AS stmt FROM information_schema.schemata WHERE schema_name LIKE 'bdkhipu\_%' ESCAPE '\\' ORDER BY schema_name
87 | ```
88 |
89 | Referencias
90 | ===
91 | http://www.rackspace.com/knowledge_center/article/installing-mysql-server-on-centos
92 |
--------------------------------------------------------------------------------
/DevOps/php.md:
--------------------------------------------------------------------------------
1 | PHP
2 | ===
3 | ### Cambiar entre versiones de php
4 | ```bash
5 | sudo update-alternatives --config php
6 | sudo a2dismod php7.4
7 | sudo a2enmod php8.2
8 | sudo systemctl restart apache2
9 |
10 | sudo a2dismod php8.2
11 | sudo a2enmod php7.4
12 | sudo systemctl restart apache2
13 |
14 | ```
15 |
16 | #### Comparadores cortos
17 | ```php
18 | // Asignación de valor en if/else.
19 | $result = $condition ? 'foo' : 'bar';
20 |
21 | // Asignación con conparación a nulo.
22 | $result = $variable ?? 'valor_si_variable_no_es_nulo'; // 'fallback'
23 | ```
24 |
25 | #### Gestión de rutas, directorio y archivos
26 | ```php
27 | $_SERVER[REQUEST_URI]
28 | //Ruta actual del proyecto
29 | getcwd()
30 |
31 | //Ruta host (sin http://)
32 | $_SERVER[HTTP_HOST]
33 |
34 | //Ruta url despues del host
35 | $_SERVER[REQUEST_URI]
36 |
37 | //Ruta base con protocolo
38 | $baseUri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]";
39 |
40 | //Llamar una página en background
41 | $ch = curl_init();
42 | curl_setopt($ch, CURLOPT_URL, "http://example.com/Set.cgi?Image=1");
43 | curl_setopt($ch, CURLOPT_HEADER, false);
44 | curl_exec($ch);
45 | curl_close($ch);
46 | ```
47 |
48 | #### Documentar una variable como una clase
49 | ```php
50 | /* @var $edit_operation_url \Drupal\Core\Url */
51 | $edit_operation_url = $operations['edit']['url'];
52 | ```
53 |
54 | #### Gestión de arreglos
55 | ```php
56 | //Recorrido
57 | $arr = [1, 2, 3, 4];
58 | foreach ($arr as &$value) {
59 | $value = $value * 2;
60 | }
61 |
62 | //Agregar campos en un array asociativo
63 | $options = [];
64 | foreach ($stores as $store) {
65 | $options = $options + [
66 | $store->getId() => $store->getName(),
67 | ];
68 | }
69 |
70 | //Agregar array en un array de arrays asociativos
71 | $options = [];
72 | foreach ($stores as $store) {
73 | $options[] = [
74 | $store->getId() => $store->getName(),
75 | ];
76 | }
77 |
78 | //Array de arrays asociativos
79 | $eventsTaron[] = [
80 | 'id' => $idEvent,
81 | 'city' => $event['city_name'],
82 | 'country' => $event['country_name'],
83 | 'place' => $place,
84 | 'product_type' => $productType,
85 | 'date' => $event['event_date'],
86 | ];
87 |
88 | ```
89 |
90 | #### Gestión de números
91 | ```php
92 | //Redondeo
93 | round( $my_number, 2, PHP_ROUND_HALF_UP)
94 | ```
95 |
96 | Gestión de objetos
97 | ```
98 | //Clonando un objeto
99 | $dateEvent = $event->getInitTime();
100 | $deadline = clone $dateEvent;
101 |
102 | //Si un objeto es de cierto tipo
103 | if ($questionAnswer instanceof Question)
104 | ...
105 | ```
106 |
107 | #### Gestion de cadenas
108 | ```php
109 | //Remplazar ocurrencias de una cadena por otra cadena
110 | $resultado = str_replace("texto a remplazar", "texto remplazador", "texto original");
111 |
112 | //Obtener un pedazo de una cadena
113 | $resultado = substr( "texto original" , 0, 4); //retorna "texto"
114 |
115 | //convertir un arreglo en un string
116 | $array = array('apellido', 'email', 'telefono');
117 | $comma_separated = implode(",", $array);//apellido,email,telefono
118 |
119 | //posición de una cadena
120 | if (strpos($a,'are') !== false) {
121 | echo 'true';
122 | }
123 |
124 | //funcion para obtener una cadena entre otras cadenas
125 | function get_string_between($string, $start, $end){
126 | $string = " ".$string;
127 | $ini = strpos($string,$start);
128 | if ($ini == 0) return "";
129 | $ini += strlen($start);
130 | $len = strpos($string,$end,$ini) - $ini;
131 | return substr($string,$ini,$len);
132 | }
133 |
134 | $fullstring = "this is my [tag]dog[/tag]";
135 | $parsed = get_string_between($fullstring, "[tag]", "[/tag]");
136 |
137 | //Partir una cadena en arreglo
138 | $pieces = explode(" ", $pizza);
139 |
140 | ```
141 |
142 | #### Timestamp y fechas
143 | ```php
144 | $now = time() //Ahora...
145 | $iniDay = strtotime("midnight", $now); //inicio del día
146 | $endDay = strtotime("tomorrow", $iniDay) - 1; //final del día
147 |
148 | //Año actual
149 | $year = date("Y");
150 |
151 | //Convertir string a timestamp
152 | $date_of_request = $request->request->get('date_of_request');
153 | $created = strptime($date_of_request, '%d/%m/%Y');
154 | $timestamp = mktime(0, 0, 0, $created['tm_mon']+1, $created['tm_mday'], $created['tm_year']+1900);
155 |
156 | //Convertir timestamp a Date
157 | date('m/d/Y', 1299446702);
158 |
159 | //Convertir Date a timestamp
160 | strtotime($time);
161 |
162 | //Aumentar n(30) días a una fecha
163 | $date = date('Y-m-d H:i:s', strtotime($date. ' + 30 days'));
164 |
165 | //Zona horaria Ej: America/La_paz
166 | date_default_timezone_get()
167 |
168 | //UTC
169 | $dec = floatval(date('Z'));
170 | $seconds = $dec;
171 | $hours = intval($dec/3600);
172 | $seconds -= $hours * 3600;
173 | $minutes = floor($seconds / 60);
174 | $utc = $this->getHours($hours).":".$this->getMins($minutes);
175 |
176 | ```
177 |
178 | #### Errores
179 | ```php
180 | // escribir en el log de errores de apache
181 | error_log("Pablito clavo un clavito...!", 0);
182 | ```
183 |
184 | #### Javascript
185 | ```php
186 | //Codificar un arreglo php para ser rescatado desde js
187 | $arrayEncodedToJs = json_encode($array);
188 |
189 | //Recuperar en un arreglo de php un arreglo js codificado
190 | $arrayDecodedFromJs = json_decode($array);
191 | ```
192 |
193 | #### Google API
194 | ```php
195 | //Librería oficial
196 | https://developers.google.com/api-client-library/php/
197 |
198 | //Repositorio
199 | https://github.com/google/google-api-php-client
200 |
201 | //Lista de apis
202 | https://www.googleapis.com/discovery/v1/apis?fields=items(title,discoveryLink)
203 |
204 | //Lista de scopes de una api (ejemplo Calendar API)
205 | https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest?fields=auth(oauth2(scopes))
206 |
207 | //Buen post
208 | http://googleappsdeveloper.blogspot.com.es/2012/01/tips-on-using-apis-discovery-service.html
209 |
210 | //Guia completa del API de google
211 | https://developers.google.com/google-apps/products
212 |
213 | ```
214 |
215 | ### Multiversiones
216 | https://ostechnix.com/how-to-switch-between-multiple-php-versions-in-ubuntu/
217 |
218 | POO
219 | ===
220 | INTERFACES
221 | - Permiten especifcar los métodos que va contener una clase.
222 | - Todos los métodos declarados en una interface son públicos.
223 | - Es posible declarar constructores.
224 | - Pueden ser extendidas por el operador "extend"
225 | - Son clases template de otras clases y en programación moderna se los usa directamente para instanciar esas otras clases que lo usan de template.
226 | ```php
227 | interface iTemplate {
228 | public function setVariable($name, $var);
229 | }
230 |
231 | class Template implements iTemplate {
232 | private $vars = array();
233 | public function setVariable($name, $var) {
234 | $this->vars[$name] = $var;
235 | }
236 | }
237 | ```
238 | ```php
239 | // Una clase puede implementar n interfaces.
240 | // Se usa para estandarizar clases.
241 | interface A {
242 | ...
243 | }
244 | interface B {
245 | ...
246 | }
247 |
248 | class C implements A, B {
249 | ...
250 | }
251 | ```
252 | ```php
253 | // Un interface puede ser implementada por n clases.
254 | // se usa para estandarizar los nombres de los métodos de un grupo de clases equivalentes.
255 | interface A {
256 | ...
257 | }
258 | class B implements A {
259 | ...
260 | }
261 | class C implements A {
262 | ...
263 | }
264 | ```
265 |
266 | TRAITS
267 | - Permiten declaran métodos abstractos y no abstractos que pueden ser usados por múltiples clases.
268 | - Resuelven el problema de que una clases no puede heredar de muchas otras clases
269 | ```php
270 | trait message1 {
271 | public function msg1() {
272 | echo "OOP is fun! ";
273 | }
274 | }
275 |
276 | class Welcome {
277 | use message1;
278 | }
279 |
280 | $obj = new Welcome();
281 | $obj->msg1();
282 | ?>
283 | ```
284 |
285 | PHP 7 nuevas sintaxis
286 | ===
287 | NULLABLE
288 | ```php
289 | // Puede retornar NULL o String
290 | function a(): ?string { }
291 |
292 | // Puede recibir como parámetro NULL o String, pero no "valor vacio"
293 | function test(?string $name) { }
294 | ```
295 | STRICT MODE
296 | ```php
297 | // Los tipos de datos se respetan de manera estrícta.
298 | .output mi_tabla.sql
14 | sqlite> .dump mi_tabla
15 | sqlite> .quit
16 |
17 | ```
18 |
19 | Referencias
20 | ===
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/DevOps/ssh.md:
--------------------------------------------------------------------------------
1 | SSH
2 | ===
3 | ```bash
4 | # Instalación de openssh servidor en sistema ubuntu: suficiente para loguearse remotamente por ssh.
5 | sudo apt-get install openssh-server
6 |
7 | # Logueo remoto por ssh
8 | ssh -p 2222 usuario@200.58.81.32
9 |
10 | # Generar key para conexion en remoto: va a generar una clave privada y una publica .pub
11 | # ed25519 es una solución criptográfica, implementa el algoritmo de firma digital de curva de Edwards EdDSA.
12 | ssh-keygen -t ed25519 -C "algun comentario"
13 |
14 | # Copiar key ssh a servidor remoto: crea una linea en ./ssh/authorized_keys en el servidor remoto y ahora le host puede conectar sin necesidad del password del sistema operativo, sino solo con la clave del key creado.
15 | ssh-copy-id -p 2222 -i ~/.ssh/id_ed25519.pub usuario@200.58.81.32
16 |
17 | # Iniciar conexion sin escribir contraseña.
18 | eval $(ssh-agent)
19 | ssh-add
20 |
21 | # Iniciar conexion sin escribir contraseña de manera permanete.
22 | vim .bashrc
23 | # Agregar
24 | alias ssha = 'eval $(ssh-agent) && ssh-add'
25 | ```
26 |
27 |
28 | REFERENCIAS
29 | ---
30 | Video explicativo
31 | - https://www.youtube.com/watch?v=-Q4T9wLsvOQ&list=PLT98CRl2KxKEUHie1m24-wkyHpEsa4Y70&index=2
32 |
33 | Documentacion ubuntu
34 | - https://ubuntu.com/server/docs/openssh-server
35 |
--------------------------------------------------------------------------------
/DevOps/xdebug.md:
--------------------------------------------------------------------------------
1 | XDEBUG
2 | ========
3 |
4 | #### Instalar
5 | ```
6 | Instalar el paquete para desarrolladores php
7 | sudo apt install php7.2-dev
8 |
9 | Obtener archivo con información del entorno php
10 | $ sudo php -i > ~/php-info.txt
11 |
12 | Subir el archivo generado php-info.txt al generador de paso para instalar en
13 | https://xdebug.org/wizard.php
14 | Ejecutar los paso generados...
15 |
16 | Conecta xdebug con el editor
17 | $ sudo apt install php-xdebug
18 |
19 | Editar xdebug.ini
20 | $ sudo vim /etc/php/7.0/mods-available/xdebug.ini
21 | Copiar la siguiente configuración
22 | zend_extension = /usr/lib/php/20170718/xdebug.so
23 | xdebug.remote_autostart = 1
24 | xdebug.remote_enable = 1
25 | xdebug.remote_handler = dbgp
26 | xdebug.remote_host = 127.0.0.1
27 | xdebug.remote_log = /tmp/xdebug_remote.log
28 | xdebug.remote_mode = req
29 | xdebug.remote_port = 9005 #if you want to change the port you can change
30 |
31 | Reiniciar apache
32 | $ sudo service apache2 restart
33 |
34 | ```
35 |
36 | ENLACES Y FUENTES
37 | =================
38 | Guía para instalar
39 | https://blog.thamaraiselvam.com/finally-configured-xdebug-with-sublime-text-3-on-ubuntu-17-04-ea19aff56c67
40 |
--------------------------------------------------------------------------------
/Ecosistema/SEO.md:
--------------------------------------------------------------------------------
1 | SEO
2 | ========
3 |
4 | #### Módulos
5 |
6 | Pixeles de facebook
7 | https://www.drupal.org/project/facebook_pixel
8 |
9 |
10 | ### Plataformas google que debes de manejar
11 | Google analitycs
12 |
13 | Google adsense.- Para monetizar un sitio añadiendo publicidad
14 |
15 | Google adwords.- Palabras clave y sus busquedas.
16 |
17 | Google search console.- sitemaps - contro busquedas.
18 |
19 | ENLACES Y FUENTES
20 | =================
21 | Panorama generar de seo-muldiidiomas
22 | https://www.srijan.net/blog/multilingual-seo-drupal
23 |
24 | Ecosistema de módulos seo
25 | https://www.srijan.net/blog/essential-drupal-seo-modules-to-boost-traffic-on-your-website
--------------------------------------------------------------------------------
/Ecosistema/integraciones.md:
--------------------------------------------------------------------------------
1 | INTEGRACIONES
2 | ========
3 |
4 | #### Datalayer
5 | Integración con googe tag manager para hacer seguimiento de los visitantes mediante etiquetas
6 | https://www.drupal.org/project/datalayer
7 |
8 |
9 | ENLACES Y FUENTES
10 | =================
11 |
--------------------------------------------------------------------------------
/Ecosistema/modulos.md:
--------------------------------------------------------------------------------
1 | MÓDULOS
2 | ========
3 |
4 | #### Redes sociales
5 | Compartir en redes sociales
6 | - https://www.drupal.org/project/addtoany
7 |
8 | ### Entidades
9 |
10 | ### Campos
11 | Permisos sobre los campos
12 | - https://www.drupal.org/project/field_permissions
13 |
14 | Colocar tamaño máximo a cualquier campo
15 | - https://www.drupal.org/project/maxlength
16 |
17 | ### Menus
18 | Agregar atributos a los links de los menús.
19 | - https://www.drupal.org/project/menu_link_attributes
20 |
21 | ### Vistas
22 | Colocar una vista como un campo en a otras entidades (Manage fields)
23 | - https://www.drupal.org/project/viewsreference
24 |
25 | Filtro alfabetico, fecha granular, rango de fechas
26 | - https://www.drupal.org/project/custom_view_filters
27 |
28 | En filtros: Agregar radiobuttons, checkboxes, seleccionar todos, nunguno
29 | - https://www.drupal.org/project/better_exposed_filters
30 |
31 | ### Layouts
32 | Permitir editar arrastrando la presentación de paragraphs
33 | - https://www.drupal.org/project/layout_paragraphs
34 |
35 | Lista de módulos que extienden layout builder
36 | - https://www.drupal.org/docs/8/core/modules/layout-builder/additional-modules
37 |
38 | ### Media
39 | Enla a la entidad padre.
40 | - https://www.drupal.org/project/media_parent_entity_link
41 |
42 | ### CKEditor
43 | Crear enlace con texto definido.
44 | - https://www.drupal.org/project/ckeditor_link_with_text
45 |
46 | ### Usuarios
47 | Redireccionar despues de loguearse por roles.
48 | - https://www.drupal.org/project/redirect_after_login
49 |
50 | Autenticación con validación mediante email, celular
51 | - https://www.drupal.org/project/tfa
52 |
53 | ### Geolocalización
54 | Almacenar datos geográficos
55 | - https://www.drupal.org/project/geofield
56 |
57 | Mapas compatibles con geofield
58 | - https://www.drupal.org/project/geofield_map
59 |
60 | Para integrar buscador
61 | - https://www.drupal.org/project/geocoder
62 |
63 | ### Subscripciones
64 | Para newsletters
65 | - https://www.drupal.org/project/simplenews
66 |
67 | ### Backups
68 | Entorno para sacar backups
69 | - https://www.droptica.com/blog/how-backup-drupal-overview-backup-and-migrate-module/?amp%25253Butm_medium=rss&%25253Butm_content=rss%25253Futm_source%25253Drss?utm_source=drupal-newsletter&utm_medium=email&utm_campaign=drupal-newsletter-20210225
70 |
71 | ENLACES Y FUENTES
72 | =================
73 | Cómo crear subtemas, documentación oficial
74 | https://www.drupal.org
75 | /docs/theming-drupal/creating-sub-themes
--------------------------------------------------------------------------------
/Front-end/Twig.md:
--------------------------------------------------------------------------------
1 | TWIG
2 | ========
3 | #### Debuguear (Depurar/destripar variables, errores)
4 | ```
5 | // Habilitar debug: En sites/default/services.yml
6 | parameters:
7 | twig.config:
8 | debug: true
9 |
10 | // Imprimir variables: Se debe activar los módulos devel y kint
11 | {{ kint(nombre_variable) }}
12 |
13 | // Se puede usar el plugin de firefox "firebug" activando "Show comments"
14 |
15 | ```
16 |
17 | #### Texto traducible del ingles
18 | ```
19 |
20 | {% trans %} Hello baby {% endtrans %}
21 |
22 | ```
23 | #### Texto con contexto e idioma fuente
24 | ```
25 |
30 |
31 |
32 | ```
33 |
34 | ENLACES Y FUENTES
35 | =================
36 | Documentación de la comunidad
37 | https://www.drupal.org/node/1906392
38 |
39 | Sitio oficial de twig contiene documentación
40 | http://twig.sensiolabs.org/
41 |
--------------------------------------------------------------------------------
/Front-end/bootstrap.md:
--------------------------------------------------------------------------------
1 | Bootstrap
2 | ========
3 | #### Sistema de grilla
4 | Tamaños disponibles
5 | ```
6 | Extra small <576px
7 | Small ≥576px
8 | Medium ≥768px
9 | Large ≥992px
10 | Extra large ≥1200px
11 | ```
12 | Clase para filas
13 | ```
14 | row
15 | ```
16 | Clases para columnas
17 |
18 | | Extra small | Small | Medium | Large | Extra large |
19 | | ----------- | -------- | -------- | -------- | ----------- |
20 | | .col- | .col-sm- | .col-md- | .col-lg- | .col-xl- |
21 |
22 | #### Responsivo
23 | Tamaños responsivos de Bootstrap 4
24 | ```
25 | Display 1 (6rem = 90px)
26 | Display 2 (5.5rem = 82.5px)
27 | Display 3 (4.5rem = 67.5px)
28 | Display 4 (3.5rem = 52.5px)
29 | h1 (2.5rem = 40px)
30 | h2 (2rem = 32px)
31 | h3 (1.75rem = 28px)
32 | h4 (1.5rem = 24px)
33 | h5 (1.25rem = 20px)
34 | h6 (1rem = 16px)
35 | p (1rem = 16px)
36 | ```
37 | Volver responsivo el h1
38 | ```
39 | h1 {font-size:1rem;} /*1rem = 16px*/
40 | ```
41 |
42 | ENLACES Y FUENTES
43 | =================
44 | Sistema de grilla
45 | https://getbootstrap.com/docs/4.0/layout/grid/
46 |
47 | Texto responsivo
48 | https://bootstrapcreative.com/can-adjust-text-size-bootstrap-responsive-design/
49 |
--------------------------------------------------------------------------------
/Front-end/javascript.md:
--------------------------------------------------------------------------------
1 | Javascript
2 | ========
3 | ####
4 |
5 | 1. Implementar Libreria en mi_modulo/hello.libraries.yml
6 | ```yml
7 | hello_world:
8 | version: 1.x
9 | js:
10 | js/hello.js: {}
11 | dependencies:
12 | - core/jquery
13 | - core/drupal
14 | - core/jquery.once
15 | ```
16 |
17 | 2. Agregar al render la libreria
18 | ```php
19 | $render[#target] = $this->t('Hello');
20 | $render[#attached] = [
21 | 'library' => [
22 | 'mi_modulo/hello_world'
23 | ]
24 | ]
25 | $render['#attached']['drupalSettings'] = [
26 | 'node_type' => $node->type->entity->label(),
27 | ];
28 | ```
29 |
30 | 3. Implementamos el js en Drupal.attachBehaviours (cuando la página esta completamente cargada)
31 | ```js
32 | (function (Drupal, $) {
33 | "use strict";
34 | Drupal.behaviors.helloWorld = {
35 | attach: function (context, settings) {
36 | var message = 'Hello ' + settings.node_type + '
'
37 | $(document).find('.hello').append(message);
38 | }
39 | }
40 | }) (Drupal, jQuery)
41 | ```
42 | context:Contiene sólo las partes nuevas de la página.
43 |
44 | settings: Contiene datos pasados desde php (Drupal)
45 |
46 | ENLACES Y FUENTES
47 | =================
48 |
49 | Estándares de programación js dentro de drupal
50 | - https://www.drupal.org/node/172169
51 |
52 |
53 | Nuevas formas de usar jquery ui
54 | - https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-from-drupal-9-to-drupal-10-0/migrating-dependencies-on-core-jquery-ui-libraries
--------------------------------------------------------------------------------
/Front-end/jinja.md:
--------------------------------------------------------------------------------
1 | Jinja
2 | ========
3 | #### Instalación
4 |
5 | ```bash
6 | python3 -m pip install jinja2
7 | ```
8 |
9 | ENLACES Y FUENTES
10 | =================
11 | Hello world
12 | - https://www.geeksforgeeks.org/getting-started-with-jinja-template/
13 |
14 | Documentación oficial
15 | - https://jinja.palletsprojects.com/en/3.1.x/api/
--------------------------------------------------------------------------------
/Front-end/librerias.md:
--------------------------------------------------------------------------------
1 | Librerias
2 | ========
3 | #### Sobreescribir los estilos de una clase padre
4 | Agregar esto en el archivo .info.yml del Tema
5 |
6 | Para rempplazar un archivo css:
7 | ```
8 | libraries-override:
9 | classy/base:
10 | css:
11 | component:
12 | css/components/menu.css: css/my-menu.css
13 | ```
14 | Para deshabilitar:
15 | ```
16 | libraries-override:
17 | classy/base:
18 | css:
19 | component:
20 | css/components/menu.css: false
21 | ```
22 |
23 | ENLACES Y FUENTES
24 | =================
--------------------------------------------------------------------------------
/Front-end/preprocess.md:
--------------------------------------------------------------------------------
1 | Preprocess
2 | ========
3 | #### Sobreescribir un theme
4 |
5 | Para manejar el focal point:
6 | ```php
7 | /**
8 | * Implements hook_preprocess_hook().
9 | */
10 | function nombre_theme_preprocess_paragraph__full_width_push(array &$variables) {
11 | $paragraph = $variables['paragraph'];
12 | if ($paragraph->hasField('field_image_media') && !$paragraph->field_image_media->isEmpty()) {
13 | // Get image url.
14 | $entity_type_manager = \Drupal::entityTypeManager();
15 | $media = $entity_type_manager->getStorage('media')->load($paragraph->field_image_media->target_id);
16 | $file = $entity_type_manager->getStorage('file')->load($media->field_media_image->target_id);
17 | $image_uri = $file->getFileUri();
18 | $style = $entity_type_manager->getStorage('image_style')->load('style_full_width_push_default');
19 | $variables['project_image_url'] = $style->buildUrl($image_uri);
20 | // Get image focal point settings.
21 | $variables['project_image_url_focal_point'] = '0 0';
22 | $crop_type = \Drupal::config('focal_point.settings')->get('crop_type');
23 | $focal_point_manager = \Drupal::service('focal_point.manager');
24 | $crop = $focal_point_manager->getCropEntity($file, $crop_type);
25 | if (!$crop->get('x')->isEmpty() && !$crop->get('y')->isEmpty()) {
26 | $x = $crop->get('x')->value;
27 | $y = $crop->get('y')->value;
28 | $focal_point = $focal_point_manager->absoluteToRelative($x, $y, $media->field_media_image->width, $media->field_media_image->height);
29 | $variables['project_image_url_focal_point'] = $focal_point['x'] . '% ' . $focal_point['y'] . '%';
30 | }
31 | \Drupal::service('renderer')->addCacheableDependency($variables, $media);
32 | }
33 | }
34 |
35 | /**
36 | * Implements hook_preprocess_views_view_unformatted__clubs__clubs_activities_schedule().
37 | */
38 | function koala_ecommerce_preprocess_field__commerce_product__title(&$variables) {
39 | /** @var Drupal\commerce_product\Entity\Product $product */
40 | if ($product = $variables['element']['#object']) {
41 | $product_id = $product->id();
42 | // @todo work with more than one variation.
43 | $variations = $product->getVariationIds();
44 | $variation_id = reset($variations);
45 | $category_id = $product->get('field_categoy')->getValue()[0]['target_id'];
46 | $term = Term::load($category_id);
47 | $subcategory_id = 0;
48 | $id = $term->id();
49 | $parent_id = $term->parent->target_id;
50 | if ($parent_id > 0) {
51 | $category_id = $parent_id;
52 | $subcategory_id = $id;
53 | }
54 |
55 | $params = [
56 | 'product_id' => $product_id,
57 | 'product_variation_id' => $variation_id,
58 | 'category' => $category_id,
59 | 'subcategory' => $subcategory_id,
60 | ];
61 | $url = new Url('koala_ecommerce.product_page', $params);
62 | $variables['items'][0]['content']['#url'] = $url;
63 | }
64 | }
65 | ```
--------------------------------------------------------------------------------
/Front-end/sub-temas.md:
--------------------------------------------------------------------------------
1 | Sub-Temas
2 | ========
3 | #### Estructura de archivos
4 | ```
5 | ```
6 |
7 | ENLACES Y FUENTES
8 | =================
9 | Cómo crear subtemas, documentación oficial
10 | https://www.drupal.org
11 | /docs/theming-drupal/creating-sub-themes
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/drupal_vuejs.info.yml:
--------------------------------------------------------------------------------
1 | name: Drupal vuejs
2 | type: module
3 | description: Example for integration of drupal and vuejs
4 | package: Custom
5 | core: 8.x
6 | core_version_requirement: ^8 || ^9
7 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/drupal_vuejs.libraries.yml:
--------------------------------------------------------------------------------
1 | # Third-party library (Vuejs CDN).
2 | vuejs:
3 | remote: https://vuejs.org
4 | version: 2.0.5
5 | license:
6 | name: MIT
7 | url: https://github.com/vuejs/vue/blob/dev/LICENSE
8 | gpl-compatible: true
9 | js:
10 | https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js: {type: external, minified: true}
11 |
12 | # Custom Vuejs functionality.
13 | appvuejs:
14 | version: 1.x
15 | js:
16 | js/appvuejs.js: {}
17 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/drupal_vuejs.module:
--------------------------------------------------------------------------------
1 | [
18 | 'test_var' => NULL,
19 | 'test_var2' => NULL
20 | ],
21 | 'template' => 'twigTest',
22 | ];
23 | return $theme;
24 | }
25 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/drupal_vuejs.permissions.yml:
--------------------------------------------------------------------------------
1 | administer drupal_vuejs configuration:
2 | title: 'Administer drupal_vuejs configuration'
3 | description: 'Optional description.'
4 | restrict access: true
5 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/drupal_vuejs.routing.yml:
--------------------------------------------------------------------------------
1 | drupal_vuejs.twigtest:
2 | path: '/drupal-vuejs/test'
3 | defaults:
4 | _title: 'Test of vue js functionality'
5 | _controller: '\Drupal\drupal_vuejs\Controller\drupalVuejsController::testContent'
6 | requirements:
7 | _permission: 'access content'
8 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/js/appvuejs.js:
--------------------------------------------------------------------------------
1 | new Vue({
2 | el: '#app',
3 |
4 | data: {
5 | hello: 'This text can be change!',
6 | names: [
7 | {firstname: 'Noah', lastname:'Doe'},
8 | {firstname: 'James', lastname:'Smith'},
9 | {firstname: 'Oliver', lastname:'Campbell'}
10 | ]
11 | },
12 | delimiters: ['[[',']]']
13 | })
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/src/Controller/drupalVuejsController.php:
--------------------------------------------------------------------------------
1 | 'twigTest',
19 | '#test_var' => $this->t('Example of a page'),
20 | '#test_var2' => $this->t('implemented with Vuejs'),
21 | '#attached' => [
22 | 'library' => [
23 | 'drupal_vuejs/vuejs',
24 | 'drupal_vuejs/appvuejs',
25 | ]
26 | ],
27 | '#cache' => array(
28 | 'max-age' => 0,
29 | ),
30 | ];
31 |
32 | return $content;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Modulos/drupal_vuejs/templates/twigTest.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
{{ test_var }} {{ test_var2 }}
3 |
4 |
5 |
6 |
[[ hello ]]
7 |
8 |
9 |
{% trans %} List generated with Vuejs {% endtrans %}
10 |
11 | -
12 | [[ name.firstname ]]
13 | [[ name.lastname ]]
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DRUPAL DEVELOPER
2 | =================
3 | Este proyecto es una guía suficiente, con los conocimientos para desarrollar potentes aplicacines web sibre Drupal 8 y 9.
4 |
5 | principios de esta guía:
6 |
7 | * Va al grano, es decir no contiene teoría ni blabla.
8 | * Contiene comandos y trozos de código útiles.
9 | * Intentar abarcar todos los conocimientos básicos que un programador en Drupal 8 debe tener.
10 |
11 | #### Back-end [semi-completo]
12 | Trozos de código y refencias para realizar trabajos con el API de drupal.
13 |
14 | #### Contribución [completo]
15 | Guías para montar un entorno de contribución productivo y poder corregir-mejorar el código de Drupal.
16 |
17 | #### Ecosistema [empezando]
18 | Módulos, Temas, Distribuciones y recursos disponibles y listos para montar.
19 |
20 | #### Front-end [empezando]
21 | Trozos de código y referencias para trabajar en la GUI que va desplegar drupal.
22 |
23 | #### Infraestructura [semi-completo]
24 | Se trada de guías para montar un ambiente productivo
25 |
26 | #### Utiles [empezando]
27 | Se trada de guías para trabajar con tecnologías complementarias y scripts o herramientas de apoyo
28 |
29 | ##### Jarvis [empezando]
30 | Se trata de una colección de scripts bash que agilizan tareas usuales.
31 | * Para poder ejecutar los comandos desde cualquier ubicación desde la consola es necesario copiarlos a /usr/local/bin
32 | ojo el script debe tener permisos de ejecución
33 | si el sistema es fedora o aws se debe colocar enlace simbólico a /usr/bin
34 | ln -s /usr/local/bin/ /usr/bin/composer/
35 |
36 | #### POR HACER
37 |
38 | * Corregir trozos de código antiguos que tienen mejores prácticas por estos días.
39 | * Completar las seciones que se encuentran en [empezando] y [semi-completo].
40 |
41 | #### LLAMADO
42 | Cualquier persona puede contribuir a estos documentos:
43 | * Reportando fallos.
44 | * Solicitando nuevas secciones o aclaraciones.
45 | * Agregando documentación. (pull-request)
46 |
--------------------------------------------------------------------------------
/Utiles/archivos/drush:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vacho/DrupalDeveloper/7df3ba942522512a057c689d20cf2fd2466e18d3/Utiles/archivos/drush
--------------------------------------------------------------------------------
/Utiles/console.md:
--------------------------------------------------------------------------------
1 | CONSOLE
2 | ========
3 |
4 | #### Instalar Composer globalmente (pre-requisito)
5 | ```bash
6 | curl -sS https://getcomposer.org/installer | php
7 | sudo mv composer.phar /usr/local/bin/composer
8 | # Para fedora, aws EC2
9 | ln -s /usr/local/bin/composer /usr/bin/composer
10 | ```
11 |
12 | Console
13 | ===
14 | #### Instalar globalmente
15 | ```bash
16 | curl https://drupalconsole.com/installer -L -o drupal.phar
17 | mv drupal.phar /usr/local/bin/drupal
18 | chmod +x /usr/local/bin/drupal
19 | # Probar
20 | drupal list
21 | ```
22 |
23 |
24 | #### Iniciar las configuraciones de la consola
25 | ```bash
26 | # Inicializar configuraciones por defecto de drupal
27 | drupal init
28 |
29 | # (opcional)Para usar Fish: Crear enlace simbólico
30 | ln -s ~/.console/drupal.fish ~/.config/fish/completions/drupal.fish
31 | ```
32 |
33 | #### Instalar Drupal
34 |
35 | ```bash
36 | # Bajar drupal
37 | drupal site:new nombreInstancia 8.1.8
38 |
39 | # Instalar drupal
40 | cd nombreInstancia
41 | drupal site:install
42 |
43 | chown www-data:www-data -R sites/default
44 | chmod 755 -R sites/default
45 | drupal cache:rebuild
46 | ```
47 |
48 | #### Comandos de desarrollo
49 |
50 | ```bash
51 | # Crear un módulo
52 | drupal generate:module
53 |
54 | # Crear una entidad de contenido
55 | drupal generate:entity:content
56 |
57 | # Actualizar entidades despues de hacer modificaciones
58 | drupal update:entities
59 |
60 | # Exportar configuraciones
61 | drupal config_split:export --no-interaction
62 |
63 | # Debuguear una configuración activa
64 | drupal debug:config mi_modulo.mi_plugin --show-overridden
65 | ```
66 |
67 | #### Comandos útiles
68 |
69 | ```bash
70 | # Limpiar caches
71 | drupal cache:rebuild
72 | # (Se puede elegir que cache limpiar despues de dar Enter, elegir con las fechas arriba, abajo)
73 |
74 | # Instalar un módulo
75 | drupal module:download nombreDelModulo
76 | drupal module:install nombreDelModulo
77 |
78 | # Poner el sitio en modo dev
79 | drupal site:mode dev
80 |
81 | # Poner el sitio en modo prod
82 | drupal site:mode prod
83 | ```
84 | #### Solución errores comunes
85 |
86 | ```bash
87 | # Timezone America/Tijuana
88 |
89 | # /etc/php5/cli/php.ini
90 | # Editar la línea por ejemplo
91 | # date.timezone = America/La_Paz
92 |
93 | # No quiere ejecutar porque necesita se añadan dependencias en el proyecto
94 | composer require drupal/console:~1.0 --prefer-dist --optimize-autoloader
95 |
96 | # No quiere actualizar dependencia con composer en servidor producción
97 | # 1. Ejecutar en ambiente local
98 | composer update
99 | # 2. Copiar el archivo "composer.lock" de local al servidor de producción
100 | # 3. Ejecutar en el servidor de producción
101 | composer install
102 | ```
103 |
104 | ENLACES Y FUENTES
105 | =================
106 | Composer
107 | - https://getcomposer.org/doc/00-intro.md#globally
108 |
109 | Documentación oficial
110 | - https://hechoendrupal.gitbooks.io/drupal-console/content/es/index.html
111 |
112 | Sitio
113 | - https://drupalconsole.com/
114 |
115 | Repositorio
116 | - https://github.com/hechoendrupal/DrupalConsole
117 |
118 | Resumen de comandos
119 | - http://drupalconsole.com/cheatsheet/
120 |
--------------------------------------------------------------------------------
/Utiles/doxygen.md:
--------------------------------------------------------------------------------
1 |
2 | DOXYGEN
3 | ========
4 |
5 | #### Instalar doxygen
6 | ```bash
7 | sudo apt-get install doxygen
8 | sudo apt install doxygen-gui
9 | ```
10 |
11 | #### Generar documentación
12 | ```bash
13 | # Correr GUI para configurar y generar documentación.
14 | doxywizard
15 | ```
16 |
17 |
18 | ENLACES Y FUENTES
19 | =================
20 | Instalar en ubuntu
21 | - https://www.tutorialspoint.com/articles/how-to-install-doxygen-on-ubuntu
22 |
--------------------------------------------------------------------------------
/Utiles/jarvis/initHostVirtual:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | MDOMAIN="$1"
3 | MEXT="$2"
4 |
5 | if [ $# -ne 2 ]
6 | then
7 | echo "Jarvis: Use $0 {domain} {extension}"
8 | exit 1
9 | fi
10 |
11 | cd /etc/apache2/sites-available/
12 |
13 | cat > $MDOMAIN.conf << EOF
14 | # Default
15 |
16 | ServerName www.$MDOMAIN.$MEXT
17 | ServerAlias $MDOMAIN.$MEXT *$MDOMAIN.$MEXT
18 | DocumentRoot /var/www/html/$MDOMAIN
19 |
20 | EOF
21 |
22 | echo "127.0.0.1 $MDOMAIN.$MEXT www.$MDOMAIN.$MEXT" >> /etc/hosts
23 |
24 | mkdir /var/www/html/$MDOMAIN
25 | a2ensite $MDOMAIN.conf
26 | service apache2 restart
27 |
--------------------------------------------------------------------------------
/Utiles/jarvis/restartDB:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | MHOST="$1"
3 | MUSER="$2"
4 | MPASS="$3"
5 | MDB="$4"
6 | BACKUP="$5"
7 | # Detect paths
8 | MYSQL=$(which mysql)
9 | AWK=$(which awk)
10 | GREP=$(which grep)
11 | if [ $# -ne 5 ]
12 | then
13 | echo "Jarvis: Use $0 {MySQL-Database-Host} {MySQL-User-Name} {MySQL-User-Password} {MySQL-Database-Name} {Backup-file-name}"
14 | echo "Jarvis: I drops all tables from a MySQL"
15 | exit 1
16 | fi
17 | TABLES=$($MYSQL -h $MHOST -u $MUSER -p$MPASS $MDB -e 'show tables' | $AWK '{ print $1}' | $GREP -v '^Tables' )
18 | for t in $TABLES
19 | do
20 | #echo "Deleting $t table from $MDB database..."
21 | $MYSQL -h $MHOST -u $MUSER -p$MPASS $MDB -e "drop table $t"
22 | done
23 | echo "Jarvis: I delete all tables from $MDB"
24 | mysql --user=$MUSER --password=$MPASS $MDB < $BACKUP
25 | echo "Jarvis: Database $MDB restored to $BACKUP"
26 |
--------------------------------------------------------------------------------
/Utiles/javascript.md:
--------------------------------------------------------------------------------
1 | Javascript
2 | ===
3 | Arreglos
4 | ```js
5 | // Recorrido de arreglos
6 | array.forEach(function(item){
7 | ...
8 | });
9 |
10 | // Quitar elementos
11 | array.splice(posicion, numeroelementos);
12 |
13 | // Agregar elementos
14 | array.push(item);
15 | array.splice(posicion, 0, item1, item2, ..., itemN);
16 |
17 | ```
18 |
--------------------------------------------------------------------------------
/Utiles/php.md:
--------------------------------------------------------------------------------
1 | PHP
2 | ===
3 | ### Cambiar entre versiones de php
4 | ```bash
5 | sudo update-alternatives --config php
6 | sudo a2dismod php7.4
7 | sudo a2enmod php8.2
8 |
9 | sudo a2dismod php8.2
10 | sudo a2enmod php7.4
11 |
12 | sudo systemctl restart apache2
13 |
14 | ```
15 |
16 | #### Comparadores cortos
17 | ```php
18 | // Asignación de valor en if/else.
19 | $result = $condition ? 'foo' : 'bar';
20 |
21 | // Asignación con conparación a nulo.
22 | $result = $variable ?? 'valor_si_variable_no_es_nulo'; // 'fallback'
23 | ```
24 |
25 | #### Gestión de rutas, directorio y archivos
26 | ```php
27 | $_SERVER[REQUEST_URI]
28 | //Ruta actual del proyecto
29 | getcwd()
30 |
31 | //Ruta host (sin http://)
32 | $_SERVER[HTTP_HOST]
33 |
34 | //Ruta url despues del host
35 | $_SERVER[REQUEST_URI]
36 |
37 | //Ruta base con protocolo
38 | $baseUri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]";
39 |
40 | //Llamar una página en background
41 | $ch = curl_init();
42 | curl_setopt($ch, CURLOPT_URL, "http://example.com/Set.cgi?Image=1");
43 | curl_setopt($ch, CURLOPT_HEADER, false);
44 | curl_exec($ch);
45 | curl_close($ch);
46 | ```
47 |
48 | #### Documentar una variable como una clase
49 | ```php
50 | /* @var $edit_operation_url \Drupal\Core\Url */
51 | $edit_operation_url = $operations['edit']['url'];
52 | ```
53 |
54 | #### Gestión de arreglos
55 | ```php
56 | //Recorrido
57 | $arr = [1, 2, 3, 4];
58 | foreach ($arr as &$value) {
59 | $value = $value * 2;
60 | }
61 |
62 | //Agregar campos en un array asociativo
63 | $options = [];
64 | foreach ($stores as $store) {
65 | $options = $options + [
66 | $store->getId() => $store->getName(),
67 | ];
68 | }
69 |
70 | //Agregar array en un array de arrays asociativos
71 | $options = [];
72 | foreach ($stores as $store) {
73 | $options[] = [
74 | $store->getId() => $store->getName(),
75 | ];
76 | }
77 |
78 | //Array de arrays asociativos
79 | $eventsTaron[] = [
80 | 'id' => $idEvent,
81 | 'city' => $event['city_name'],
82 | 'country' => $event['country_name'],
83 | 'place' => $place,
84 | 'product_type' => $productType,
85 | 'date' => $event['event_date'],
86 | ];
87 |
88 | ```
89 |
90 | #### Gestión de números
91 | ```php
92 | //Redondeo
93 | round( $my_number, 2, PHP_ROUND_HALF_UP)
94 | ```
95 |
96 | Gestión de objetos
97 | ```
98 | //Clonando un objeto
99 | $dateEvent = $event->getInitTime();
100 | $deadline = clone $dateEvent;
101 |
102 | //Si un objeto es de cierto tipo
103 | if ($questionAnswer instanceof Question)
104 | ...
105 | ```
106 |
107 | #### Gestion de cadenas
108 | ```php
109 | //Remplazar ocurrencias de una cadena por otra cadena
110 | $resultado = str_replace("texto a remplazar", "texto remplazador", "texto original");
111 |
112 | //Obtener un pedazo de una cadena
113 | $resultado = substr( "texto original" , 0, 4); //retorna "texto"
114 |
115 | //convertir un arreglo en un string
116 | $array = array('apellido', 'email', 'telefono');
117 | $comma_separated = implode(",", $array);//apellido,email,telefono
118 |
119 | //posición de una cadena
120 | if (strpos($a,'are') !== false) {
121 | echo 'true';
122 | }
123 |
124 | //funcion para obtener una cadena entre otras cadenas
125 | function get_string_between($string, $start, $end){
126 | $string = " ".$string;
127 | $ini = strpos($string,$start);
128 | if ($ini == 0) return "";
129 | $ini += strlen($start);
130 | $len = strpos($string,$end,$ini) - $ini;
131 | return substr($string,$ini,$len);
132 | }
133 |
134 | $fullstring = "this is my [tag]dog[/tag]";
135 | $parsed = get_string_between($fullstring, "[tag]", "[/tag]");
136 |
137 | //Partir una cadena en arreglo
138 | $pieces = explode(" ", $pizza);
139 |
140 | ```
141 |
142 | #### Timestamp y fechas
143 | ```php
144 | $now = time() //Ahora...
145 | $iniDay = strtotime("midnight", $now); //inicio del día
146 | $endDay = strtotime("tomorrow", $iniDay) - 1; //final del día
147 |
148 | //Año actual
149 | $year = date("Y");
150 |
151 | //Convertir string a timestamp
152 | $date_of_request = $request->request->get('date_of_request');
153 | $created = strptime($date_of_request, '%d/%m/%Y');
154 | $timestamp = mktime(0, 0, 0, $created['tm_mon']+1, $created['tm_mday'], $created['tm_year']+1900);
155 |
156 | //Convertir timestamp a Date
157 | date('m/d/Y', 1299446702);
158 |
159 | //Convertir Date a timestamp
160 | strtotime($time);
161 |
162 | //Aumentar n(30) días a una fecha
163 | $date = date('Y-m-d H:i:s', strtotime($date. ' + 30 days'));
164 |
165 | //Zona horaria Ej: America/La_paz
166 | date_default_timezone_get()
167 |
168 | //UTC
169 | $dec = floatval(date('Z'));
170 | $seconds = $dec;
171 | $hours = intval($dec/3600);
172 | $seconds -= $hours * 3600;
173 | $minutes = floor($seconds / 60);
174 | $utc = $this->getHours($hours).":".$this->getMins($minutes);
175 |
176 | ```
177 |
178 | #### Errores
179 | ```php
180 | // escribir en el log de errores de apache
181 | error_log("Pablito clavo un clavito...!", 0);
182 | ```
183 |
184 | #### Javascript
185 | ```php
186 | //Codificar un arreglo php para ser rescatado desde js
187 | $arrayEncodedToJs = json_encode($array);
188 |
189 | //Recuperar en un arreglo de php un arreglo js codificado
190 | $arrayDecodedFromJs = json_decode($array);
191 | ```
192 |
193 | #### Google API
194 | ```php
195 | //Librería oficial
196 | https://developers.google.com/api-client-library/php/
197 |
198 | //Repositorio
199 | https://github.com/google/google-api-php-client
200 |
201 | //Lista de apis
202 | https://www.googleapis.com/discovery/v1/apis?fields=items(title,discoveryLink)
203 |
204 | //Lista de scopes de una api (ejemplo Calendar API)
205 | https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest?fields=auth(oauth2(scopes))
206 |
207 | //Buen post
208 | http://googleappsdeveloper.blogspot.com.es/2012/01/tips-on-using-apis-discovery-service.html
209 |
210 | //Guia completa del API de google
211 | https://developers.google.com/google-apps/products
212 |
213 | ```
214 |
215 | ### Multiversiones
216 | https://ostechnix.com/how-to-switch-between-multiple-php-versions-in-ubuntu/
217 |
218 | POO
219 | ===
220 | INTERFACES
221 | - Permiten especifcar los métodos que va contener una clase.
222 | - Todos los métodos declarados en una interface son públicos.
223 | - Es posible declarar constructores.
224 | - Pueden ser extendidas por el operador "extend"
225 | - Son clases template de otras clases y en programación moderna se los usa directamente para instanciar esas otras clases que lo usan de template.
226 | ```php
227 | interface iTemplate {
228 | public function setVariable($name, $var);
229 | }
230 |
231 | class Template implements iTemplate {
232 | private $vars = array();
233 | public function setVariable($name, $var) {
234 | $this->vars[$name] = $var;
235 | }
236 | }
237 | ```
238 | ```php
239 | // Una clase puede implementar n interfaces.
240 | // Se usa para estandarizar clases.
241 | interface A {
242 | ...
243 | }
244 | interface B {
245 | ...
246 | }
247 |
248 | class C implements A, B {
249 | ...
250 | }
251 | ```
252 | ```php
253 | // Un interface puede ser implementada por n clases.
254 | // se usa para estandarizar los nombres de los métodos de un grupo de clases equivalentes.
255 | interface A {
256 | ...
257 | }
258 | class B implements A {
259 | ...
260 | }
261 | class C implements A {
262 | ...
263 | }
264 | ```
265 |
266 | TRAITS
267 | - Permiten declaran métodos abstractos y no abstractos que pueden ser usados por múltiples clases.
268 | - Resuelven el problema de que una clases no puede heredar de muchas otras clases
269 | ```php
270 | trait message1 {
271 | public function msg1() {
272 | echo "OOP is fun! ";
273 | }
274 | }
275 |
276 | class Welcome {
277 | use message1;
278 | }
279 |
280 | $obj = new Welcome();
281 | $obj->msg1();
282 | ?>
283 | ```
284 |
285 | PHP 7 nuevas sintaxis
286 | ===
287 | NULLABLE
288 | ```php
289 | // Puede retornar NULL o String
290 | function a(): ?string { }
291 |
292 | // Puede recibir como parámetro NULL o String, pero no "valor vacio"
293 | function test(?string $name) { }
294 | ```
295 | STRICT MODE
296 | ```php
297 | // Los tipos de datos se respetan de manera estrícta.
298 |