Proyectos de Subversion LeadersLinked - Services

Rev

Rev 562 | Rev 724 | Ir a la última revisión | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 562 Rev 721
Línea 96... Línea 96...
96
     * {@inheritDoc}
96
     * {@inheritDoc}
97
     * @see \Laminas\Mvc\Controller\AbstractActionController::indexAction()
97
     * @see \Laminas\Mvc\Controller\AbstractActionController::indexAction()
98
     */
98
     */
99
    public function indexAction()
99
    public function indexAction()
100
    {
100
    {
-
 
101
        $request = $this->getRequest();
-
 
102
        if (!$request->isGet()) {
-
 
103
            return new JsonModel([
-
 
104
                'success' => false,
-
 
105
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
-
 
106
            ]);
-
 
107
        }
-
 
108
 
101
        // Get current user and network information from plugins.
109
        // Get current user and network information from plugins.
102
        $currentUserPlugin = $this->plugin('currentUserPlugin');
110
        $currentUserPlugin = $this->plugin('currentUserPlugin');
103
        $currentUser = $currentUserPlugin->getUser();
111
        $currentUser = $currentUserPlugin->getUser();
Línea 104... Línea 112...
104
 
112
 
105
        $currentNetworkPlugin = $this->plugin('currentNetworkPlugin');
113
        $currentNetworkPlugin = $this->plugin('currentNetworkPlugin');
Línea -... Línea 114...
-
 
114
        $currentNetwork = $currentNetworkPlugin->getNetwork();
-
 
115
 
-
 
116
        // --- Query Parameters ---
-
 
117
        $category_filter_id = Functions::sanitizeFilterString($this->params()->fromQuery('category_id'));
-
 
118
        $search             = Functions::sanitizeFilterString($this->params()->fromQuery('search'));
-
 
119
        $page               = intval($this->params()->fromQuery('start', 1), 10);
-
 
120
        $order_field        = 'added_on'; // Default order field
-
 
121
        $order_direction    = 'asc';      // Default order direction
-
 
122
        $records_x_page     = 12;         // Default records per page
-
 
123
 
-
 
124
        // --- Get accessible categories and filter by category if needed ---
-
 
125
        $categoryData = $this->getAccessibleCategories($currentUser, $currentNetwork);
-
 
126
        $category_ids_to_filter = $this->filterCategoriesByRequest($categoryData, $category_filter_id);
-
 
127
 
-
 
128
        // --- Content Fetching ---
-
 
129
        $storage = Storage::getInstance($this->config, $this->adapter);
-
 
130
        $path = $storage->getPathKnowledgeArea(); 
-
 
131
 
-
 
132
        $knowledgeAreaContentMapper = KnowledgeAreaContentMapper::getInstance($this->adapter);
-
 
133
        $paginator = $knowledgeAreaContentMapper->fetchAllDataTableByCategoryIds(
-
 
134
            $category_ids_to_filter, 
-
 
135
            $search, 
-
 
136
            $page, 
-
 
137
            $records_x_page, 
-
 
138
            $order_field, 
-
 
139
            $order_direction
-
 
140
        );
-
 
141
 
-
 
142
        // --- Response Item Construction ---
-
 
143
        $items = $this->buildContentItems($paginator, $categoryData, $storage, $path);
-
 
144
 
-
 
145
        // --- JSON Response ---
-
 
146
        $image_size = $this->config['leaderslinked.image_sizes.knowledge_area'];
-
 
147
 
-
 
148
        return new JsonModel([
-
 
149
            'success' => true,
-
 
150
            'data' => [
-
 
151
                'current' => [
-
 
152
                    'items' => $items,
-
 
153
                    'page' => $paginator->getCurrentPageNumber(),
-
 
154
                    'count' => $paginator->getCurrentItemCount(),
-
 
155
                ],
-
 
156
                'total' => [
-
 
157
                    'count' => $paginator->getTotalItemCount(),
-
 
158
                    'pages' => $paginator->getPages()->pageCount,
-
 
159
                ],
-
 
160
                'categories' => array_values($categoryData['categories']),
-
 
161
                'categories_with_edition' => $categoryData['categories_with_edition_uuids'],
-
 
162
                'link_add' => $categoryData['allow_add'] ? $this->url()->fromRoute('knowledge-area/add') : '',
-
 
163
                'image_size' => $image_size,
-
 
164
                'content_edit' => count($categoryData['category_with_edition_ids']) > 0,
-
 
165
            ]
-
 
166
        ]);
-
 
167
    }
-
 
168
 
-
 
169
    /**
-
 
170
     * Get metadata for knowledge area (categories, permissions, etc.)
-
 
171
     * This endpoint can be called separately to get UI configuration data
-
 
172
     */
106
        $currentNetwork = $currentNetworkPlugin->getNetwork();
173
    public function metadataAction()
107
 
174
    {
-
 
175
        $request = $this->getRequest();
-
 
176
        if (!$request->isGet()) {
-
 
177
            return new JsonModel([
-
 
178
                'success' => false,
-
 
179
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
Línea 108... Línea -...
108
        $request = $this->getRequest();
-
 
109
        if ($request->isGet()) {
-
 
110
 
-
 
111
            // --- ACL Permissions ---
-
 
112
            // Determine user permissions for various knowledge area actions.
-
 
113
            $acl = $this->getEvent()->getViewModel()->getVariable('acl');
-
 
114
            $allowAdd       = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/add') ? 1 : 0;
-
 
115
            $allowEdit      = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/edit');
-
 
116
            $allowDelete    = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/delete');
-
 
117
            $allowView      = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/view');
-
 
118
 
-
 
119
            // --- Query Parameters ---
-
 
120
            // Retrieve and sanitize query parameters for filtering, searching, and pagination.
180
            ]);
121
            $category_filter_id = Functions::sanitizeFilterString($this->params()->fromQuery('category_id'));
-
 
122
            $search             = Functions::sanitizeFilterString($this->params()->fromQuery('search'));
-
 
123
            $page               = intval($this->params()->fromQuery('start', 1), 10);
-
 
124
            $order_field        = 'added_on'; // Default order field
-
 
125
            $order_direction    = 'asc';      // Default order direction
-
 
126
            $records_x_page     = 12;         // Default records per page
181
        }
127
 
-
 
128
            // --- Category Fetching and Processing ---
-
 
129
            // Initialize arrays to store category information.
-
 
130
            $category_with_edition_ids = [];   // IDs of categories the user can edit.
-
 
Línea 131... Línea -...
131
            $category_with_edition_uuids = []; // UUIDs of categories the user can edit (for response).
-
 
132
            $user_accessible_category_ids = []; // All category IDs accessible to the user directly.
182
 
133
            $categories = [];                  // Master array of category details (id => [uuid, name]).
183
        $currentUserPlugin = $this->plugin('currentUserPlugin');
Línea 134... Línea -...
134
 
-
 
135
            // Instantiate mappers.
184
        $currentUser = $currentUserPlugin->getUser();
136
            $knowledgeAreaCategoryMapper = KnowledgeAreaCategoryMapper::getInstance($this->adapter);
-
 
137
            $knowledgeAreaCategoryUserMapper = KnowledgeAreaCategoryUserMapper::getInstance($this->adapter);
-
 
138
 
185
 
139
            // 1. Fetch categories based on user's direct permissions (via KnowledgeAreaCategoryUser).
-
 
140
            $userCategoryRecords =  $knowledgeAreaCategoryUserMapper->fetchAllByUserId($currentUser->id);
-
 
141
            foreach ($userCategoryRecords as $record) {
-
 
142
                if ($record->role == KnowledgeAreaCategoryUser::ROLE_ADMINISTRATOR || $record->role == KnowledgeAreaCategoryUser::ROLE_USER) {
-
 
143
                    // User has admin or user role in this category, allowing edition.
-
 
144
                    array_push($category_with_edition_ids, $record->category_id);
-
 
145
                    // Fetch category details to get UUID for the response.
-
 
146
                    $categoryDetails = $knowledgeAreaCategoryMapper->fetchOne($record->category_id);
-
 
147
                    if($categoryDetails) {
-
 
Línea -... Línea 186...
-
 
186
        $currentNetworkPlugin = $this->plugin('currentNetworkPlugin');
-
 
187
        $currentNetwork = $currentNetworkPlugin->getNetwork();
-
 
188
 
148
                        array_push($category_with_edition_uuids, $categoryDetails->uuid);
189
        $categoryData = $this->getAccessibleCategories($currentUser, $currentNetwork);
-
 
190
        $image_size = $this->config['leaderslinked.image_sizes.knowledge_area'];
-
 
191
 
-
 
192
        return new JsonModel([
-
 
193
            'success' => true,
-
 
194
            'data' => [
-
 
195
                'categories' => array_values($categoryData['categories']),
-
 
196
                'categories_with_edition' => $categoryData['categories_with_edition_uuids'],
-
 
197
                'link_add' => $categoryData['allow_add'] ? $this->url()->fromRoute('knowledge-area/add') : '',
-
 
198
                'image_size' => $image_size,
-
 
199
                'content_edit' => count($categoryData['category_with_edition_ids']) > 0,
-
 
200
            ]
-
 
201
        ]);
-
 
202
    }
-
 
203
 
-
 
204
    /**
-
 
205
     * Get only the content listing without metadata
-
 
206
     * This endpoint can be called for pagination/filtering without reloading metadata
-
 
207
     */
-
 
208
    public function listAction()
-
 
209
    {
-
 
210
        $request = $this->getRequest();
-
 
211
        if (!$request->isGet()) {
-
 
212
            return new JsonModel([
-
 
213
                'success' => false,
-
 
214
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
-
 
215
            ]);
-
 
216
        }
-
 
217
 
-
 
218
        $currentUserPlugin = $this->plugin('currentUserPlugin');
-
 
219
        $currentUser = $currentUserPlugin->getUser();
-
 
220
 
-
 
221
        $currentNetworkPlugin = $this->plugin('currentNetworkPlugin');
-
 
222
        $currentNetwork = $currentNetworkPlugin->getNetwork();
-
 
223
 
-
 
224
        // --- Query Parameters ---
-
 
225
        $category_filter_id = Functions::sanitizeFilterString($this->params()->fromQuery('category_id'));
149
                    }
226
        $search             = Functions::sanitizeFilterString($this->params()->fromQuery('search'));
-
 
227
        $page               = intval($this->params()->fromQuery('start', 1), 10);
-
 
228
        $order_field        = 'added_on';
-
 
229
        $order_direction    = 'asc';
-
 
230
        $records_x_page     = 12;
-
 
231
 
-
 
232
        // --- Get accessible categories and filter ---
-
 
233
        $categoryData = $this->getAccessibleCategories($currentUser, $currentNetwork);
-
 
234
        $category_ids_to_filter = $this->filterCategoriesByRequest($categoryData, $category_filter_id);
150
                }
235
 
-
 
236
        // --- Content Fetching ---
-
 
237
        $storage = Storage::getInstance($this->config, $this->adapter);
-
 
238
        $path = $storage->getPathKnowledgeArea(); 
-
 
239
 
-
 
240
        $knowledgeAreaContentMapper = KnowledgeAreaContentMapper::getInstance($this->adapter);
-
 
241
        $paginator = $knowledgeAreaContentMapper->fetchAllDataTableByCategoryIds(
-
 
242
            $category_ids_to_filter, 
-
 
243
            $search, 
151
                array_push($user_accessible_category_ids, $record->category_id);
244
            $page, 
152
            }
245
            $records_x_page, 
-
 
246
            $order_field, 
-
 
247
            $order_direction
-
 
248
        );
-
 
249
 
153
 
250
        // --- Response Item Construction ---
154
            // 2. Fetch details for all directly accessible categories if any exist.
251
        $items = $this->buildContentItems($paginator, $categoryData, $storage, $path);
155
            if (!empty($user_accessible_category_ids)) {
252
 
-
 
253
        return new JsonModel([
156
                $detailedUserCategories =  $knowledgeAreaCategoryMapper->fetchAllByIds($user_accessible_category_ids);
254
            'success' => true,
-
 
255
            'data' => [
-
 
256
                'current' => [
-
 
257
                    'items' => $items,
157
                foreach ($detailedUserCategories as $record) {
258
                    'page' => $paginator->getCurrentPageNumber(),
-
 
259
                    'count' => $paginator->getCurrentItemCount(),
-
 
260
                ],
-
 
261
                'total' => [
-
 
262
                    'count' => $paginator->getTotalItemCount(),
-
 
263
                    'pages' => $paginator->getPages()->pageCount,
-
 
264
                ],
-
 
265
            ]
-
 
266
        ]);
-
 
267
    }
-
 
268
 
-
 
269
    /**
-
 
270
     * Get accessible categories for the current user and network
-
 
271
     * 
-
 
272
     * @param object $currentUser
-
 
273
     * @param object $currentNetwork
-
 
274
     * @return array
-
 
275
     */
-
 
276
    private function getAccessibleCategories($currentUser, $currentNetwork)
-
 
277
    {
-
 
278
        // --- ACL Permissions ---
-
 
279
        $acl = $this->getEvent()->getViewModel()->getVariable('acl');
-
 
280
        $allowAdd       = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/add') ? 1 : 0;
-
 
281
        $allowEdit      = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/edit');
-
 
282
        $allowDelete    = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/delete');
-
 
283
        $allowView      = $acl->isAllowed($currentUser->usertype_id, 'knowledge-area/view');
-
 
284
 
-
 
285
        // --- Category Fetching and Processing ---
-
 
286
        $category_with_edition_ids = [];
-
 
287
        $category_with_edition_uuids = [];
-
 
288
        $user_accessible_category_ids = [];
-
 
289
        $categories = [];
-
 
290
 
-
 
291
        // Instantiate mappers.
-
 
292
        $knowledgeAreaCategoryMapper = KnowledgeAreaCategoryMapper::getInstance($this->adapter);
-
 
293
        $knowledgeAreaCategoryUserMapper = KnowledgeAreaCategoryUserMapper::getInstance($this->adapter);
-
 
294
 
-
 
295
        // 1. Fetch categories based on user's direct permissions
-
 
296
        $userCategoryRecords = $knowledgeAreaCategoryUserMapper->fetchAllByUserId($currentUser->id);
158
                    if (!isset($categories[$record->id])) { // Add if not already present
297
        foreach ($userCategoryRecords as $record) {
159
                        $categories[$record->id] = [
298
            if ($record->role == KnowledgeAreaCategoryUser::ROLE_ADMINISTRATOR || $record->role == KnowledgeAreaCategoryUser::ROLE_USER) {
-
 
299
                array_push($category_with_edition_ids, $record->category_id);
-
 
300
                $categoryDetails = $knowledgeAreaCategoryMapper->fetchOne($record->category_id);
160
                            'uuid' => $record->uuid,
301
                if($categoryDetails) {
161
                            'name' => $record->name,
302
                    array_push($category_with_edition_uuids, $categoryDetails->uuid);
-
 
303
                }
162
                        ];
304
            }
163
                    }
305
            array_push($user_accessible_category_ids, $record->category_id);
164
                }
306
        }
165
            }
307
 
166
                
308
        // 2. Fetch details for all directly accessible categories
167
            // 3. Fetch all public categories within the current network.
309
        if (!empty($user_accessible_category_ids)) {
168
            $publicCategories =  $knowledgeAreaCategoryMapper->fetchAllPublicByNetworkId($currentNetwork->id);
310
            $detailedUserCategories = $knowledgeAreaCategoryMapper->fetchAllByIds($user_accessible_category_ids);
169
            foreach ($publicCategories as $record) {
311
            foreach ($detailedUserCategories as $record) {
170
                if (!isset($categories[$record->id])) { // Add if not already present (ensures no duplicates from user-specific list)
312
                if (!isset($categories[$record->id])) {
-
 
313
                    $categories[$record->id] = [
Línea 171... Línea 314...
171
                    $categories[$record->id] = [
314
                        'uuid' => $record->uuid,
172
                        'uuid' => $record->uuid,
315
                        'name' => $record->name,
173
                        'name' => $record->name,
316
                    ];
174
                    ];
-
 
175
                }
-
 
176
            }
317
                }
177
            
-
 
178
            // Sort all collected categories alphabetically by name.
-
 
179
            uasort($categories, function ($a, $b) {
318
            }
180
                return $a['name'] <=> $b['name'];
-
 
181
            });
-
 
182
 
319
        }
183
            // --- Filtering by Category ---
320
            
184
            // If a specific category filter is applied, narrow down the category_ids to search in.
-
 
185
            $category_ids_to_filter = array_keys($categories); // Start with all accessible category IDs.
321
        // 3. Fetch all public categories within the current network
186
            if ($category_filter_id) {
322
        $publicCategories = $knowledgeAreaCategoryMapper->fetchAllPublicByNetworkId($currentNetwork->id);
-
 
323
        foreach ($publicCategories as $record) {
187
                $categoryFilter = $knowledgeAreaCategoryMapper->fetchOneByUuid($category_filter_id);
324
            if (!isset($categories[$record->id])) {
188
                if ($categoryFilter && isset($categories[$categoryFilter->id])) { // Ensure filtered category is accessible
325
                $categories[$record->id] = [
189
                    $category_ids_to_filter = [$categoryFilter->id];
326
                    'uuid' => $record->uuid,
190
                } else {
-
 
191
                    $category_ids_to_filter = []; // Filtered category not found or not accessible, show no results for this filter.
327
                    'name' => $record->name,
192
                }
328
                ];
193
            }
-
 
194
            
-
 
195
            // --- Content Fetching ---
-
 
196
            $storage = Storage::getInstance($this->config, $this->adapter);
329
            }
197
            // $path is the base path for knowledge area, used by getGenericImage.
-
 
198
            $path = $storage->getPathKnowledgeArea(); 
330
        }
199
 
-
 
200
            $knowledgeAreaContentMapper = KnowledgeAreaContentMapper::getInstance($this->adapter);
331
        
201
            // Fetch paginated knowledge area content based on accessible categories and search criteria.
332
        // Sort all collected categories alphabetically by name
202
            $paginator = $knowledgeAreaContentMapper->fetchAllDataTableByCategoryIds($category_ids_to_filter, $search, $page, $records_x_page, $order_field, $order_direction);
-
 
203
 
333
        uasort($categories, function ($a, $b) {
204
            // --- Response Item Construction ---
-
 
205
            $items = [];
334
            return $a['name'] <=> $b['name'];
206
            $contentRecords = $paginator->getCurrentItems();
-
 
207
            foreach ($contentRecords as $record) {
335
        });
208
                // Ensure category details are available for the current content item.
336
 
209
                // This might happen if content somehow exists for a category not in the user's compiled list (e.g. stale data).
-
 
210
                if (!isset($categories[$record->category_id])) {
337
        return [
211
                    $category = $knowledgeAreaCategoryMapper->fetchOne($record->category_id);
-
 
212
                    if ($category) {
-
 
213
                        $categories[$category->id] = [
-
 
214
                            'uuid' =>  $category->uuid,
338
            'categories' => $categories,
215
                            'name' =>  $category->name,
-
 
216
                        ];
-
 
217
                    } else {
-
 
218
                        // Fallback if category is still not found (should be rare).
-
 
219
                        $categories[$record->category_id] = ['uuid' => null, 'name' => 'Unknown Category'];
-
 
220
                    }
339
            'category_with_edition_ids' => $category_with_edition_ids,
Línea -... Línea 340...
-
 
340
            'categories_with_edition_uuids' => $category_with_edition_uuids,
221
                }
341
            'allow_add' => $allowAdd,
-
 
342
            'allow_edit' => $allowEdit,
222
                
343
            'allow_delete' => $allowDelete,
-
 
344
            'allow_view' => $allowView,
-
 
345
        ];
-
 
346
    }
223
                // Strip HTML tags and truncate description for display.
347
 
-
 
348
    /**
224
                $description = strip_tags($record->description);
349
     * Filter categories based on request parameter
-
 
350
     * 
225
                if (strlen($description) > 120) {
351
     * @param array $categoryData
-
 
352
     * @param string $category_filter_id
226
                    $description = substr($description, 0, 120) . '...';
353
     * @return array
227
                }
354
     */
228
 
355
    private function filterCategoriesByRequest($categoryData, $category_filter_id)
229
                // Construct the item for the JSON response.
356
    {
-
 
357
        $category_ids_to_filter = array_keys($categoryData['categories']);
-
 
358
        
-
 
359
        if ($category_filter_id) {
-
 
360
            $knowledgeAreaCategoryMapper = KnowledgeAreaCategoryMapper::getInstance($this->adapter);
-
 
361
            $categoryFilter = $knowledgeAreaCategoryMapper->fetchOneByUuid($category_filter_id);
-
 
362
            if ($categoryFilter && isset($categoryData['categories'][$categoryFilter->id])) {
Línea -... Línea 363...
-
 
363
                $category_ids_to_filter = [$categoryFilter->id];
-
 
364
            } else {
-
 
365
                $category_ids_to_filter = [];
-
 
366
            }
-
 
367
        }
-
 
368
        
-
 
369
        return $category_ids_to_filter;
-
 
370
    }
-
 
371
 
-
 
372
    /**
-
 
373
     * Build content items for response
-
 
374
     * 
-
 
375
     * @param object $paginator
-
 
376
     * @param array $categoryData
-
 
377
     * @param object $storage
-
 
378
     * @param string $path
230
                $item = [
379
     * @return array
231
                    // Use the KnowledgeAreaCategory's UUID for the image path.
380
     */
232
                    'image' => $storage->getGenericImage($path, ($categories[$record->category_id]['uuid'] ?? null), $record->image),
381
    private function buildContentItems($paginator, $categoryData, $storage, $path)
-
 
382
    {
-
 
383
        $items = [];
-
 
384
        $contentRecords = $paginator->getCurrentItems();
-
 
385
        $knowledgeAreaCategoryMapper = KnowledgeAreaCategoryMapper::getInstance($this->adapter);
-
 
386
        
-
 
387
        foreach ($contentRecords as $record) {
233
                    'title' => $record->title,
388
            // Ensure category details are available for the current content item
234
                    'description' => $description,
389
            if (!isset($categoryData['categories'][$record->category_id])) {
235
                    'category' => $categories[$record->category_id]['name'],
-
 
236
                    'link_view' => $allowView ?  $this->url()->fromRoute('knowledge-area/view', ['id' => $record->uuid]) : '',
390
                $category = $knowledgeAreaCategoryMapper->fetchOne($record->category_id);
Línea 237... Línea 391...
237
                ];
391
                if ($category) {
238
 
392
                    $categoryData['categories'][$category->id] = [
-
 
393
                        'uuid' => $category->uuid,
239
                // Add edit/delete links if user has permission for the content's category.
394
                        'name' => $category->name,
-
 
395
                    ];
Línea 240... Línea 396...
240
                if (in_array($record->category_id, $category_with_edition_ids)) {
396
                } else {
241
                    $item['link_edit'] = $allowEdit ?  $this->url()->fromRoute('knowledge-area/edit', ['id' => $record->uuid]) : '';
397
                    $categoryData['categories'][$record->category_id] = ['uuid' => null, 'name' => 'Unknown Category'];
-
 
398
                }
242
                    $item['link_delete'] = $allowDelete ? $this->url()->fromRoute('knowledge-area/delete', ['id' => $record->uuid]) : '';
399
            }
243
                }
400
            
244
                array_push($items, $item);
401
            // Strip HTML tags and truncate description for display
245
            }
402
            $description = strip_tags($record->description);
246
            
403
            if (strlen($description) > 120) {
-
 
404
                $description = substr($description, 0, 120) . '...';
247
            // --- JSON Response ---
405
            }
248
            // Configured image size for frontend reference.
406
 
249
            $image_size = $this->config['leaderslinked.image_sizes.knowledge_area'];
407
            // Construct the item for the JSON response
250
 
408
            $item = [
251
            // Return all data in a JSON format.
-
 
252
            return new JsonModel([
-
 
253
                'success' => true,
-
 
254
                'data' => [
409
                'image' => $storage->getGenericImage($path, ($categoryData['categories'][$record->category_id]['uuid'] ?? null), $record->image),
255
                    'items' => $items,                         // Paginated content items.
-
 
256
                    'total' => $paginator->getTotalItemCount(), // Total number of content items.
410
                'title' => $record->title,
257
                    'page' => $paginator->getCurrentPageNumber(), // Current page number.
-
 
258
                    'total_pages' => $paginator->getPages()->pageCount, // Total number of pages.
-
 
259
                    'categories' => array_values($categories), // List of all accessible categories (re-indexed).
-
 
260
                    'categories_with_edition' => $category_with_edition_uuids, // UUIDs of categories user can edit.
411
                'description' => $description,
-
 
412
                'category' => $categoryData['categories'][$record->category_id]['name'],
-
 
413
                'link_view' => $categoryData['allow_view'] ? $this->url()->fromRoute('knowledge-area/view', ['id' => $record->uuid]) : '',
261
                    'link_add' => $allowAdd ? $this->url()->fromRoute('knowledge-area/add') : '', // Link to add new content if allowed.
414
            ];
Línea 262... Línea 415...
262
                    'image_size' => $image_size,             // Expected image dimensions.
415
 
263
                    'content_edit' => count($category_with_edition_ids) > 0, // Flag if user can edit any content.
416
            // Add edit/delete links if user has permission for the content's category
264
                ]
417
            if (in_array($record->category_id, $categoryData['category_with_edition_ids'])) {
Línea 349... Línea 502...
349
                    // La clase Image fue eliminada debido a que no se encontraba o estaba obsoleta.
502
                    // La clase Image fue eliminada debido a que no se encontraba o estaba obsoleta.
350
                    $storage = Storage::getInstance($this->config, $this->adapter);
503
                    $storage = Storage::getInstance($this->config, $this->adapter);
351
                    // Obtiene la ruta base para los archivos del área de conocimiento.
504
                    // Obtiene la ruta base para los archivos del área de conocimiento.
352
                    // $target_path = $storage->getPathKnowledgeArea(); // No longer needed directly here, composePathTo methods use storagePath internally
505
                    // $target_path = $storage->getPathKnowledgeArea(); // No longer needed directly here, composePathTo methods use storagePath internally
Línea 353... Línea 506...
353
 
506
 
-
 
507
                    $storage->setFiles($request->getFiles()->toArray());
-
 
508
 
-
 
509
                    if($storage->setCurrentFilename('image')) {
-
 
510
                        $tmp_filename = $storage->getTmpFilename();
-
 
511
                        $filename = 'knowledge_image_' . $knowledgeAreaContent->uuid  . '.' . $storage->getExtension();
Línea 354... Línea -...
354
                    $files = $this->getRequest()->getFiles()->toArray();
-
 
355
 
-
 
356
                    // Manejo del archivo de imagen principal.
-
 
357
                    if (isset($files['image']) && empty($files['image']['error'])) {
-
 
358
                        $tmp_image_name  = $files['image']['tmp_name'];
-
 
359
                        $original_image_name_parts = explode('.',  $files['image']['name']);
-
 
360
                        // Genera un nombre de archivo único y normalizado, forzando la extensión .png.
-
 
361
                        $final_image_filename = Functions::normalizeString(uniqid() . '-' . $original_image_name_parts[0] . '.png');
-
 
362
                        
512
                        $storage->composePathToFilename(Storage::TYPE_KNOWLEDGE_AREA, $knowledgeAreaCategory->uuid, $filename);
363
                        // Obtener dimensiones para el redimensionamiento de la imagen del área de conocimiento.
513
 
364
                        list($target_width_str, $target_height_str) = explode('x', $this->config['leaderslinked.image_sizes.knowledge_area']);
514
                        list($target_width_str, $target_height_str) = explode('x', $this->config['leaderslinked.image_sizes.knowledge_area']);
Línea 365... Línea 515...
365
                        $target_width = (int)$target_width_str;
515
                        $target_width = (int)$target_width_str;
366
                        $target_height = (int)$target_height_str;
-
 
367
 
516
                        $target_height = (int)$target_height_str;
368
                        $uuid_path_segment = $knowledgeAreaCategory->uuid;
-
 
369
                        
517
 
370
                        // Construye la ruta completa del directorio de destino usando el UUID de la categoría.
518
                        if (!$storage->uploadImageResize($tmp_filename, $filename, $target_width, $target_height)) {
371
                        $full_target_dir = $storage->composePathToDirectory(Storage::TYPE_KNOWLEDGE_AREA, $uuid_path_segment);
519
                            return new JsonModel([
372
                        // Crea el directorio si no existe.
520
                                'success'   => false,
373
                        if (!is_dir($full_target_dir)) {
-
 
374
                            mkdir($full_target_dir, 0775, true);
-
 
Línea 375... Línea -...
375
                        }
-
 
376
                        // Construye la ruta completa del archivo de destino.
-
 
377
                        $full_target_path_for_image = $storage->composePathToFilename(Storage::TYPE_KNOWLEDGE_AREA, $uuid_path_segment, $final_image_filename);
-
 
378
                        
521
                                'data'      => 'ERROR_IMAGE_UPLOAD'
379
                        // Sube y redimensiona la imagen usando el método de la clase Storage.
-
 
380
                        if ($storage->uploadImageResize($tmp_image_name, $full_target_path_for_image, $target_width, $target_height)) {
522
                            ]);
Línea 381... Línea -...
381
                            $knowledgeAreaContent->image = $final_image_filename; // Guarda solo el nombre del archivo.
-
 
382
                            $knowledgeAreaContentMapper->update($knowledgeAreaContent);
523
                        }
383
                        }
524
                        
384
                    }
525
                        $knowledgeAreaContent->image = $filename;
385
 
526
                    }
386
                    // Manejo del archivo adjunto.
527
 
387
                    if (isset($files['attachment']) && empty($files['attachment']['error'])) {
528
                    if($storage->setCurrentFilename('attachment')) {
388
                        $tmp_attachment_name   = $files['attachment']['tmp_name'];
-
 
389
                        // Normaliza el nombre del archivo adjunto, manteniendo su extensión original.
529
                        $tmp_filename = $storage->getTmpFilename();
390
                        $final_attachment_filename = Functions::normalizeString($files['attachment']['name']);
530
                        $filename = 'knowledge_attachment_' . $knowledgeAreaContent->uuid  . '.' . $storage->getExtension();
391
                        
531
                        $storage->composePathToFilename(Storage::TYPE_KNOWLEDGE_AREA, $knowledgeAreaCategory->uuid, $filename);
392
                        $uuid_path_segment = $knowledgeAreaCategory->uuid;
532
 
393
                        // Necesitamos la ruta base para los adjuntos si composePathToDirectory no se usa aquí directamente
533
                        if (!$storage->moveUploadedFile($tmp_filename, $filename)) {
394
                        $base_attachment_path = $storage->getPathKnowledgeArea(); 
-
 
Línea 395... Línea 534...
395
                        $full_target_dir_for_attachment = $base_attachment_path . DIRECTORY_SEPARATOR . $uuid_path_segment;
534
                            return new JsonModel([
-
 
535
                                'success'   => false,
-
 
536
                                'data'      => 'ERROR_IMAGE_UPLOAD'
396
                        if (!is_dir($full_target_dir_for_attachment)) {
537
                            ]);
397
                            mkdir($full_target_dir_for_attachment, 0775, true);
538
                        }
-
 
539
 
398
                        }
540
                        $knowledgeAreaContent->attachment = $filename;
399
                        $full_target_path_for_attachment = $full_target_dir_for_attachment . DIRECTORY_SEPARATOR . $final_attachment_filename;
541
                    }
400
 
542
 
Línea 401... Línea 543...
401
                        // Mueve el archivo adjunto subido a su ubicación final.
543
                    if(!$knowledgeAreaContentMapper->update($knowledgeAreaContent)) {
Línea 402... Línea 544...
402
                        if ($storage->moveUploadedFile($tmp_attachment_name, $full_target_path_for_attachment)) {
544
                        return new JsonModel([
403
                            $knowledgeAreaContent->attachment = $final_attachment_filename; // Guarda solo el nombre del archivo.
545
                            'success'   => false,
-
 
546
                            'data'      => $knowledgeAreaContentMapper->getError()
404
                            $knowledgeAreaContentMapper->update($knowledgeAreaContent);
547
                        ]);
-
 
548
                    }
-
 
549
 
405
                        }
550
                    $this->logger->info('Se agrego el contenido ' . $knowledgeAreaContent->title, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
406
                    }
551
 
407
 
552
                    $data = [
408
                    $this->logger->info('Se agrego el contenido ' . $knowledgeAreaContent->title, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
553
                        'success'   => true,
409
 
554
                        'data'      => [