- Issue created by @ugintl
- 🇬🇷Greece vensires
Hello @ugintl and thank you for the question!
A client of ours had requested a LMS platform with seminars, articles, videos and certifications while also providing comments, facebook-like functionality etc. On top of that, the users obtain points for each of their actions and in some cases even for the different states of a content they have reached.
Let's say for example that a user visits a seminar node:
- when the node is first visited we want to automatically as viewed
- when it was read we want the user to press a button and as read
- when the quiz of the seminar is complete we want to as completed and also store the percentage score of the results (eg. 80/100)Something extra we needed was a validation that a malicious user wouldn't be able to mark a content as completed if it wasn't already marked as "read"; so there was a dependency requirement between the states (check hook_markit_access_alter()).
It's also important to note that not all content types required to be marked as "Completed". An article for example only requires to be viewed. So we required some settings per entity type and per bundle of entity type.
Next points are the endpoints #4 and #6 in order to allow the users to see how many users liked or reviewed the node + who are these users.
Something extra that was really convenient for us was the use of the following code so that the frontend is aware of the content's state for the current user. We decided not to add it to the module itself but it might be convenient for other developers too:
/** * Implements hook_node_view_alter(). */ function MYMODULE_node_view_alter(array &$build, \Drupal\node\NodeInterface $entity, Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) { /** @var \Drupal\user\UserInterface $account */ $account = \Drupal::entityTypeManager()->getStorage('user')->load(\Drupal::currentUser()->id()); if ($entity->hasField('markit')) { $build['markit'] = []; $metadata = \Drupal\Core\Cache\CacheableMetadata::createFromObject($account); $metadata->applyTo($build['markit']); $markit_types = \Drupal::database()->select('markit', 'm') ->distinct(TRUE) ->fields('m', ['type', 'score']) ->condition('target_entity_type', 'node') ->condition('target_entity_id', $entity->id()) ->condition('uid', $account->id()) ->execute() ->fetchAllKeyed(); foreach ($markit_types as $markit_type => $score) { $build['#attributes']["data-markit-{$markit_type}-set"] = 1; if (isset($score)) { $build['#attributes']["data-markit-{$markit_type}-score"] = $score; } } }
As a sum up,
taking into account all the points addressed previously
+ the fact that Flag module was in beta for Drupal 8+ at that time (~4 years ago) and still is
+ that only some of the points above could be addressed by Flag module alone and definitely not with the convenience provided by this module for our use cases
+ we were already using LikeIt → for the like functionality (again since Flag was beta)
+ we discovered LikeIt's configuration form and entity data structure could be a really good starting point to provide the extra functionalities we were missing,
+ the entity structure with the fields and the properties allowed us good reporting capabilities using View
we concluded in developing our own markit module.And share it with the great Drupal community of course :)
- 🇬🇷Greece vensires
No, a simple drupal core installation.
We have bad experience with Opigno LMS in a previous project where we had to get away from that distribution and then go back to Drupal core; and it wasn’t an easy procedure. - 🇵🇰Pakistan ugintl
Oh. That must have been lot of work.
How long did it take you to create an LMS from scratch on drupal?
- 🇬🇷Greece vensires
Creating the content types required was the easy part - or at least the easiest part. Combining the functionalities together, deciding on which modules to use and which to develop, along with the implementation of the design and the UX expected + the interaction with H5P widgets and a friendly content editor experience with it were the most troublesome things. But the overall result was a great success.
I thing the main question was answered so I am closing this as fixed :)
Automatically closed - issue fixed for 2 weeks with no activity.