Kaynağa Gözat

Modules updates.

AntonLV 4 yıl önce
ebeveyn
işleme
a5070718b2
100 değiştirilmiş dosya ile 10667 ekleme ve 0 silme
  1. 56 0
      modules/boonex/channels/updates/13.0.1_13.0.2/install/config.php
  2. 13 0
      modules/boonex/channels/updates/13.0.1_13.0.2/install/installer.php
  3. 153 0
      modules/boonex/channels/updates/13.0.1_13.0.2/source/install/config.php
  4. 24 0
      modules/boonex/channels/updates/13.0.1_13.0.2/source/template/images/no-picture.svg
  5. 51 0
      modules/boonex/charts/updates/12.0.0_13.0.0/install/config.php
  6. 13 0
      modules/boonex/charts/updates/12.0.0_13.0.0/install/installer.php
  7. 101 0
      modules/boonex/charts/updates/12.0.0_13.0.0/source/classes/BxChartsCron.php
  8. 128 0
      modules/boonex/charts/updates/12.0.0_13.0.0/source/classes/BxChartsDb.php
  9. 77 0
      modules/boonex/charts/updates/12.0.0_13.0.0/source/install/config.php
  10. 56 0
      modules/boonex/courses/updates/13.0.1_13.0.2/install/config.php
  11. 13 0
      modules/boonex/courses/updates/13.0.1_13.0.2/install/installer.php
  12. 152 0
      modules/boonex/courses/updates/13.0.1_13.0.2/source/install/config.php
  13. 19 0
      modules/boonex/courses/updates/13.0.1_13.0.2/source/template/images/no-picture.svg
  14. 51 0
      modules/boonex/credits/updates/13.0.1_13.0.2/install/config.php
  15. 25 0
      modules/boonex/credits/updates/13.0.1_13.0.2/install/installer.php
  16. 11 0
      modules/boonex/credits/updates/13.0.1_13.0.2/install/langs/en.xml
  17. 30 0
      modules/boonex/credits/updates/13.0.1_13.0.2/install/sql/enable.sql
  18. 8 0
      modules/boonex/credits/updates/13.0.1_13.0.2/install/sql/install.sql
  19. 304 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsConfig.php
  20. 31 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsCronClearing.php
  21. 395 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsDb.php
  22. 121 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsFormCredit.php
  23. 206 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsGridHistoryAdministration.php
  24. 1093 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsModule.php
  25. 77 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/install/config.php
  26. 277 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/install/langs/en.xml
  27. 32 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/disable.sql
  28. 221 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/enable.sql
  29. 176 0
      modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/install.sql
  30. 51 0
      modules/boonex/decorous/updates/13.0.1_13.0.2/install/config.php
  31. 26 0
      modules/boonex/decorous/updates/13.0.1_13.0.2/install/installer.php
  32. 49 0
      modules/boonex/decorous/updates/13.0.1_13.0.2/source/data/template/bx_persons/cover.html
  33. 14 0
      modules/boonex/decorous/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less
  34. 68 0
      modules/boonex/decorous/updates/13.0.1_13.0.2/source/install/config.php
  35. 56 0
      modules/boonex/events/updates/13.0.1_13.0.2/install/config.php
  36. 13 0
      modules/boonex/events/updates/13.0.1_13.0.2/install/installer.php
  37. 152 0
      modules/boonex/events/updates/13.0.1_13.0.2/source/install/config.php
  38. 19 0
      modules/boonex/events/updates/13.0.1_13.0.2/source/template/images/no-picture.svg
  39. 51 0
      modules/boonex/files/updates/13.0.1_13.0.2/install/config.php
  40. 13 0
      modules/boonex/files/updates/13.0.1_13.0.2/install/installer.php
  41. 135 0
      modules/boonex/files/updates/13.0.1_13.0.2/source/install/config.php
  42. 11 0
      modules/boonex/files/updates/13.0.1_13.0.2/source/template/entry-text.html
  43. 51 0
      modules/boonex/forum/updates/13.0.1_13.0.2/install/config.php
  44. 13 0
      modules/boonex/forum/updates/13.0.1_13.0.2/install/installer.php
  45. 702 0
      modules/boonex/forum/updates/13.0.1_13.0.2/source/classes/BxForumGrid.php
  46. 149 0
      modules/boonex/forum/updates/13.0.1_13.0.2/source/install/config.php
  47. 13 0
      modules/boonex/forum/updates/13.0.1_13.0.2/source/template/score_element_inline.html
  48. 56 0
      modules/boonex/groups/updates/13.0.1_13.0.2/install/config.php
  49. 13 0
      modules/boonex/groups/updates/13.0.1_13.0.2/install/installer.php
  50. 152 0
      modules/boonex/groups/updates/13.0.1_13.0.2/source/install/config.php
  51. 24 0
      modules/boonex/groups/updates/13.0.1_13.0.2/source/template/images/no-picture.svg
  52. 51 0
      modules/boonex/lucid/updates/13.0.1_13.0.2/install/config.php
  53. 26 0
      modules/boonex/lucid/updates/13.0.1_13.0.2/install/installer.php
  54. 12 0
      modules/boonex/lucid/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less
  55. 68 0
      modules/boonex/lucid/updates/13.0.1_13.0.2/source/install/config.php
  56. 51 0
      modules/boonex/market/updates/13.0.1_13.0.2/install/config.php
  57. 13 0
      modules/boonex/market/updates/13.0.1_13.0.2/install/installer.php
  58. 140 0
      modules/boonex/market/updates/13.0.1_13.0.2/source/install/config.php
  59. 42 0
      modules/boonex/market/updates/13.0.1_13.0.2/source/template/css/entry.css
  60. 24 0
      modules/boonex/market/updates/13.0.1_13.0.2/source/template/entry-text.html
  61. 51 0
      modules/boonex/nexus/updates/13.0.0_13.0.1/install/config.php
  62. 13 0
      modules/boonex/nexus/updates/13.0.0_13.0.1/install/installer.php
  63. 68 0
      modules/boonex/nexus/updates/13.0.0_13.0.1/source/install/config.php
  64. 132 0
      modules/boonex/nexus/updates/13.0.0_13.0.1/source/template/js.html
  65. 87 0
      modules/boonex/nexus/updates/13.0.0_13.0.1/source/template/styles.html
  66. 51 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/install/config.php
  67. 13 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/install/installer.php
  68. 5 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/install/langs/en.xml
  69. 405 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/source/classes/BxNtfsDb.php
  70. 82 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/source/install/config.php
  71. 139 0
      modules/boonex/notifications/updates/13.0.1_13.0.2/source/install/langs/en.xml
  72. 51 0
      modules/boonex/ocean/updates/13.0.1_13.0.2/install/config.php
  73. 26 0
      modules/boonex/ocean/updates/13.0.1_13.0.2/install/installer.php
  74. 20 0
      modules/boonex/ocean/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less
  75. 68 0
      modules/boonex/ocean/updates/13.0.1_13.0.2/source/install/config.php
  76. 51 0
      modules/boonex/payment/updates/13.0.1_13.0.2/install/config.php
  77. 13 0
      modules/boonex/payment/updates/13.0.1_13.0.2/install/installer.php
  78. 337 0
      modules/boonex/payment/updates/13.0.1_13.0.2/source/classes/BxPaymentConfig.php
  79. 610 0
      modules/boonex/payment/updates/13.0.1_13.0.2/source/classes/BxPaymentProviderStripeV3.php
  80. 70 0
      modules/boonex/payment/updates/13.0.1_13.0.2/source/install/config.php
  81. 51 0
      modules/boonex/persons/updates/13.0.1_13.0.2/install/config.php
  82. 13 0
      modules/boonex/persons/updates/13.0.1_13.0.2/install/installer.php
  83. 2 0
      modules/boonex/persons/updates/13.0.1_13.0.2/install/sql/enable.sql
  84. 152 0
      modules/boonex/persons/updates/13.0.1_13.0.2/source/install/config.php
  85. 565 0
      modules/boonex/persons/updates/13.0.1_13.0.2/source/install/sql/enable.sql
  86. 51 0
      modules/boonex/photos/updates/13.0.1_13.0.2/install/config.php
  87. 13 0
      modules/boonex/photos/updates/13.0.1_13.0.2/install/installer.php
  88. 136 0
      modules/boonex/photos/updates/13.0.1_13.0.2/source/install/config.php
  89. 1 0
      modules/boonex/photos/updates/13.0.1_13.0.2/source/template/entry-text.html
  90. 51 0
      modules/boonex/polls/updates/13.0.1_13.0.2/install/config.php
  91. 13 0
      modules/boonex/polls/updates/13.0.1_13.0.2/install/installer.php
  92. 136 0
      modules/boonex/polls/updates/13.0.1_13.0.2/source/install/config.php
  93. 18 0
      modules/boonex/polls/updates/13.0.1_13.0.2/source/template/entry-text-subentries.html
  94. 6 0
      modules/boonex/polls/updates/13.0.1_13.0.2/source/template/entry-text.html
  95. 51 0
      modules/boonex/posts/updates/13.0.1_13.0.2/install/config.php
  96. 13 0
      modules/boonex/posts/updates/13.0.1_13.0.2/install/installer.php
  97. 153 0
      modules/boonex/posts/updates/13.0.1_13.0.2/source/install/config.php
  98. 701 0
      modules/boonex/posts/updates/13.0.1_13.0.2/source/install/sql/install.sql
  99. 51 0
      modules/boonex/protean/updates/13.0.1_13.0.2/install/config.php
  100. 26 0
      modules/boonex/protean/updates/13.0.1_13.0.2/install/installer.php

+ 56 - 0
modules/boonex/channels/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Channels',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/channels/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'channels_update_1301_1302',
+
+    'module_dir' => 'boonex/channels/',
+    'module_uri' => 'channels',
+
+    'db_prefix' => 'bx_cnl_',
+    'class_prefix' => 'BxCnl',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Channels',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(
+        'template/images/no-pciture-big.png',
+        'template/images/no-picture-icon.png',
+        'template/images/no-picture-preview.png',
+        'template/images/no-picture-thumb.png',
+    ),
+);

+ 13 - 0
modules/boonex/channels/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCnlUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 153 - 0
modules/boonex/channels/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,153 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Channels Channels
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_channels',
+    'title' => 'Channels',
+    'note' => 'Channels functionality.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use channels in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/channels/',
+    'home_uri' => 'channels',
+
+    'db_prefix' => 'bx_cnl_',
+    'class_prefix' => 'BxCnl',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Channels',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+        'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+        'trigger_page_profile_view_entry',
+        'trigger_page_group_view_entry',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_channels_pics'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_channels_icon',
+        'bx_channels_thumb',
+        'bx_channels_avatar',
+        'bx_channels_avatar_big',
+        'bx_channels_picture',
+        'bx_channels_cover',
+        'bx_channels_cover_thumb',
+        'bx_channels_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_channels',
+        'bx_channels_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+        'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 24 - 0
modules/boonex/channels/updates/13.0.1_13.0.2/source/template/images/no-picture.svg

@@ -0,0 +1,24 @@
+<svg width="240" height="240" viewBox="0 0 240 240" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M89.4058 196.52C90.7359 193.317 88.3729 189.822 84.9053 189.745C72.4675 189.469 61.4816 188.96 51.8195 188.181C49.1096 187.962 46.6821 189.918 46.4516 192.627C44.6404 213.913 48.8595 223.34 58.9122 226.033C70.0619 229.021 79.1381 221.247 89.4058 196.52ZM114.011 116.88C113.536 118.699 111.88 120 110 120V120C94.1976 120 80.2643 120.255 68.0279 120.816C64.6323 120.971 62.0349 117.798 62.9123 114.514C63.019 114.114 63.1263 113.713 63.2341 113.311C84.8227 32.7412 97.5411 8.62303 115.852 13.5295C133.435 18.2407 133.171 43.5481 114.011 116.88Z" fill="url(#paint0_linear_435_2643)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M128.912 226.033C147.223 230.94 159.942 206.821 181.53 126.252C181.619 125.92 181.708 125.589 181.796 125.258C182.68 121.953 180.044 118.766 176.628 118.952C164.642 119.602 150.929 119.931 135.307 119.99C133.038 119.999 131.044 121.564 130.472 123.76C111.591 196.263 111.416 221.345 128.912 226.033ZM155.129 43.5979C153.814 46.792 156.16 50.2719 159.613 50.3674C172.177 50.7148 183.189 51.3186 192.791 52.2207C195.518 52.4769 197.987 50.5299 198.236 47.802C200.237 25.9048 196.04 16.2594 185.852 13.5295C174.619 10.5197 165.491 18.4321 155.129 43.5979Z" fill="url(#paint1_linear_435_2643)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M126.673 105.739C126.142 107.902 127.772 110 130 110V110C213.412 110 240 103.957 240 85.0001C240 66.8536 215.637 60.5406 140.392 60.0338C137.894 60.017 135.74 61.8524 135.351 64.3199C133.508 75.9865 130.613 89.6905 126.673 105.739ZM65.1363 69.2426C66.2362 65.8091 63.4822 62.3347 59.9008 62.7499C30.72 66.1325 20 72.9628 20 85.0001C20 95.5427 28.2231 102.091 49.8696 105.827C52.3593 106.257 54.7397 104.683 55.41 102.247C58.7898 89.9625 62.0132 78.9918 65.1363 69.2426Z" fill="url(#paint2_linear_435_2643)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M193.776 134.854C191.259 134.345 188.81 135.923 188.127 138.398C184.864 150.231 181.746 160.836 178.723 170.298C177.617 173.757 180.419 177.245 184.018 176.76C210.246 173.227 220 166.482 220 155C220 145.071 212.707 138.685 193.776 134.854ZM108.369 175.698C107.98 178.162 105.83 179.997 103.336 179.987C25.1651 179.663 -8.60626e-06 173.443 -6.99392e-06 155C-5.33663e-06 136.043 26.5882 130 110 130C110.577 130 111.151 130 111.723 130.001C114.966 130.004 117.334 133.058 116.568 136.21C112.868 151.432 110.133 164.504 108.369 175.698Z" fill="url(#paint3_linear_435_2643)"/>
+<defs>
+<linearGradient id="paint0_linear_435_2643" x1="87.3822" y1="12.9231" x2="87.3822" y2="226.64" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB923C"/>
+<stop offset="1" stop-color="#EA580C"/>
+</linearGradient>
+<linearGradient id="paint1_linear_435_2643" x1="157.382" y1="12.9231" x2="157.382" y2="226.64" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB923C"/>
+<stop offset="1" stop-color="#EA580C"/>
+</linearGradient>
+<linearGradient id="paint2_linear_435_2643" x1="130" y1="60.0337" x2="130" y2="110" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34D399"/>
+<stop offset="1" stop-color="#059669"/>
+</linearGradient>
+<linearGradient id="paint3_linear_435_2643" x1="110" y1="130" x2="110" y2="179.987" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34D399"/>
+<stop offset="1" stop-color="#059669"/>
+</linearGradient>
+</defs>
+</svg>

+ 51 - 0
modules/boonex/charts/updates/12.0.0_13.0.0/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Charts',
+    'version_from' => '12.0.0',
+    'version_to' => '13.0.0',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/charts/updates/update_12.0.0_13.0.0/',
+    'home_uri' => 'charts_update_1200_1300',
+
+    'module_dir' => 'boonex/charts/',
+    'module_uri' => 'charts',
+
+    'db_prefix' => 'bx_charts_',
+    'class_prefix' => 'BxCharts',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Charts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/charts/updates/12.0.0_13.0.0/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxChartsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 101 - 0
modules/boonex/charts/updates/12.0.0_13.0.0/source/classes/BxChartsCron.php

@@ -0,0 +1,101 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Charts Charts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxChartsCron extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+        $this->_sModule = 'bx_charts';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct();
+    }
+
+    function processing()
+    {
+        $this->processingTopByLikes();
+        $this->processingMostActiveProfiles();
+        $this->processingMostFollowedProfiles();
+    }
+    
+    function processingTopByLikes()
+    {
+        $aSystems = BxDolVote::getSystems();
+        $aModules = array_keys($this->_oModule->serviceGetTextModules());
+        $sModulesDisabled = explode(',', getParam('bx_charts_chart_top_contents_by_likes_modules_disabled'));
+        $aModules = array_diff($aModules, $sModulesDisabled);
+        $this->_oModule->_oDb->clearTopByLikes();
+        foreach($aModules as $sModule){
+            $oModule = BxDolModule::getInstance($sModule);
+            if(isset($oModule->_oConfig->CNF['OBJECT_VOTES'])){
+                $sSystem = $oModule->_oConfig->CNF['OBJECT_VOTES'];
+                if(empty($sSystem))
+                    continue;
+                $this->_oModule->_oDb->saveTopByLikes($sModule, $aSystems[$sSystem]['table_track']);
+            }
+        }
+    }
+    
+    function processingMostActiveProfiles()
+    {
+        $this->_oModule->_oDb->clearMostActiveProfiles();
+        $aContentModules = array_keys($this->_oModule->serviceGetTextModules());
+        $sContentModulesDisabled = explode(',', getParam('bx_charts_chart_most_active_profiles_posts_for_module_disabled'));
+        $aContentModules = array_diff($aContentModules, $sContentModulesDisabled);
+        foreach($aContentModules as $sContentModule){
+            $oContentModule = BxDolModule::getInstance($sContentModule);
+            if ($oContentModule && isset($oContentModule->_oConfig->CNF['TABLE_ENTRIES']) && isset($oContentModule->_oConfig->CNF['FIELD_AUTHOR'])){
+                $sContentTable = $oContentModule->_oConfig->CNF['TABLE_ENTRIES'];
+                $sColumnAuthor = $oContentModule->_oConfig->CNF['FIELD_AUTHOR'];
+				$sColumnAdded = $oContentModule->_oConfig->CNF['FIELD_ADDED'];
+                if (!empty($sContentTable) && !empty($sColumnAuthor)){
+                    $aSystems = BxDolView::getSystems();
+                    $aModules = array_keys($this->_oModule->serviceGetProfileModules());
+                    $sModulesDisabled = explode(',', getParam('bx_charts_chart_most_active_profiles_modules_disabled'));
+                    $aModules = array_diff($aModules, $sModulesDisabled);
+                    foreach($aModules as $sProfileModule){
+                        $oModule = BxDolModule::getInstance($sProfileModule);
+                        if(isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
+                            $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
+                            if(empty($sSystem))
+                                continue;
+                            $this->_oModule->_oDb->saveMostActiveProfiles_Create($sProfileModule, $sContentModule, $sContentTable, $sColumnAuthor, $sColumnAdded);
+                        }
+                    }
+                }
+            }
+        }
+        
+        foreach($aModules as $sProfileModule){
+            $oModule = BxDolModule::getInstance($sProfileModule);
+            if(isset($oModule->_oConfig->CNF['OBJECT_VIEWS'])){
+                $sSystem = $oModule->_oConfig->CNF['OBJECT_VIEWS'];
+                if(empty($sSystem))
+                    continue;
+                $this->_oModule->_oDb->saveMostActiveProfiles_View($sProfileModule, $aSystems[$sSystem]['table_track']);
+            }
+        }
+    }
+    
+    function processingMostFollowedProfiles()
+    {
+        $this->_oModule->_oDb->clearMostFollowedProfiles();
+        $aModules = array_keys($this->_oModule->serviceGetProfileModules());
+        foreach($aModules as $sProfileModule){
+            $this->_oModule->_oDb->saveMostFollowedProfiles($sProfileModule);
+        }
+    }
+}
+
+/** @} */

+ 128 - 0
modules/boonex/charts/updates/12.0.0_13.0.0/source/classes/BxChartsDb.php

@@ -0,0 +1,128 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Charts Charts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolModuleDb');
+
+class BxChartsDb extends BxBaseModGeneralDb
+{
+    protected $_sTableTopByLikes;
+    protected $_sTableMostActiveProfiles;
+    
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+        $this->_sTableTopByLikes = $this->_sPrefix . 'top_by_likes';
+        $this->_sTableMostActiveProfiles = $this->_sPrefix . 'most_active_profiles';
+        $this->_sTableMostFollowedProfiles = $this->_sPrefix . 'most_followed_profiles';
+    }
+    /* TopByLikes part */
+    public function saveTopByLikes($sModuleName, $sTableName)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_top_contents_by_likes_interval_day'));
+        $sQuery = "INSERT INTO `" . $this->_sTableTopByLikes . "` (`object_id`, `module`, `value`) SELECT `object_id`,'" . $sModuleName . "', COUNT(`id`) FROM `" . $sTableName . "` WHERE `date` > " . ($iInterval > 0 ? $this->getTimeFromDaysBefore($iInterval) : 0) . " GROUP BY `object_id` ORDER BY  COUNT(`id`) DESC LIMIT 0, " . intval(getParam('bx_charts_chart_top_contents_by_likes_count'));
+        $this->query($sQuery);
+    }
+    
+    public function clearTopByLikes()
+    {
+        $sQuery = "TRUNCATE TABLE `" . $this->_sTableTopByLikes . "`";
+        $this->query($sQuery);
+    }
+    
+    public function getTopByLikes()
+    {
+        return $this->getAll("SELECT * FROM  `" . $this->_sTableTopByLikes . "` ORDER BY `value` DESC LIMIT 0," . intval(getParam('bx_charts_chart_top_contents_by_likes_count')));
+    }
+    
+    /* MostActiveProfiles part */
+    public function saveMostActiveProfiles_View($sProfileModuleName, $sTableName)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_most_active_profiles_interval_day'));
+        $sQuery = "INSERT INTO `" . $this->_sTableMostActiveProfiles . "` (`object_id`, `profile_module`, `views_count`) SELECT `object_id`,'" . $sProfileModuleName . "', COUNT(`date`) AS views FROM `" . $sTableName . "` 
+ WHERE `object_id` IN (SELECT `object_id` FROM `" . $this->_sTableMostActiveProfiles . "` WHERE `profile_module` = '" . $sProfileModuleName . "' ) AND `date` > " . ($iInterval > 0 ? $this->getTimeFromDaysBefore($iInterval) : 0) . " GROUP BY `object_id`";
+       
+        $this->query($sQuery);
+    }
+    
+    public function saveMostActiveProfiles_Create($sProfileModuleName, $sContentModuleName, $sTableName, $sColumnAuthor, $sColumnAdded)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_most_active_profiles_interval_day'));
+        $sQuery = "INSERT INTO `" . $this->_sTableMostActiveProfiles . "` (`object_id`, `profile_module`, `content_module`, `create_count`)  SELECT `sys_profiles`.`content_id`, `sys_profiles`.`type`, '" . $sContentModuleName . "' , COUNT(`" . $sTableName . "`.`id`) FROM `" . $sTableName . "`
+  INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `" . $sTableName . "`.`" . $sColumnAuthor . "` WHERE sys_profiles.type='" . $sProfileModuleName . "' AND  `" . $sTableName . "`.`" . $sColumnAdded . "` > " . ($iInterval > 0 ? $this->getTimeFromDaysBefore($iInterval) : 0) . " GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`" . $sTableName . "`.`id`) DESC LIMIT 0," . intval(getParam('bx_charts_chart_most_active_profiles_count'));
+        $this->query($sQuery);
+    }
+    
+    public function clearMostActiveProfiles()
+    {
+        $sQuery = "TRUNCATE TABLE `" . $this->_sTableMostActiveProfiles . "`";
+        $this->query($sQuery);
+    }
+    
+    public function getMostActiveProfiles()
+    {
+        return $this->getAll("SELECT SUM(`views_count`) AS views_count, SUM(`create_count`) AS create_count, `object_id`, `profile_module` as `module` FROM `" . $this->_sTableMostActiveProfiles . "` GROUP BY `object_id`, `module` ORDER BY SUM(`create_count`) DESC, SUM(`views_count`) DESC LIMIT 0," . intval(getParam('bx_charts_chart_most_active_profiles_count')));
+    }
+   
+    /* MostFollowedProfiles part */
+    public function saveMostFollowedProfiles($sProfileModuleName)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_most_followed_profiles_interval_day'));
+        $sQuery = "INSERT INTO `" . $this->_sTableMostFollowedProfiles . "` (`object_id`, `profile_module`, `followers_count`)  SELECT `sys_profiles`.`content_id`, `sys_profiles`.`type` , COUNT(`sys_profiles_conn_subscriptions`.`id`) FROM `sys_profiles_conn_subscriptions`
+  INNER JOIN `sys_profiles`  ON `sys_profiles`.`id` = `sys_profiles_conn_subscriptions`.`content` WHERE sys_profiles.type='" . $sProfileModuleName . "' AND  `sys_profiles_conn_subscriptions`.`added` > " . ($iInterval > 0 ? $this->getTimeFromDaysBefore($iInterval) : 0) . " GROUP BY `sys_profiles`.`content_id`, `sys_profiles`.`type` ORDER BY COUNT(`sys_profiles_conn_subscriptions`.`id`) DESC LIMIT 0," . intval(getParam('bx_charts_chart_most_followed_profiles_count'));
+        $this->query($sQuery);
+    }
+    
+    public function clearMostFollowedProfiles()
+    {
+        $sQuery = "TRUNCATE TABLE `" . $this->_sTableMostFollowedProfiles . "`";
+        $this->query($sQuery);
+    }
+    
+    public function getMostFollowedProfiles()
+    {
+        return $this->getAll("SELECT SUM(`followers_count`) AS followers_count, `object_id`, `profile_module` as `module` FROM `" . $this->_sTableMostFollowedProfiles . "` GROUP BY `object_id`, `module` ORDER BY SUM(`followers_count`) DESC LIMIT 0," . intval(getParam('bx_charts_chart_most_followed_profiles_count')));
+    }
+    
+    /* Growth part */
+    public function getStatistic()
+    {
+        return $this->getAll("SELECT * FROM `sys_statistics` WHERE `name` <> 'bx_albums_media' ORDER BY `order`");
+    }
+
+    /* Growth part */
+    public function getGrowth($sTableName)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_growth_interval_day'));
+        $sQuery =  "SELECT " . getParam('bx_charts_chart_growth_group_by') . "(FROM_UNIXTIME(`added`))  AS `period`, YEAR(FROM_UNIXTIME(`added`))  AS `year`,  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `added` > " . ($iInterval > 0 ? $this->getTimeFromDaysBefore($iInterval) : 0) . " GROUP BY `period`, `year` ORDER BY `year`, `period` ASC";
+        return $this->getAll($sQuery);
+    }
+    
+    public function getGrowthInitValue($sTableName)
+    {
+        $iInterval = intval(getParam('bx_charts_chart_growth_interval_day'));
+        $mixedStartDate = $this->getTimeFromDaysBefore($iInterval);
+        
+        $sQuery =  "SELECT  COUNT(*) AS `count` FROM " . $sTableName . " WHERE `added` < " . ($iInterval > 0 ? $mixedStartDate : 0);
+        $mixedStartValue = $this->getOne($sQuery);
+      
+        if ($iInterval == 0){
+            $sQuery =  "SELECT  MIN(`added`) AS `mindata` FROM " . $sTableName;
+            $mixedStartDate = $this->getOne($sQuery);
+        }
+        return array($mixedStartValue,$mixedStartDate);
+    }
+    
+    private function getTimeFromDaysBefore($iDay){
+        return time() - $iDay * 86400;
+    }
+}
+
+/** @} */

+ 77 - 0
modules/boonex/charts/updates/12.0.0_13.0.0/source/install/config.php

@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Charts Charts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_charts',
+    'title' => 'Charts',
+    'note' => 'Charts module.',
+    'version' => '13.0.0',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/charts/',
+    'home_uri' => 'charts',
+
+    'db_prefix' => 'bx_charts_',
+    'class_prefix' => 'BxCharts',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Charts',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 56 - 0
modules/boonex/courses/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Courses',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/courses/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'courses_update_1301_1302',
+
+    'module_dir' => 'boonex/courses/',
+    'module_uri' => 'courses',
+
+    'db_prefix' => 'bx_courses_',
+    'class_prefix' => 'BxCourses',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Courses',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(
+        'template/images/no-pciture-big.png',
+        'template/images/no-picture-icon.png',
+        'template/images/no-picture-preview.png',
+        'template/images/no-picture-thumb.png',
+    ),
+);

+ 13 - 0
modules/boonex/courses/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCoursesUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 152 - 0
modules/boonex/courses/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_courses',
+    'title' => 'Courses',
+    'note' => 'Basic course profiles functionality.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/courses/',
+    'home_uri' => 'courses',
+
+    'db_prefix' => 'bx_courses_',
+    'class_prefix' => 'BxCourses',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Courses',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+        'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_courses_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_courses_icon', 
+    	'bx_courses_thumb', 
+    	'bx_courses_avatar', 
+        'bx_courses_avatar_big', 
+    	'bx_courses_picture', 
+    	'bx_courses_cover', 
+    	'bx_courses_cover_thumb',
+        'bx_courses_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_courses',
+    	'bx_courses_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+    	'update_relations' => 1,        
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 19 - 0
modules/boonex/courses/updates/13.0.1_13.0.2/source/template/images/no-picture.svg

@@ -0,0 +1,19 @@
+<svg width="240" height="240" viewBox="0 0 240 240" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M189.909 143.498C189.806 139.974 186.093 137.817 182.873 139.252C137.37 159.537 102.506 159.639 57.1093 139.556C53.8867 138.131 50.1788 140.296 50.082 143.819C50.0269 145.822 50 147.882 50 150C50 203.08 66.9197 220 120 220C173.08 220 190 203.08 190 150C190 147.769 189.97 145.602 189.909 143.498Z" fill="url(#paint0_linear_435_3054)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M27.7223 124.666C24.479 122.826 20.3921 124.947 20.2542 128.673C20.0793 133.402 20 138.82 20 145C20 179.123 22.4171 190 30 190C37.5829 190 40 179.123 40 145C40 141.089 39.9683 137.484 39.9006 134.165C39.8636 132.35 38.8278 130.708 37.222 129.859C36.7575 129.614 36.2918 129.367 35.8249 129.118C32.9983 127.61 30.2975 126.127 27.7223 124.666Z" fill="url(#paint1_linear_435_3054)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M51.3903 56.4436C99.8241 84.4069 116.471 91.2271 120.263 84.6601C124.054 78.0932 109.824 67.0864 61.3903 39.1231V39.1231C60.0653 38.3581 60.1571 36.4159 61.5492 35.781C109.361 13.9741 143.839 16.7137 195 43.9999C251.872 74.3315 251.872 93.6683 195 124C138.129 154.331 101.872 154.331 45.0005 124C-8.23 95.6103 -11.6381 76.8527 34.7761 49.6965C36.3262 48.7895 38.2759 48.7923 39.8234 49.7037C43.4408 51.834 47.2932 54.0782 51.3903 56.4436Z" fill="url(#paint2_linear_435_3054)"/>
+<defs>
+<linearGradient id="paint0_linear_435_3054" x1="50" y1="208" x2="190" y2="212" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6EE7B7"/>
+<stop offset="1" stop-color="#10B981"/>
+</linearGradient>
+<linearGradient id="paint1_linear_435_3054" x1="30" y1="123.992" x2="30" y2="190" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB923C"/>
+<stop offset="1" stop-color="#EA580C"/>
+</linearGradient>
+<linearGradient id="paint2_linear_435_3054" x1="125" y1="147" x2="120" y2="21" gradientUnits="userSpaceOnUse">
+<stop stop-color="#60A5FA"/>
+<stop offset="1" stop-color="#2563EB"/>
+</linearGradient>
+</defs>
+</svg>

+ 51 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Credits',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/credits/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'credits_update_1301_1302',
+
+    'module_dir' => 'boonex/credits/',
+    'module_uri' => 'credits',
+
+    'db_prefix' => 'bx_credits_',
+    'class_prefix' => 'BxCredits',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Credits',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 25 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCreditsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+    
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_credits_history', 'type'))
+                $this->oDb->query("ALTER TABLE `bx_credits_history` ADD `type` varchar(16) NOT NULL default '' AFTER `amount`");
+            if(!$this->oDb->isFieldExists('bx_credits_history', 'cleared'))
+                $this->oDb->query("ALTER TABLE `bx_credits_history` ADD `cleared` int(11) NOT NULL DEFAULT '0' AFTER `date`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 11 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/install/langs/en.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_credits_option_withdraw_clearing"><![CDATA[Clearing period (in days) before received credits can be withdrawn]]></string_add>
+    <string_add name="_bx_credits_option_withdraw_minimum"><![CDATA[Minimum amount of cleared credits which can be withdrawn]]></string_add>
+    <string_add name="_bx_credits_option_withdraw_remaining"><![CDATA[Minimum credits balance after withdrawal]]></string_add>
+	<string_add name="_bx_credits_form_credit_input_sys_cleared"><![CDATA[Cleared Balance]]></string_add>
+    <string_add name="_bx_credits_form_credit_input_cleared"><![CDATA[Cleared Balance]]></string_add>
+	<string_add name="_bx_credits_grid_column_title_htr_cleared"><![CDATA[Clearing]]></string_add>
+	<string_add name="_bx_credits_err_withdraw_minimum"><![CDATA[Withdrawal less then {0} credits isn't available.]]></string_add>
+    <string_add name="_bx_credits_err_withdraw_remaining"><![CDATA[Minimum remaining balance after withdrawal should be more then {0} credits.]]></string_add>
+</resources>

+ 30 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/install/sql/enable.sql

@@ -0,0 +1,30 @@
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_credits' LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name` IN ('bx_credits_withdraw_clearing', 'bx_credits_withdraw_minimum', 'bx_credits_withdraw_remaining');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_credits_withdraw_clearing', '30', @iCategId, '_bx_credits_option_withdraw_clearing', 'digit', '', '', '', 3),
+('bx_credits_withdraw_minimum', '500', @iCategId, '_bx_credits_option_withdraw_minimum', 'digit', '', '', '', 4),
+('bx_credits_withdraw_remaining', '100', @iCategId, '_bx_credits_option_withdraw_remaining', 'digit', '', '', '', 5);
+
+
+-- GRIDS
+UPDATE `sys_grid_fields` SET `width`='15%' WHERE `object`='bx_credits_history_administration' AND `name`='info';
+UPDATE `sys_grid_fields` SET `width`='10%' WHERE `object`='bx_credits_history_administration' AND `name`='date';
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_credits_history_administration' AND `name`='cleared';
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_credits_history_administration', 'cleared', '_bx_credits_grid_column_title_htr_cleared', '10%', 0, '', '', 8);
+
+UPDATE `sys_grid_fields` SET `width`='15%' WHERE `object`='bx_credits_history_common' AND `name`='info';
+UPDATE `sys_grid_fields` SET `width`='10%' WHERE `object`='bx_credits_history_common' AND `name`='date';
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_credits_history_common' AND `name`='cleared';
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_credits_history_common', 'cleared', '_bx_credits_grid_column_title_htr_cleared', '10%', 0, '', '', 7);
+
+
+-- CRONS
+DELETE FROM `sys_cron_jobs` WHERE `name`='bx_credits_clearing';
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_credits_clearing', '0 0 * * *', 'BxCreditsCronClearing', 'modules/boonex/credits/classes/BxCreditsCronClearing.php', '');

+ 8 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/install/sql/install.sql

@@ -0,0 +1,8 @@
+-- FORMS
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_credits_credit' AND `name`='cleared';
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_credits_credit', 'bx_credits', 'cleared', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_cleared', '_bx_credits_form_credit_input_cleared', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', 'Xss', '', 1, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_credits_credit_withdraw_request' AND `input_name`='cleared';
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_credits_credit_withdraw_request', 'cleared', 2147483647, 1, 1);

+ 304 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsConfig.php

@@ -0,0 +1,304 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCreditsConfig extends BxBaseModGeneralConfig
+{
+    protected $_iAuthor;
+    protected $_aCurrency;
+
+    protected $_sCheckoutSessionKey;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'copyright col-green3',
+
+            // database tables
+            'TABLE_BUNDLES' => $aModule['db_prefix'] . 'bundles',
+            'TABLE_ORDERS' => $aModule['db_prefix'] . 'orders',
+            'TABLE_ORDERS_DELETED' => $aModule['db_prefix'] . 'orders_deleted',
+            'TABLE_PROFILES' => $aModule['db_prefix'] . 'profiles',
+            'TABLE_HISTORY' => $aModule['db_prefix'] . 'history',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => '',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => '',
+            'FIELD_NAME' => 'name',
+            'FIELD_TITLE' => 'title',
+            'FIELD_AMOUNT' => 'amount',
+            'FIELD_BONUS' => 'bonus',
+            'FIELD_PRICE' => 'price',
+            'FIELD_STATUS' => 'active',
+
+            'FIELD_C_MESSAGE' => 'message',
+
+            'FIELD_H_ID' => 'id',
+            'FIELD_H_DIRECTION' => 'direction',
+            'FIELD_H_DATE' => 'date',
+            'FIELD_H_CLEARED' => 'cleared',
+
+            // page URIs
+            'URI_HOME' => 'credits-home',
+            'URL_HOME' => 'page.php?i=credits-home',
+            'URL_CHECKOUT' => 'page.php?i=credits-checkout',
+            'URL_ORDERS_COMMON' => 'page.php?i=credits-orders',
+            'URL_ORDERS_ADMINISTRATION' => 'page.php?i=credits-orders-administration',
+            'URL_HISTORY_COMMON' => 'page.php?i=credits-history-common',
+            'URL_HISTORY_ADMINISTRATION' => 'page.php?i=credits-history-administration',
+
+            // some params
+            'PARAM_WITHDRAW' => 'bx_credits_enable_withdraw',
+            'PARAM_WITHDRAW_EMAIL' => 'bx_credits_withdraw_email',
+            'PARAM_WITHDRAW_CLEARING' => 'bx_credits_withdraw_clearing',
+            'PARAM_WITHDRAW_MINIMUM' => 'bx_credits_withdraw_minimum',
+            'PARAM_WITHDRAW_REMAINING' => 'bx_credits_withdraw_remaining',
+            'PARAM_PRECISION' => 'bx_credits_precision',
+            'PARAM_CR_USE' => 'bx_credits_conversion_rate_use',
+            'PARAM_CR_WITHDRAW' => 'bx_credits_conversion_rate_withdraw',
+            'PARAM_PROVIDER_NAME' => 'credits',
+            'PARAM_PROVIDER_ENABLE' => 'bx_credits_enable_provider',
+            'PARAM_CODE' => 'bx_credits_code',
+            'PARAM_ICON' => 'bx_credits_icon',
+
+            // objects
+            'OBJECT_FORM_CREDIT' => 'bx_credits_credit',
+            'OBJECT_FORM_CREDIT_DISPLAY_GRANT' => 'bx_credits_credit_grant',
+            'OBJECT_FORM_CREDIT_DISPLAY_SEND' => 'bx_credits_credit_send',
+            'OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_REQUEST' => 'bx_credits_credit_withdraw_request',
+            'OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_CONFIRM' => 'bx_credits_credit_withdraw_confirm',
+            'OBJECT_FORM_BUNDLE' => 'bx_credits_bundle',
+            'OBJECT_FORM_BUNDLE_DISPLAY_ADD' => 'bx_credits_bundle_add',
+            'OBJECT_FORM_BUNDLE_DISPLAY_EDIT' => 'bx_credits_bundle_edit',
+            'OBJECT_MENU_SUBMENU' => 'bx_credits_submenu', 
+            'OBJECT_MENU_MANAGE_SUBMENU' => 'bx_credits_manage_submenu',
+            'OBJECT_GRID_BUNDLES' => 'bx_credits_bundles',
+            'OBJECT_GRID_ORDERS_ADMINISTRATION' => 'bx_credits_orders_administration',
+            'OBJECT_GRID_ORDERS_COMMON' => 'bx_credits_orders_common',
+            'OBJECT_GRID_HISTORY_ADMINISTRATION' => 'bx_credits_history_administration',
+            'OBJECT_GRID_HISTORY_COMMON' => 'bx_credits_history_common',
+
+            // email templates
+            'ETEMPLATE_GRANTED' => 'bx_credits_granted',
+            'ETEMPLATE_RECEIVED' => 'bx_credits_received',
+            'ETEMPLATE_PURCHASED' => 'bx_credits_purchased',
+            'ETEMPLATE_IN' => 'bx_credits_in',
+            'ETEMPLATE_OUT' => 'bx_credits_out',
+            'ETEMPLATE_WITHDRAW_REQUESTED' => 'bx_credits_withdraw_requested',
+            'ETEMPLATE_WITHDRAW_SENT' => 'bx_credits_withdraw_sent',
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_credits_txt_sample_single',
+                'grant_popup' => '_bx_credits_grid_popup_title_htr_grant',
+                'send_popup' => '_bx_credits_grid_popup_title_htr_send',
+                'withdraw_request_popup' => '_bx_credits_grid_popup_title_htr_withdraw_request',
+                'withdraw_confirm_popup' => '_bx_credits_grid_popup_title_htr_withdraw_confirm',
+            ),
+        );
+
+        $this->_aJsClasses = array_merge($this->_aJsClasses, array(
+            'studio' => 'BxCreditsStudio',
+            'checkout' => 'BxCreditsCheckout',
+            'subscribe' => 'BxCreditsSubscribe',
+            'withdraw' => 'BxCreditsWithdraw',
+        ));
+
+        $this->_aJsObjects = array_merge($this->_aJsObjects, array(
+            'studio' => 'oBxCreditsStudio',
+            'checkout' => 'oBxCreditsCheckout',
+            'subscribe' => 'oBxCreditsSubscribe',
+            'withdraw' => 'oBxCreditsWithdraw',
+        ));
+
+        $sPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'add_bundle_popup' =>  $sPrefix . '-add-bundle-popup',
+            'edit_bundle_popup' =>  $sPrefix . '-edit-bundle-popup',
+
+            'send_popup' =>  $sPrefix . '-send-popup',
+            'grant_popup' =>  $sPrefix . '-grant-popup',
+            'withdraw_request_popup' =>  $sPrefix . '-withdraw-request-popup',
+            'withdraw_confirm_popup' =>  $sPrefix . '-withdraw-confirm-popup',
+            'withdraw_field_rate' => $sPrefix . '-wff-rate',
+            'withdraw_field_amount' => $sPrefix . '-wff-amount',
+            'withdraw_field_result' => $sPrefix . '-wff-result',
+
+            'subscribe_popup' =>  $sPrefix . '-subscribe-popup',
+        );
+
+        $this->_aPrefixes = array(
+            'style' => 'bx-credits',
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $this->_iAuthor = (int)$oPayments->getOption('site_admin');
+        $this->_aCurrency = array(
+            'code' => $oPayments->getOption('default_currency_code'),
+            'sign' => $oPayments->getOption('default_currency_sign')
+        );
+        
+        $this->_sCheckoutSessionKey = $this->_sName . '_checkout';
+    }
+
+    public function getHtmlIds($sKey = '')
+    {
+        if(empty($sKey))
+            return $this->_aHtmlIds;
+
+        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
+    }
+
+    public function getAuthor()
+    {
+    	return $this->_iAuthor;
+    }
+
+    public function getCurrency()
+    {
+    	return $this->_aCurrency;
+    }
+
+    public function isWithdraw()
+    {
+        return getParam($this->CNF['PARAM_WITHDRAW']) == 'on';
+    }
+
+    public function getWithdrawEmail()
+    {
+        $sEmail = getParam($this->CNF['PARAM_WITHDRAW_EMAIL']);
+        if(empty($sEmail))
+            $sEmail = getParam('site_email');
+
+        return $sEmail;
+    }
+
+    public function getWithdrawClearing()
+    {
+        return (int)getParam($this->CNF['PARAM_WITHDRAW_CLEARING']);
+    }
+
+    public function getTransferTypesForClearing()
+    {
+        return [
+            BX_CREDITS_TRANSFER_TYPE_PURCHASE,
+            BX_CREDITS_TRANSFER_TYPE_CHECKOUT,
+            BX_CREDITS_TRANSFER_TYPE_GRANT,
+            BX_CREDITS_TRANSFER_TYPE_SEND,
+            BX_CREDITS_TRANSFER_TYPE_SERVICE
+        ];
+    }
+
+    public function getTransferTypesForSpending()
+    {
+        return [
+            BX_CREDITS_TRANSFER_TYPE_CHECKOUT,
+            BX_CREDITS_TRANSFER_TYPE_SEND,
+            BX_CREDITS_TRANSFER_TYPE_SERVICE
+        ];
+    }
+
+    public function getPrecision()
+    {
+        return (int)getParam($this->CNF['PARAM_PRECISION']);
+    }
+
+    public function getConversionRateUse()
+    {
+        return $this->_getConversionRate('use');
+    }
+
+    public function getConversionRateWithdraw()
+    {
+        return $this->_getConversionRate('withdraw');
+    }
+
+    public function getCheckoutUrl()
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->CNF['URL_CHECKOUT']);
+    }
+
+    public function getBundleUrl($aBundle)
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->CNF['URL_HOME']);
+    }
+
+    public function getBundleName($sName)
+    {
+        return uriGenerate($sName, $this->CNF['TABLE_BUNDLES'], $this->CNF['FIELD_NAME'], 'cat', '_');
+    }
+
+    public function getBundleDescription($aBundle)
+    {
+        if(empty($aBundle[$this->CNF['FIELD_BONUS']]))
+            return $aBundle[$this->CNF['FIELD_AMOUNT']];
+
+        return _t('_bx_credits_txt_n_plus_m_for_free', $aBundle[$this->CNF['FIELD_AMOUNT']], $aBundle[$this->CNF['FIELD_BONUS']]);
+    }
+
+    public function getCheckoutData()
+    {
+        return BxDolSession::getInstance()->getUnsetValue($this->_sCheckoutSessionKey);
+    }
+
+    public function setCheckoutData($aData)
+    {
+        return BxDolSession::getInstance()->setValue($this->_sCheckoutSessionKey, $aData);
+    }
+
+    public function getOrder($iLength = 16)
+    {
+        return strtoupper(genRndPwd($iLength, false));
+    }
+
+    /**
+     * Convert Credits to Money
+     */
+    public function convertC2M($fCredits, $fRate = false, $iPrecision = false)
+    {
+        if($fRate === false)
+            $fRate = $this->getConversionRateUse();
+        if($iPrecision === false)
+            $iPrecision = $this->getPrecision();
+
+        return round((float)$fCredits * $fRate, $iPrecision);
+    }
+
+    /**
+     * Convert Money to Credits
+     */
+    public function convertM2C($fMoney, $fRate = false, $iPrecision = false)
+    {
+        if($fRate === false)
+            $fRate = $this->getConversionRateUse();
+        if($iPrecision === false)
+            $iPrecision = $this->getPrecision();
+
+        return round((float)$fMoney / $fRate, $iPrecision);
+    }
+
+    /*
+     * Internal methods
+     */
+    protected function _getConversionRate($sType)
+    {
+        $fRate = (float)getParam($this->CNF['PARAM_CR_' . strtoupper($sType)]);
+
+        return $fRate > 0 && $fRate <= 1 ? $fRate : 1;
+    }
+}
+
+/** @} */

+ 31 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsCronClearing.php

@@ -0,0 +1,31 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCreditsCronClearing extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+    	$this->_sModule = 'bx_credits';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    function processing()
+    {
+        $this->_oModule->processClearing();
+    }
+}
+
+/** @} */

+ 395 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsDb.php

@@ -0,0 +1,395 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Module database queries
+ */
+class BxCreditsDb extends BxBaseModGeneralDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+
+    /**
+     * Bundle related methods.
+     */
+    public function getBundle($aParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "`tb`.*";
+    	$sJoinClause = $sWhereClause = $sLimitClause = "";
+        $sOrderClause = "`tb`.`order` ASC";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tb`.`id`=:id";
+                break;
+
+            case 'order_max':
+            	$aMethod['name'] = 'getOne';
+
+                $sSelectClause = "IFNULL(MAX(`tb`.`order`), 0)";
+                break;
+
+            case 'all':
+                break;
+        }
+
+        if(isset($aParams['active']))
+            $sWhereClause .= $this->prepareAsString(" AND `tb`.`active`=?", (bool)$aParams['active'] ? 1 : 0);
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : "";
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : "";
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_BUNDLES'] . "` AS `tb`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function isBundle($iId)
+    {
+        $aSport = $this->getBundle(array('type' => 'id', 'id' => $iId));
+        return !empty($aSport) && is_array($aSport);
+    }
+
+    public function insertBundle($aSet)
+    {
+        $sQuery = "INSERT INTO `" . $this->_oConfig->CNF['TABLE_BUNDLES'] . "` SET " . $this->arrayToSQL($aSet);
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function updateBundle($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_BUNDLES'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function deleteBundle($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_BUNDLES'] . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ');
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    /**
+     * Order related methods.
+     */
+    public function getOrder($aParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "`to`.*";
+    	$sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `to`.`id`=:id";
+                break;
+
+            case 'row_by':
+                $aMethod['name'] = 'getRow';
+                $sWhereClause = " AND " . $this->arrayToSQL($aParams['by'], ' AND ');
+                break;
+
+            case 'all':
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : "";
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : "";
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_ORDERS'] . "` AS `to`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function isOrder($iId)
+    {
+        $aOrder = $this->getOrder(array('type' => 'id', 'id' => $iId));
+        return !empty($aOrder) && is_array($aOrder);
+    }
+
+    public function isOrderByPbo($iProfileId, $iBundleId, $sOrder)
+    {
+        $aOrder = $this->getOrder(array('type' => 'row_by', 'by' => array('profile_id' => $iProfileId, 'bundle_id' => $iBundleId, 'order' => $sOrder)));
+        return !empty($aOrder) && is_array($aOrder);
+    }
+
+    public function insertOrder($aSet, $sSetAddon = '')
+    {
+        $sQuery = "INSERT INTO `" . $this->_oConfig->CNF['TABLE_ORDERS'] . "` SET " . $this->arrayToSQL($aSet) . $sSetAddon;
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function insertOrderDeleted($aSet, $sSetAddon = '')
+    {
+        $sQuery = "INSERT INTO `" . $this->_oConfig->CNF['TABLE_ORDERS_DELETED'] . "` SET " . $this->arrayToSQL($aSet) . $sSetAddon;
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function registerOrder($iProfileId, $iBundleId, $iCount, $sOrder, $sLicense, $sType, $sDuration = '', $iTrial = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sSetAddon = ', `added`=UNIX_TIMESTAMP()';
+
+        return $this->insertOrder(array(
+            'profile_id' => $iProfileId,
+            'bundle_id' => $iBundleId,
+            'count' => $iCount,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType
+        ), $sSetAddon);
+    }
+
+    public function updateOrder($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_ORDERS'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    /**
+     * Note. Prolong isn't allowed for now.
+     */
+    public function prolongOrder($iProfileId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial)
+    {
+        return false;
+    }
+
+    public function deleteOrder($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_ORDERS'] . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ');
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function unregisterOrder($iProfileId, $iItemId, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOrder = $this->getOrder(array('type' => 'row_by', 'by' => array(
+            'profile_id' => $iProfileId,
+            'bundle_id' => $iItemId,
+            'order' => $sOrder,
+            'license' => $sLicense
+    	)));
+
+        if(empty($aOrder) || !is_array($aOrder))
+            return true;
+
+        //--- Move to deleted orders table with 'refund' as reason.
+        $this->insertOrderDeleted($aOrder, ", `reason`='refund', `deleted`=UNIX_TIMESTAMP()");
+
+        return $this->deleteOrder(array('id' => $aOrder[$CNF['FIELD_ID']]));
+    }
+
+    /**
+     * Profile related methods.
+     */
+    public function getProfile($aParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "`tp`.*";
+    	$sJoinClause = $sWhereClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tp`.`id`=:id";
+                break;
+            
+            case 'balance':
+            	$aMethod['name'] = 'getOne';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sSelectClause = "`tp`.`balance`";
+                $sWhereClause = " AND `tp`.`id`=:id";
+                break;
+        }
+
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_PROFILES'] . "` AS `tp`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function isProfile($iId)
+    {
+        $aProfile = $this->getProfile(array('type' => 'id', 'id' => $iId));
+        return !empty($aProfile) && is_array($aProfile);
+    }
+
+    public function insertProfile($aSet)
+    {
+        $sQuery = "INSERT INTO `" . $this->_oConfig->CNF['TABLE_PROFILES'] . "` SET " . $this->arrayToSQL($aSet);
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function updateProfile($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_PROFILES'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function updateProfileBalance($iId, $fAmount, $bCleared = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sBalance = $bCleared ? 'cleared' : 'balance';
+
+        if(!$this->isProfile($iId))
+            return $this->insertProfile(['id' => $iId, $sBalance => $fAmount]);
+
+        $sQuery = "UPDATE `" . $CNF['TABLE_PROFILES'] . "` SET `" . $sBalance . "`=`" . $sBalance . "`+:amount WHERE `id`=:id";
+        return (int)$this->query($sQuery, [
+            'id' => $iId,
+            'amount' => $fAmount
+        ]) > 0;
+    }
+
+    public function deleteProfile($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_PROFILES'] . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ');
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    /**
+     * History related methods.
+     */
+    public function getHistory($aParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+    	$aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+
+    	$sSelectClause = "`th`.*";
+    	$sJoinClause = $sWhereClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'cleared':
+                $aMethod['name'] = 'getOne';
+                $aMethod['params'][1] = [
+                    'profile' => $aParams['profile']
+                ];
+
+                $sSelectClause = "SUM(`th`.`amount`)";
+                $sWhereClause = " AND `th`.`first_pid`=:profile AND `th`.`direction`='in' AND `th`.`type` IN (" . $this->implode_escape($this->_oConfig->getTransferTypesForClearing()) . ") AND `th`.`cleared`<>'0'";
+                break;
+
+            case 'spent':
+                $aMethod['name'] = 'getOne';
+                $aMethod['params'][1] = [
+                    'profile' => $aParams['profile'],
+                    'type_cancel' => BX_CREDITS_TRANSFER_TYPE_CANCELLATION
+                ];
+
+                $sSelectClause = "SUM(`th`.`amount`)";
+                $sJoinClause = " LEFT JOIN `" . $CNF['TABLE_HISTORY'] . "` AS `thc` ON `th`.`order`=`thc`.`order` AND `thc`.`type`=:type_cancel";
+                $sWhereClause = " AND `th`.`first_pid`=:profile AND `th`.`direction`='out' AND `th`.`type` IN (" . $this->implode_escape($this->_oConfig->getTransferTypesForSpending()) . ") AND ISNULL(`thc`.`id`)";
+                break;
+
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause = " AND `th`.`id`=:id";
+                break;
+
+            case 'row_by':
+                $aMethod['name'] = 'getRow';
+                $sWhereClause = " AND " . $this->arrayToSQL($aParams['by'], ' AND ');
+                break;
+
+            case 'clearing':
+                $aMethod['params'][1] = [
+                    'clearing' => $aParams['clearing']
+                ];
+
+                $sWhereClause = " AND `th`.`direction`='in' AND `th`.`type` IN (" . $this->implode_escape($this->_oConfig->getTransferTypesForClearing()) . ") AND `th`.`date` < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL :clearing DAY)) AND `th`.`cleared`='0'";
+                break;
+        }
+
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_HISTORY'] . "` AS `th`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function isHistory($iId)
+    {
+        $aHistory = $this->getHistory(array('type' => 'id', 'id' => $iId));
+        return !empty($aHistory) && is_array($aHistory);
+    }
+
+    public function insertHistory($aSet)
+    {
+        $sQuery = "INSERT INTO `" . $this->_oConfig->CNF['TABLE_HISTORY'] . "` SET " . $this->arrayToSQL($aSet);
+        return (int)$this->query($sQuery) > 0 ? $this->lastId() : false;
+    }
+
+    public function updateHistory($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_HISTORY'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function deleteHistory($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_HISTORY'] . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ');
+        return (int)$this->query($sQuery) > 0;
+    }
+}
+
+/** @} */

+ 121 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsFormCredit.php

@@ -0,0 +1,121 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Credit form
+ */
+class BxCreditsFormCredit extends BxTemplFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_fRate;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_credits';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $this->_fRate = $this->_oModule->_oConfig->getConversionRateWithdraw();
+
+        if(isset($this->aInputs[$CNF['FIELD_C_MESSAGE']])) {
+            $sInfo = '_bx_credits_form_credit_input_message_inf_';
+            switch($this->aParams['display']) {
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_GRANT']:
+                    $sInfo .= 'g';
+                    break;
+
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_SEND']:
+                    $sInfo .= 's';
+                    break;
+
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_REQUEST']:
+                    $sInfo .= 'wr';
+                    break;
+                
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_CONFIRM']:
+                    $sInfo .= 'wc';
+                    break;
+            }
+
+            $this->aInputs[$CNF['FIELD_C_MESSAGE']]['info'] = _t($sInfo);
+        }
+    }
+
+    protected function genCustomRowRate(&$aInput)
+    {
+        if($this->_fRate == 1)
+            return '';
+
+        return $this->genRowStandard($aInput);
+    }
+
+    protected function genCustomRowResult(&$aInput)
+    {
+        if($this->_fRate == 1)
+            return '';
+
+        return $this->genRowStandard($aInput);
+    }
+
+    protected function genCustomInputBalance(&$aInput)
+    {
+        $aInput['value'] = $this->_oModule->getProfileBalance();
+
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputCleared(&$aInput)
+    {
+        $aInput['value'] = $this->_oModule->getProfileBalanceCleared();
+
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputRate(&$aInput)
+    {
+        $aInput['value'] = $this->_fRate;
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_rate');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputAmount(&$aInput)
+    {
+        if($this->_fRate != 1)
+            $aInput['attrs']['onblur'] = $this->_oModule->_oConfig->getJsObject('withdraw') . '.getResult(this)';
+
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_amount');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputResult(&$aInput)
+    {
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_result');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputProfile(&$aInput)
+    {
+        if(empty($aInput['custom']) || !is_array($aInput['custom']))
+            $aInput['custom'] = array();
+        $aInput['custom']['only_once'] = 1;
+
+        $aInput['ajax_get_suggestions'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . "get_profiles";
+
+        return $this->genCustomInputUsernamesSuggestions($aInput);
+    }
+}
+
+/** @} */

+ 206 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsGridHistoryAdministration.php

@@ -0,0 +1,206 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxCreditsGridHistoryAdministration extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iUserId;
+    protected $_bWithdraw;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_credits';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+    	if(!$oTemplate)
+            $oTemplate = $this->_oModule->_oTemplate;
+
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+
+        $iUserId = bx_get_logged_profile_id();
+        if($iUserId !== false) {
+            $this->_iUserId = (int)$iUserId;
+            $this->_aQueryAppend['user_id'] = $this->_iUserId;
+        }
+
+        $this->_bWithdraw = $this->_oModule->_oConfig->isWithdraw();
+    }
+
+    public function getCode($isDisplayHeader = true)
+    {
+        $sResult = parent::getCode($isDisplayHeader);
+        if(!empty($sResult) && $isDisplayHeader)
+            $sResult = $this->_oModule->_oTemplate->getJsCode('withdraw') . $sResult;
+
+        return $sResult;
+    }
+
+    public function performActionGrant()
+    {
+        $sAction = 'grant';
+
+        $this->_performActionWithProfileAmount($sAction);
+    }
+
+    public function performActionWithdrawConfirm()
+    {
+        if(!$this->_bWithdraw)
+            return echoJson([]);
+
+        $sAction = 'withdraw_confirm';
+
+        $this->_performActionWithProfileAmount($sAction);
+    }
+
+    protected function _getActionWithdrawConfirm($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if(!$this->_bWithdraw)
+            $isDisabled = true;
+
+        return  parent::_getActionDefault($sType, $sKey, $a, false, $isDisabled, $aRow);
+    }
+
+    protected function _getCellDirection($mixedValue, $sKey, $aField, $aRow)
+    {
+        if(in_array($mixedValue, [BX_CREDITS_DIRECTION_IN, BX_CREDITS_DIRECTION_OUT]))
+            $mixedValue = _t('_bx_credits_txt_direction_' . $mixedValue);
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellFirstPid($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_getProfile($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellSecondPid($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_getProfile($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAmount($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($this->_oModule->convertC2S($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellOrder($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellDate($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue, BX_FORMAT_DATE, true), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellCleared($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if($aRow[$CNF['FIELD_H_DIRECTION']] == BX_CREDITS_DIRECTION_IN) {
+            if(empty($mixedValue)) {
+                $iPeriod = $this->_oModule->_oConfig->getWithdrawClearing();
+                if($iPeriod == 0)
+                    $iPeriod = 1;
+
+                $oDate = date_create('@' . $aRow[$CNF['FIELD_H_DATE']]);
+                date_add($oDate, new DateInterval('P' . $iPeriod . 'D'));
+                $mixedValue = date_format($oDate, 'U');
+            }
+
+            $mixedValue = bx_time_js($mixedValue, BX_FORMAT_DATE, true);
+        }
+        else 
+            $mixedValue = '';
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getProfile($mixedValue) 
+    {
+        if(is_numeric($mixedValue) && (int)$mixedValue == 0)
+            $mixedValue = $this->_oModule->_oConfig->getAuthor();
+
+        $oProfile = BxDolProfile::getInstanceMagic($mixedValue);
+        if(!$oProfile)
+            return $mixedValue;
+
+        return $oProfile->getUnit(0, ['template' => ['name' => 'unit', 'size' => 'icon']]);
+    }
+
+    protected function _performActionWithProfileAmount($sAction)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $iProfile = (int)$oForm->getCleanValue('profile');
+            $fAmount = (float)$oForm->getCleanValue('amount');
+            $sMessage = $oForm->getCleanValue('message');
+            $aResult = $this->_oModule->{'process' . bx_gen_method_name($sAction)}($this->_iUserId, $iProfile, $fAmount, $sMessage);
+
+            if((int)$aResult['code'] == 0) {
+                if(!empty($aResult['id']))
+                    $aRes = ['grid' => $this->getCode(false), 'blink' => $aResult['id']];
+                else
+                    $aRes = ['msg' => _t(!empty($aResult['msg']) ? $aResult['msg'] : '_bx_credits_msg_action_performed')];
+            }
+            else
+                $aRes = ['msg' => _t(!empty($aResult['msg']) ? $aResult['msg'] : '_bx_credits_err_cannot_perform_action')];
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplFunctions::getInstance()->popupBox($this->_oModule->_oConfig->getHtmlIds($sAction . '_popup'), _t($CNF['T'][$sAction . '_popup']), $this->_oModule->_oTemplate->parseHtmlByName('credit_form.html', [
+                'form_id' => $oForm->aFormAttrs['id'],
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            ]));
+
+            echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+        }
+    }
+
+    protected function _getFormObject($sAction)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_CREDIT'], $CNF['OBJECT_FORM_CREDIT_DISPLAY_' . strtoupper($sAction)]);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
+
+        return $oForm;
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+        $this->_oModule->_oTemplate->addJs([
+            'jquery.form.min.js', 
+            'withdraw.js'
+        ]);
+
+        $this->_oModule->_oTemplate->addCss([
+            'main.css',
+            'withdraw.css'
+        ]);
+
+        $oForm = new BxTemplFormView([]);
+        $oForm->addCssJs();
+    }
+}
+
+/** @} */

+ 1093 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/classes/BxCreditsModule.php

@@ -0,0 +1,1093 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_CREDITS_TRANSFER_TYPE_PURCHASE', 'purchase');
+define('BX_CREDITS_TRANSFER_TYPE_CHECKOUT', 'checkout');
+define('BX_CREDITS_TRANSFER_TYPE_CANCELLATION', 'cancellation');
+define('BX_CREDITS_TRANSFER_TYPE_GRANT', 'grant');
+define('BX_CREDITS_TRANSFER_TYPE_SEND', 'send');
+define('BX_CREDITS_TRANSFER_TYPE_WITHDRAW', 'withdraw');
+define('BX_CREDITS_TRANSFER_TYPE_SERVICE', 'service');
+
+define('BX_CREDITS_DIRECTION_IN', 'in');
+define('BX_CREDITS_DIRECTION_OUT', 'out');
+
+define('BX_CREDITS_ORDER_TYPE_SINGLE', 'single'); //--- one-time payment
+define('BX_CREDITS_ORDER_TYPE_RECURRING', 'recurring'); //--- recurring payment (subscription)
+
+
+class BxCreditsModule extends BxBaseModGeneralModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function actionGetProfiles()
+    {
+        $sTerm = bx_get('term');
+
+        $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
+
+        echoJson($a);
+    }
+
+    public function actionCheckBundleName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$sName = bx_process_input(bx_get('name'));
+    	if(empty($sName))
+            return echoJson(array());
+
+        $sResult = '';
+
+        $iId = (int)bx_get('id');
+        if(!empty($iId)) {
+            $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iId)); 
+            if(strcmp($sName, $aBundle[$CNF['FIELD_NAME']]) == 0) 
+                $sResult = $sName;
+        }
+
+    	echoJson(array(
+            'name' => !empty($sResult) ? $sResult : $this->_oConfig->getBundleName($sName)
+    	));
+    }
+
+    public function actionCheckout()
+    {
+        $iBuyerId = bx_get_logged_profile_id();
+        if(!$iBuyerId)
+            return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
+
+        $aData = $this->_oConfig->getCheckoutData();
+        if(empty($aData) || !is_array($aData))
+            return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
+
+        $iSellerId = (int)$aData['seller'];
+        $fAmount = (float)$aData['amount'];
+
+        $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
+        if($fAmount > $fBalance)
+            return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
+
+        $sOrder = $this->_oConfig->getOrder();
+        $sInfo = '_bx_credits_txt_history_info_checkout';
+        $sData = serialize(array(
+            'conversion' => $this->_oConfig->getConversionRateUse(),
+            'precision' => $this->_oConfig->getPrecision()
+        ));
+
+        $this->updateProfileBalance($iBuyerId, $iSellerId, -$fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo, $sData);
+        $this->updateProfileBalance($iSellerId, $iBuyerId, $fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo, $sData);
+
+        bx_alert($this->getName(), 'checkout', 0, false, array(
+            'seller' => $iSellerId,
+            'buyer' => $iBuyerId,
+            'amount' => $fAmount, 
+            'order' => $sOrder
+        ));
+
+        return echoJson(array(
+            'code' => 0,
+            'redirect' => bx_append_url_params($aData['return_data_url'], array('o' => $sOrder, 'c' => $aData['custom']))
+        ));
+    }
+
+    public function actionSubscribe()
+    {
+        $iBuyerId = bx_get_logged_profile_id();
+        if(!$iBuyerId)
+            return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
+
+        $aData = $this->_oConfig->getCheckoutData();
+        if(empty($aData) || !is_array($aData))
+            return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
+
+        $iSellerId = (int)$aData['seller'];
+        $fAmount = (float)$aData['amount'];
+
+        $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
+        if($fAmount > $fBalance)
+            return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
+
+        $sUnique = $this->_oConfig->getOrder(9);
+        $sCustomer = 'bx_cus_' . $sUnique;
+        $sSubscription = 'bx_sub_' . $sUnique;
+
+        bx_alert($this->getName(), 'subscribe', 0, false, array(
+            'seller' => $iSellerId,
+            'buyer' => $iBuyerId,
+            'amount' => $fAmount, 
+            'trial' => $aData['trial'],
+            'customer' => $sCustomer,
+            'subscription' => $sSubscription
+        ));
+
+        return echoJson(array(
+            'code' => 0,
+            'redirect' => bx_append_url_params($aData['return_data_url'], array(
+                'cs' => $sCustomer, 
+                'sb' => $sSubscription,
+                'tr' => $aData['trial'],
+                'c' => $aData['custom']
+            ))
+        ));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'GetBlockBundles' => '',
+            'GetBlockOrders' => '',
+            'GetBlockHistory' => '',
+        );
+    }
+
+    public function serviceGetCheckoutUrl()
+    {
+        return $this->_oConfig->getCheckoutUrl();
+    }
+
+    public function serviceValidateCheckout($iSeller, $iBuyer, $fAmount, $sOrder)
+    {
+        $fAmount = (float)$fAmount;
+
+        $aOut = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iBuyer, 'direction' => BX_CREDITS_DIRECTION_OUT, 'order' => $sOrder)));
+        if(empty($aOut) || !is_array($aOut) || (int)$aOut['second_pid'] != (int)$iSeller)
+            return false;
+        
+        $aDataOut = unserialize($aOut['data']);
+        if($this->_oConfig->convertM2C($fAmount, $aDataOut['conversion'], $aDataOut['precision']) != (float)$aOut['amount'])
+            return false;
+
+        $aIn = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iSeller, 'direction' => BX_CREDITS_DIRECTION_IN, 'order' => $sOrder)));
+        if(empty($aIn) || !is_array($aIn) || (int)$aIn['second_pid'] != (int)$iBuyer)
+            return false;
+
+        $aDataIn = unserialize($aIn['data']);
+        if($this->_oConfig->convertM2C($fAmount, $aDataIn['conversion'], $aDataIn['precision']) != (float)$aIn['amount'])
+            return false;
+
+        return true;
+    }
+
+    public function serviceGetBlockCheckout()
+    {
+        $oBuyer = BxDolProfile::getInstance();
+        if(!$oBuyer)
+            return MsgBox(_t('_bx_credits_err_unknown_buyer'));
+        
+        $iSeller = (int)bx_get('seller');
+        $oSeller = BxDolProfile::getInstance($iSeller);
+        if(!$oSeller)
+            return MsgBox(_t('_bx_credits_err_unknown_seller'));
+
+        $fAmountM = (float)bx_get('amount');
+        $fAmountC = $this->_oConfig->convertM2C($fAmountM);
+
+        $aData = array(
+            'seller' => $iSeller,
+            'currency' => array(
+                'code' => bx_process_input(bx_get('currency_code')),
+                'sign' => bx_process_input(bx_get('currency_sign')),
+            ),
+            'amountm' => $fAmountM,
+            'amountc' => $fAmountC
+        );
+
+        $iItemsCount = (int)bx_get('items_count');
+        for($i = 0; $i < $iItemsCount; $i++) {
+            $aData['items'][] = array(
+                'title' => bx_process_input(bx_get('item_title_' . $i)),
+                'quantity' => (int)bx_get('item_quantity_' . $i)
+            );
+        }
+
+        $this->_oConfig->setCheckoutData(array(
+            'seller' => $iSeller,
+            'amount' => $fAmountC,
+            'custom' => bx_process_input(bx_get('custom')),
+            'return_data_url' => bx_process_input(bx_get('return_data_url')),
+        ));
+        return $this->_oTemplate->getBlockCheckout($oBuyer, $oSeller, $aData);
+    }
+
+    public function serviceGetPopupSubscribe($aData)
+    {
+        $oBuyer = BxDolProfile::getInstance();
+        if(!$oBuyer)
+            return array('msg' => _t('_bx_credits_err_unknown_buyer'));
+
+        $iSeller = (int)$aData['seller'];
+        $oSeller = BxDolProfile::getInstance($iSeller);
+        if(!$oSeller)
+            return array('msg' => _t('_bx_credits_err_unknown_seller'));
+
+        $fAmountM = (float)$aData['amount'];
+        $fAmountC = $this->_oConfig->convertM2C($fAmountM);
+
+        $aData = array_merge($aData, array(
+            'amountm' => $fAmountM,
+            'amountc' => $fAmountC
+        ));
+
+        $this->_oConfig->setCheckoutData(array(
+            'seller' => $iSeller,
+            'amount' => $fAmountC,
+            'trial' => (int)$aData['trial'] > 0,
+            'custom' => bx_process_input($aData['custom']),
+            'return_data_url' => bx_process_input($aData['return_data_url']),
+        ));
+        return $this->_oTemplate->getPopupSubscribe($oBuyer, $oSeller, $aData);
+    }
+
+    public function serviceGetMenuItemAddonAmount()
+    {
+        $iProfileId = bx_get_logged_profile_id();
+        if(!$iProfileId)
+            return '';
+
+        return array(
+            'unit' => $this->_oTemplate->getUnit(), 
+            'value' => $this->convertC2S($this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId)), false)
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_bundles get_block_bundles
+     * 
+     * @code bx_srv('bx_credits', 'get_block_bundles'); @endcode
+     * 
+     * Get page block with bundles
+     * 
+     * @see BxCreditsModule::serviceGetBlockBundles
+     */
+    /** 
+     * @ref bx_credits-get_block_bundles "get_block_bundles"
+     */
+    public function serviceGetBlockBundles()
+    {
+        return $this->_oTemplate->getBlockBundles();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_orders_note get_block_orders_note
+     * 
+     * @code bx_srv('bx_credits', 'get_block_orders_note', [...]); @endcode
+     * 
+     * Get page block with a notice for orders usage.
+     *
+     * @return HTML string with block content to display on the site.
+     * 
+     * @see BxCreditsModule::serviceBlockLicensesNote
+     */
+    /** 
+     * @ref bx_credits-get_block_orders_note "get_block_orders_note"
+     */
+    public function serviceGetBlockOrdersNote()
+    {
+        return MsgBox(_t('_bx_credits_page_block_content_orders_common_note'));
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-block_orders get_block_orders
+     * 
+     * @code bx_srv('bx_credits', 'get_block_orders', [...]); @endcode
+     * 
+     * Get page block with a list of orders purchased by currently logged member.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxCreditsModule::serviceBlockLicenses
+     */
+    /** 
+     * @ref bx_credits-get_block_orders "get_block_orders"
+     */
+    public function serviceGetBlockOrders($sType = 'common') 
+    {
+        return $this->_getBlockOrders($sType);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_history get_block_history
+     * 
+     * @code bx_srv('bx_credits', 'get_block_history', [...]); @endcode
+     * 
+     * Get page block with a list of all changes with credits.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxCreditsModule::serviceGetBlockHistory
+     */
+    /** 
+     * @ref bx_credits-get_block_history "get_block_history"
+     */
+    public function serviceGetBlockHistory($sType = 'common') 
+    {
+        return $this->_getBlockHistory($sType);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_credits', 'get_payment_data', [...]); @endcode
+     * 
+     * Get an array with module's description. Is needed for payments processing module.
+     * 
+     * @return an array with module's description.
+     * 
+     * @see BxCreditsModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_credits-get_payment_data "get_payment_data"
+     */
+    public function serviceGetPaymentData()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $aResult = $this->_aModule;
+        $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_COMMON'], array('filter' => '{order}'));
+        $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_ADMINISTRATION'], array('filter' => '{order}'));
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'get_cart_item', [...]); @endcode
+     * 
+     * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
+     * 
+     * @param $iItemId product's ID.
+     * @return an array with prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_credits-get_cart_item "get_cart_item"
+     */
+    public function serviceGetCartItem($iItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$iItemId)
+            return array();
+
+        $aItem = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        return array (
+            'id' => $aItem[$CNF['FIELD_ID']],
+            'author_id' => $this->_oConfig->getAuthor(),
+            'name' => $aItem[$CNF['FIELD_NAME']],
+            'title' => _t($aItem[$CNF['FIELD_TITLE']]),
+            'description' => $this->_oConfig->getBundleDescription($aItem),
+            'url' => $this->_oConfig->getBundleUrl($aItem),
+            'price_single' => $aItem[$CNF['FIELD_PRICE']],
+            'price_recurring' => '',
+            'period_recurring' => 1,
+            'period_unit_recurring' => '',
+            'trial_recurring' => ''
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_credits', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iSellerId seller ID.
+     * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
+     * 
+     * @see BxCreditsModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_credits-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iAuthorId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iAuthorId = $this->_oConfig->getAuthor();
+        $aItems = $this->_oDb->getBundle(array('type' => 'all', 'active' => 1));
+
+        $aResult = array();
+        foreach($aItems as $aItem)
+            $aResult[] = array(
+                'id' => $aItem[$CNF['FIELD_ID']],
+                'author_id' => $iAuthorId,
+                'name' => $aItem[$CNF['FIELD_NAME']],
+                'title' => _t($aItem[$CNF['FIELD_TITLE']]),
+                'description' => $this->_oConfig->getBundleDescription($aItem),
+                'url' => $this->_oConfig->getBundleUrl($aItem),
+                'price_single' => $aItem[$CNF['FIELD_PRICE']],
+                'price_recurring' => '',
+                'period_recurring' => 1,
+                'period_unit_recurring' => '',
+                'trial_recurring' => ''
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Credits module. Is called with payment processing module after the payment was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_credits-register_cart_item "register_cart_item"
+     */
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-register_subscription_item register_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'register_subscription_item', [...]); @endcode
+     * 
+     * Register a processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceRegisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-register_subscription_item "register_subscription_item"
+     */
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-reregister_cart_item reregister_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'reregister_cart_item', [...]); @endcode
+     * 
+     * Reregister a single time payment inside the Credits module. Is called with payment processing module after the payment was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceReregisterCartItem
+     */
+    /** 
+     * @ref bx_credits-reregister_cart_item "reregister_cart_item"
+     */
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-reregister_subscription_item reregister_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'reregister_subscription_item', [...]); @endcode
+     * 
+     * Reregister a subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceReregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-reregister_subscription_item "reregister_subscription_item"
+     */
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Credits module. Is called with payment processing module after the payment was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the payment was unregistered or not.
+     * 
+     * @see BxCreditsModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_credits-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-unregister_subscription_item unregister_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'unregister_subscription_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the subscription was unregistered or not.
+     * 
+     * @see BxCreditsModule::serviceUnregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-unregister_subscription_item "unregister_subscription_item"
+     */
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING); 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-cancel_subscription_item cancel_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'cancel_subscription_item', [...]); @endcode
+     * 
+     * Cancel an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was canceled there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return boolean value determining where the subscription was canceled or not.
+     * 
+     * @see BxCreditsModule::serviceCancelSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-cancel_subscription_item "cancel_subscription_item"
+     */
+    public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	return true;
+    }
+
+    public function serviceGetProfileBalance($iProfileId = 0)
+    {
+        return $this->getProfileBalance($iProfileId);
+    }
+
+    public function serviceUpdateProfileBalance($iFirstPid, $fAmount, $iSecondPid = 0, $sOrder = '', $sInfo = '')
+    {
+        if(empty($sInfo))
+            $sInfo = '_bx_credits_txt_history_info_service';
+
+        return $this->updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, BX_CREDITS_TRANSFER_TYPE_SERVICE, $sOrder, $sInfo);
+    }
+    
+    public function serviceMakePayment($iBuyerPid, $fAmount, $iSellerPid, $sOrder = '')
+    {
+        $sInfo = '_bx_credits_txt_history_info_checkout';
+
+        if(!$this->updateProfileBalance($iBuyerPid, $iSellerPid, -$fAmount, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sOrder, $sInfo))
+            return false;
+
+        if(!$this->updateProfileBalance($iSellerPid, $iBuyerPid, $fAmount, $sOrder, BX_CREDITS_TRANSFER_TYPE_CHECKOUT, $sInfo)) {
+            $this->updateProfileBalance($iBuyerPid, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_CANCELLATION, $sOrder, '_bx_credits_txt_history_info_cancellation');
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Delete all content by profile 
+     * @param $iProfileId profile id 
+     * @return number of deleted items
+     */
+    public function serviceDeleteEntitiesByAuthor ($iProfileId)
+    {
+        $this->_oDb->deleteProfile(array('id' => $iProfileId));
+        $this->_oDb->deleteHistory(array('first_pid' => $iProfileId));
+    }
+
+
+    /*
+     * Common methods
+     */
+    public function convertC2S($fCredits, $bWithUnit = true)
+    {
+        $sResult = '';
+        if($bWithUnit)
+            $sResult .= $this->_oTemplate->getUnit();
+
+        $iPrecision = $this->_oConfig->getPrecision();
+        $sResult .= sprintf("%01." . $iPrecision . "f", round((float)$fCredits, $iPrecision));
+
+        return $sResult;
+    }
+
+    public function getProfileBalance($iProfileId = 0)
+    {
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id();
+
+        if(empty($iProfileId))
+            return 0;
+
+        return (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId));
+    }
+
+    public function getProfileBalanceCleared($iProfileId = 0)
+    {
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id();
+
+        if(empty($iProfileId))
+            return 0;
+
+        $fCleared = (float)$this->_oDb->getHistory(['type' => 'cleared', 'profile' => $iProfileId]);
+        $fSpent = (float)$this->_oDb->getHistory(['type' => 'spent', 'profile' => $iProfileId]);
+
+        return $fCleared > $fSpent ? $fCleared - $fSpent : 0;
+    }
+
+    public function updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sType, $sOrder = '', $sInfo = '', $sData = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($sOrder))
+            $sOrder = $this->_oConfig->getOrder();
+
+        if(empty($sData))
+            $sData = serialize(array(
+                'conversion' => $this->_oConfig->getConversionRateUse(),
+                'precision' => $this->_oConfig->getPrecision()
+            ));
+
+        if(!$this->_oDb->updateProfileBalance($iFirstPid, $fAmount))
+            return false;
+
+        $fAmountAbs = abs($fAmount);
+        $sDirection = $fAmount > 0 ? BX_CREDITS_DIRECTION_IN : BX_CREDITS_DIRECTION_OUT;
+
+        $iHistoryId = $this->_oDb->insertHistory([
+            'first_pid' => $iFirstPid,
+            'second_pid' => $iSecondPid,
+            'amount' => $fAmountAbs,
+            'type' => $sType,
+            'direction' => $sDirection,
+            'order' => $sOrder,
+            'data' => $sData,
+            'info' => $sInfo,
+            'date' => time()
+        ]);
+
+        if(!$iHistoryId)
+            return false;
+
+        bx_alert($this->getName(), 'update_balance', 0, false, array(
+            'first_pid' => $iFirstPid,
+            'second_pid' => $iSecondPid,
+            'amount' => $fAmountAbs,
+            'type' => $sType,
+            'direction' => $sDirection,
+            'order' => $sOrder,
+        ));
+
+        $oSecondProfile = BxDolProfile::getInstanceMagic($iSecondPid);
+        sendMailTemplate($CNF['ETEMPLATE_' . strtoupper($sDirection)], 0, $iFirstPid, array(
+            'second_profile_name' => $oSecondProfile->getDisplayName(),
+            'amount' => $fAmountAbs,
+        ));
+
+        return $iHistoryId;
+    }
+
+    public function processGrant($iUserId, $iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return ['code' => 2, 'msg' => '_bx_credits_err_profile_not_found'];
+
+        $sInfo = '_bx_credits_txt_history_info_grant';
+        $iHistoryId = $this->updateProfileBalance($iProfileId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_GRANT, '', $sInfo);
+        if(!$iHistoryId)
+            return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
+
+        sendMailTemplate($CNF['ETEMPLATE_GRANTED'], 0, $iProfileId, [
+            'amount' => $fAmount,
+            'message' => $sMessage
+        ]);
+
+        bx_alert($this->getName(), 'granted', 0, false, [
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+        ]);
+
+        return ['code' => 0, 'id' => $iHistoryId];
+    }
+
+    public function processSend($iUserId, $iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $fAmountAvail = $this->getProfileBalance($iUserId);
+        if($fAmount > $fAmountAvail)
+            return ['code' => 1, 'msg' => '_bx_credits_err_low_balance'];
+
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return ['code' => 2, 'msg' => '_bx_credits_err_profile_not_found'];
+
+        $sOrder = $this->_oConfig->getOrder();
+        $sInfo = !empty($sMessage) ? $sMessage : '_bx_credits_txt_history_info_send';
+
+        $iHistoryId = $this->updateProfileBalance($iUserId, $iProfileId, -$fAmount, BX_CREDITS_TRANSFER_TYPE_SEND, $sOrder, $sInfo);
+        if(!$iHistoryId)
+            return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
+
+        if(!$this->updateProfileBalance($iProfileId, $iUserId, $fAmount, BX_CREDITS_TRANSFER_TYPE_SEND, $sOrder, $sInfo)) {
+            $sInfo = '_bx_credits_txt_history_info_cancellation';
+            $iHistoryId = $this->updateProfileBalance($iUserId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_CANCELLATION, $sOrder, $sInfo);
+
+            return ['code' => 3, 'id' => $iHistoryId, 'msg' => '_bx_credits_err_cannot_update_balance'];
+        }
+
+        $oUser = BxDolProfile::getInstance($iUserId);
+        sendMailTemplate($CNF['ETEMPLATE_RECEIVED'], 0, $iProfileId, [
+            'performer_id' => $iUserId,
+            'performer_name' => $oUser->getDisplayName(),
+            'performer_link' => $oUser->getUrl(),
+            'amount' => $fAmount,
+            'order' => $sOrder,
+            'message' => $sMessage
+        ]);
+
+        bx_alert($this->getName(), 'sent', 0, $iUserId, [
+            'performer' => $iUserId,
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+            'order' => $sOrder,
+        ]);
+
+        return ['code' => 0, 'id' => $iHistoryId];
+    }
+
+    public function processWithdrawRequest($iUserId, $iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id ();
+
+        if(empty($iProfileId))
+            return ['code' => 1, 'msg' => '_bx_credits_err_login_required'];
+
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return ['code' => 1, 'msg' => '_bx_credits_err_login_required'];
+
+        $fBalanceCleared = $this->getProfileBalanceCleared($iProfileId);
+        if($fAmount > $fBalanceCleared)
+            return ['code' => 2, 'msg' => '_bx_credits_err_low_balance'];
+
+        if($fAmount < ($iWithdrawMinimum = (int)getParam($CNF['PARAM_WITHDRAW_MINIMUM'])))
+            return ['code' => 3, 'msg' => _t('_bx_credits_err_withdraw_minimum', $iWithdrawMinimum)];
+
+        $fBalance = $this->getProfileBalance($iProfileId);
+        if(($fBalance - $fAmount) < ($iWithdrawRemaining = (int)getParam($CNF['PARAM_WITHDRAW_REMAINING'])))
+            return ['code' => 4, 'msg' => _t('_bx_credits_err_withdraw_remaining', $iWithdrawRemaining)];
+
+        $aResult = ['code' => 5, 'msg' => '_bx_credits_err_cannot_send'];
+
+        $fRate = $this->_oConfig->getConversionRateWithdraw();
+
+        $aTemplateVars = [
+            'profile_link' => $oProfile->getUrl(),
+            'profile_name' => $oProfile->getDisplayName(),
+            'amount' => $fAmount,
+            'rate' => $fRate,
+            'message' => $sMessage,
+            'confirm_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_HISTORY_ADMINISTRATION'])
+        ];
+        $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($CNF['ETEMPLATE_WITHDRAW_REQUESTED'], $aTemplateVars);
+        if(!$aTemplate)
+            return $aResult;
+
+        $sEmail = $this->_oConfig->getWithdrawEmail();
+        if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, [], BX_EMAIL_SYSTEM, 'html', false, [], true))
+            return $aResult;
+
+        bx_alert($this->getName(), 'withdraw_requested', 0, $iProfileId, [
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+            'rate' => $fRate
+        ]);
+
+        return ['code' => 0];
+    }
+
+    public function processWithdrawConfirm($iUserId, $iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return ['code' => 1, 'msg' => '_bx_credits_err_profile_not_found'];
+
+        $fBalance = $this->getProfileBalance($iProfileId);
+        if($fAmount > $fBalance)
+            return ['code' => 2, 'msg' => '_bx_credits_err_low_balance'];
+
+        $sInfo = '_bx_credits_txt_history_info_withdraw';
+        $iHistoryId = $this->updateProfileBalance($iProfileId, 0, -$fAmount, BX_CREDITS_TRANSFER_TYPE_WITHDRAW, '', $sInfo);
+        if(!$iHistoryId)
+            return ['code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance'];
+
+        sendMailTemplate($CNF['ETEMPLATE_WITHDRAW_SENT'], 0, $iProfileId, [
+            'amount' => $fAmount,
+            'message' => $sMessage
+        ]);
+
+        bx_alert($this->getName(), 'withdraw_sent', 0, $iUserId, [
+            'performer' => $iUserId,
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+        ]);
+
+        return ['code' => 0, 'id' => $iHistoryId];
+    }
+
+    public function processClearing()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aItems = $this->_oDb->getHistory(['type' => 'clearing', 'clearing' => $this->_oConfig->getWithdrawClearing()]);
+        if(empty($aItems) || !is_array($aItems))
+            return;
+
+        $iNow = time();
+        foreach($aItems as $aItem) {
+            $this->_oDb->updateHistory([$CNF['FIELD_H_CLEARED'] => $iNow], [$CNF['FIELD_H_ID'] => $aItem['id']]);
+
+            //TODO: Some action(s) related to clearing can be performed here.
+        }
+    }
+
+    /*
+     * Internal methods
+     */
+    protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aBundle) || !is_array($aBundle))
+            return array();
+
+        $iTrial = 0;
+        $sDuration = '';
+        $sAction = 'register';
+        if($sType == BX_CREDITS_ORDER_TYPE_RECURRING && isset($CNF['FIELD_DURATION_RECURRING'], $CNF['FIELD_TRIAL_RECURRING'])) {
+            $iTrial = $aBundle[$CNF['FIELD_TRIAL_RECURRING']];
+            $sDuration = $aBundle[$CNF['FIELD_DURATION_RECURRING']];
+
+            if($this->_oDb->isOrderByPbo($iClientId, $iItemId, $sOrder))
+                $sAction = 'prolong';
+        }
+
+        if(!$this->_oDb->{$sAction . 'Order'}($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial))
+            return array();
+
+        $sInfo = '_bx_credits_txt_history_info_purchase';
+        $fAmount = ((float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']]) * $iItemCount;
+        if(!$this->updateProfileBalance($iClientId, 0, $fAmount, BX_CREDITS_TRANSFER_TYPE_PURCHASE, '', $sInfo))
+            return array();
+
+        bx_alert($this->getName(), 'order_' . $sAction, 0, false, array(
+            'profile_id' => $iClientId,
+            'bundle_id' => $iItemId,
+            'product_id' => $iItemId,   //--- Alias for 'bundle_id'
+            'count' => $iItemCount,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+            'duration' => $sDuration,
+            'trial' => $iTrial
+        ));
+
+        $oClient = BxDolProfile::getInstanceMagic($iClientId);
+        $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
+        $sSellerUrl = $oSeller->getUrl();
+        $sSellerName = $oSeller->getDisplayName();
+
+        sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
+            'client_name' => $oClient->getDisplayName(),
+            'bundle_name' => $aBundle[$CNF['FIELD_NAME']],
+            'bundle_title' => _t($aBundle[$CNF['FIELD_TITLE']]),
+            'bundle_url' => $this->_oConfig->getBundleUrl($aBundle),
+            'vendor_url' => $sSellerUrl,
+            'vendor_name' => $sSellerName,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'notes' => _t('_bx_credits_txt_purchased_note', $sSellerUrl, $sSellerName),
+        ));
+
+        return $aItem;
+    }
+
+    protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aBundle) || !is_array($aBundle))
+            return false;
+
+        if(!$this->_oDb->unregisterOrder($iClientId, $iItemId, $sOrder, $sLicense, $sType))
+            return false;
+
+        $fAmount = (float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']];
+        $aProfile = $this->_oDb->getProfile(array('type' => 'id', 'id' => $iClientId));
+        if(!empty($aProfile) && is_array($aProfile))
+            $this->_oDb->updateProfile(array('balance' => (float)$aProfile['balance'] - $fAmount), array('id' => $aProfile['id']));
+
+        bx_alert($this->getName(), 'order_unregister', 0, false, array(
+            'profile_id' => $iClientId,
+            'bundle_id' => $iItemId,
+            'product_id' => $iItemId,   //--- Alias for 'bundle_id'
+            'count' => $iItemCount,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+        ));
+
+        return true;
+    }
+
+    protected function _getBlockOrders($sType) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_ORDERS_' . strtoupper($sType)];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        return array(
+            'content' => $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
+        );
+    }
+
+    protected function _getBlockHistory($sType) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_HISTORY_' . strtoupper($sType)];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        return array(
+            'content' => $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
+        );
+    }
+}
+
+/** @} */

+ 77 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_credits',
+    'title' => 'Credits',
+    'note' => 'Credits module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/credits/',
+    'home_uri' => 'credits',
+
+    'db_prefix' => 'bx_credits_',
+    'class_prefix' => 'BxCredits',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Credits',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(),
+
+);
+
+/** @} */

+ 277 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/install/langs/en.xml

@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_credits"><![CDATA[Credits]]></string>
+
+
+    <!-- Options -->
+    <string name="_bx_credits_option_enable_withdraw"><![CDATA[Allow members to withdraw credits converting them to money]]></string>
+    <string name="_bx_credits_option_withdraw_email"><![CDATA[Email for withdraw requests]]></string>
+    <string name="_bx_credits_option_withdraw_clearing"><![CDATA[Clearing period (in days) before received credits can be withdrawn]]></string>
+    <string name="_bx_credits_option_withdraw_minimum"><![CDATA[Minimum amount of cleared credits which can be withdrawn]]></string>
+    <string name="_bx_credits_option_withdraw_remaining"><![CDATA[Minimum credits balance after withdrawal]]></string>
+    <string name="_bx_credits_option_precision"><![CDATA[Precision (number of digits after the decimal point)]]></string>
+    <string name="_bx_credits_option_conversion_rate_use"><![CDATA[Conversion rate to pay with credits]]></string>
+    <string name="_bx_credits_option_conversion_rate_withdraw"><![CDATA[Conversion rate to withdraw credits]]></string>
+    <string name="_bx_credits_option_code"><![CDATA[Code to prefix amount]]></string>
+    <string name="_bx_credits_option_icon"><![CDATA[Icon to prefix amount]]></string>
+    <string name="_bx_credits_enable_provider"><![CDATA[Auto activate 'Credits' provider for all newly created profiles]]></string>
+
+
+    <!-- Forms -->
+    <string name="_bx_credits_form_bundle"><![CDATA[Bundle]]></string>
+    <string name="_bx_credits_form_bundle_display_add"><![CDATA[Add Bundle]]></string>
+    <string name="_bx_credits_form_bundle_display_edit"><![CDATA[Edit Bundle]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_form_bundle_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_form_bundle_input_title_err"><![CDATA[This field is essential. Please fill it in for all languages.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_form_bundle_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_form_bundle_input_name_err"><![CDATA[This field is essential for API calls. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_bundle_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_bundle_input_amount_err"><![CDATA[This field is essential. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_form_bundle_input_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_form_bundle_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_form_bundle_input_price_err"><![CDATA[This field is essential. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_bundle_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_credits_form_bundle_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_credits_form_credit"><![CDATA[Credit]]></string>
+    <string name="_bx_credits_form_credit_display_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_form_credit_display_send"><![CDATA[Send]]></string>
+    <string name="_bx_credits_form_credit_display_withdraw_request"><![CDATA[Request Withdraw]]></string>
+    <string name="_bx_credits_form_credit_display_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_form_credit_input_sys_balance"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_form_credit_input_balance"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_form_credit_input_sys_cleared"><![CDATA[Cleared Balance]]></string>
+    <string name="_bx_credits_form_credit_input_cleared"><![CDATA[Cleared Balance]]></string>
+    <string name="_bx_credits_form_credit_input_sys_rate"><![CDATA[Conversion rate]]></string>
+    <string name="_bx_credits_form_credit_input_rate"><![CDATA[Conversion rate]]></string>
+    <string name="_bx_credits_form_credit_input_sys_result"><![CDATA[Result]]></string>
+    <string name="_bx_credits_form_credit_input_result"><![CDATA[Result]]></string>
+    <string name="_bx_credits_form_credit_input_sys_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_credit_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_credit_input_sys_message"><![CDATA[Message]]></string>
+    <string name="_bx_credits_form_credit_input_message"><![CDATA[Message]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_g"><![CDATA[]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_s"><![CDATA[Indicate the purpose of sending to reflect it in history for future references]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_wr"><![CDATA[Payment instructions and other notes]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_wc"><![CDATA[Payment confirmation and other notes]]></string>
+    <string name="_bx_credits_form_credit_input_profile"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_form_credit_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_credit_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_credit_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_credits_form_credit_input_do_cancel"><![CDATA[Cancel]]></string>
+
+
+    <!-- Pages -->
+    <string name="_bx_credits_page_title_sys_home"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_title_home"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_block_title_sys_bundles"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_block_title_bundles"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_title_sys_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_title_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_block_title_sys_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_block_title_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_title_sys_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_page_title_history_common"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_block_title_sys_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_page_block_title_history_common"><![CDATA[History]]></string>    
+    <string name="_bx_credits_page_title_sys_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_page_title_history_administration"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_block_title_sys_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_page_block_title_history_administration"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_title_sys_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_page_title_orders_common"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_common_note"><![CDATA[Note]]></string>
+    <string name="_bx_credits_page_block_title_orders_common_note"><![CDATA[Note]]></string>
+    <string name="_bx_credits_page_block_content_orders_common_note"><![CDATA[The orders are for reference only.]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_page_block_title_orders_common"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_title_sys_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_page_title_orders_administration"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_page_block_title_orders_administration"><![CDATA[Orders]]></string>
+
+
+    <!-- Menus -->
+    <string name="_bx_credits_menu_item_title_system_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_system_history"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_menu_item_title_history"><![CDATA[{unit}{value}]]></string>
+    <string name="_bx_credits_menu_item_title_system_notifications"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_menu_item_title_notifications"><![CDATA[{value}]]></string>
+    <string name="_bx_credits_menu_title_submenu"><![CDATA[Credits Submenu]]></string>
+    <string name="_bx_credits_menu_set_title_submenu"><![CDATA[Credits Submenu]]></string>
+    <string name="_bx_credits_menu_item_title_system_home"><![CDATA[Home]]></string>
+    <string name="_bx_credits_menu_item_title_home"><![CDATA[Home]]></string>
+    <string name="_bx_credits_menu_item_title_system_admt_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_admt_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_bundles"><![CDATA[Bundles]]></string>
+    <string name="_bx_credits_menu_item_title_system_manage"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_manage"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_title_manage_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_credits_menu_set_title_manage_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_credits_menu_item_title_system_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_menu_item_title_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_menu_item_title_system_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_menu_item_title_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_menu_item_title_system_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_menu_item_title_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_menu_item_title_system_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_menu_item_title_history_common"><![CDATA[My History]]></string>
+
+
+    <!-- Grids -->
+    <string name="_bx_credits_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_grid_column_title_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_grid_column_title_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_grid_column_title_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_credits_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_credits_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_credits_grid_popup_title_add_bundle"><![CDATA[Add Bundle]]></string>
+    <string name="_bx_credits_grid_popup_title_edit_bundle"><![CDATA[Edit '{0}' Bundle]]></string>
+
+    <string name="_bx_credits_grid_column_title_htr_pid"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_grid_column_title_htr_first_pid"><![CDATA[Profile 1]]></string>
+    <string name="_bx_credits_grid_column_title_htr_second_pid"><![CDATA[Profile 2]]></string>
+    <string name="_bx_credits_grid_column_title_htr_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_grid_column_title_htr_order"><![CDATA[Order]]></string>
+    <string name="_bx_credits_grid_column_title_htr_direction"><![CDATA[Direction]]></string>
+    <string name="_bx_credits_grid_column_title_htr_info"><![CDATA[Notice]]></string>
+    <string name="_bx_credits_grid_column_title_htr_date"><![CDATA[Date]]></string>
+    <string name="_bx_credits_grid_column_title_htr_cleared"><![CDATA[Clearing]]></string>
+    <string name="_bx_credits_grid_action_title_htr_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_grid_action_title_htr_send"><![CDATA[Send]]></string>
+    <string name="_bx_credits_grid_action_title_htr_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_grid_action_title_htr_withdraw_request"><![CDATA[Request withdraw]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_send"><![CDATA[Send]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_withdraw_request"><![CDATA[Request withdraw]]></string>
+
+    <string name="_bx_credits_grid_column_title_ord_profile_id"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_grid_column_title_ord_bundle"><![CDATA[Bundle]]></string>
+    <string name="_bx_credits_grid_column_title_ord_transaction"><![CDATA[Transaction]]></string>
+    <string name="_bx_credits_grid_column_title_ord_type"><![CDATA[Type]]></string>
+    <string name="_bx_credits_grid_column_value_ord_type_single"><![CDATA[Single]]></string>
+    <string name="_bx_credits_grid_column_value_ord_type_recurring"><![CDATA[Recurring]]></string>
+    <string name="_bx_credits_grid_column_title_ord_added"><![CDATA[Added]]></string>
+    <string name="_bx_credits_grid_column_title_ord_expired"><![CDATA[Expires]]></string>
+
+
+    <!-- Email templates -->
+    <string name="_bx_credits_et_txt_name_granted"><![CDATA[Credits granted.]]></string>
+    <string name="_bx_credits_et_txt_subject_granted"><![CDATA[You're granted {amount} credits.]]></string>
+    <string name="_bx_credits_et_txt_body_granted"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You're granted <b>{amount}</b> credits.</p>
+<p>{message}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_received"><![CDATA[Credits received.]]></string>
+    <string name="_bx_credits_et_txt_subject_received"><![CDATA[You've received {amount} credits.]]></string>
+    <string name="_bx_credits_et_txt_body_received"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You've received <b>{amount}</b> credits from <a href="{performer_link}">{performer_name}</a>.<br />The order is <b>{order}</b>.</p>
+<p>{message}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_purchased"><![CDATA[Credits purchased.]]></string>
+    <string name="_bx_credits_et_txt_subject_purchased"><![CDATA[You've purchased {bundle_title} credits bundle.]]></string>
+    <string name="_bx_credits_et_txt_body_purchased"><![CDATA[{email_header}
+<p>Hello, {client_name}.</p>
+<p>You've purchased <a href="{bundle_url}">{bundle_title}</a> credits bundle.<br />Your order is <b>{order}</b>.</p>
+<p>{notes}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_in"><![CDATA[Credits in.]]></string>
+    <string name="_bx_credits_et_txt_subject_in"><![CDATA[Credits in.]]></string>
+    <string name="_bx_credits_et_txt_body_in"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You've received <b>{amount}</b> credits from {second_profile_name}.</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_out"><![CDATA[Credits out.]]></string>
+    <string name="_bx_credits_et_txt_subject_out"><![CDATA[Credits out.]]></string>
+    <string name="_bx_credits_et_txt_body_out"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You've sent <b>{amount}</b> credits to {second_profile_name}.</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_withdraw_requested"><![CDATA[Withdraw request.]]></string>
+    <string name="_bx_credits_et_txt_subject_withdraw_requested"><![CDATA[Withdraw request.]]></string>
+    <string name="_bx_credits_et_txt_body_withdraw_requested"><![CDATA[{email_header}
+<p><a href="{profile_link}">{profile_name}</a> requested to withdraw <b>{amount}</b> credits from his/her balance.</p>
+<p>Current withdraw conversion rate is <b>{rate}</b></p>
+<p>Withdrawal can be confirmed <a href="{confirm_url}">here</a>.</p>
+<p>Notes from <b>{profile_name}</b>:<br />{message}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_withdraw_sent"><![CDATA[Withdraw was sent.]]></string>
+    <string name="_bx_credits_et_txt_subject_withdraw_sent"><![CDATA[Withdraw was sent.]]></string>
+    <string name="_bx_credits_et_txt_body_withdraw_sent"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>The requested amount of credits (<b>{amount}</b>) was withdrawn to you.</p>
+<p>{message}</p>
+{email_footer}]]></string>
+
+
+    <!-- Other -->
+    <string name="_bx_credits_txt_sample_single"><![CDATA[credit]]></string>
+    <string name="_bx_credits_txt_sample_single_with_article"><![CDATA[a credit]]></string>
+    <string name="_bx_credits_txt_for_free"><![CDATA[for Free]]></string>
+    <string name="_bx_credits_txt_n_plus_m_for_free"><![CDATA[{0} (+{1} for free)]]></string>
+    <string name="_bx_credits_txt_purchase"><![CDATA[Purchase]]></string>
+    <string name="_bx_credits_txt_never"><![CDATA[never]]></string>
+    <string name="_bx_credits_txt_direction_out"><![CDATA[sent to]]></string>
+    <string name="_bx_credits_txt_direction_in"><![CDATA[got from]]></string>
+    <string name="_bx_credits_txt_purchased_note"><![CDATA[Contact <a href="{0}">{1}</a> if you have any questions or need support.]]></string>
+    <string name="_bx_credits_txt_history_info_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_txt_history_info_send"><![CDATA[Transfer]]></string>
+    <string name="_bx_credits_txt_history_info_purchase"><![CDATA[Bundle purchase]]></string>
+    <string name="_bx_credits_txt_history_info_checkout"><![CDATA[Profile to profile checkout]]></string>
+    <string name="_bx_credits_txt_history_info_withdraw"><![CDATA[Withdraw by request]]></string>
+    <string name="_bx_credits_txt_history_info_service"><![CDATA[Artificially initiated transfer]]></string>
+    <string name="_bx_credits_txt_history_info_refund"><![CDATA[Refund]]></string>
+    <string name="_bx_credits_txt_history_info_cancellation"><![CDATA[Cancellation]]></string>
+
+
+    <string name="_bx_credits_msg_empty_author"><![CDATA['Main seller' is empty. You need to mark some profile as 'Main seller' in Settings of currently active Payment app.]]></string>
+    <string name="_bx_credits_msg_action_performed"><![CDATA[The action was performed successfully.]]></string>
+    <string name="_bx_credits_err_profile_not_found"><![CDATA[Profile wasn't found.]]></string>
+    <string name="_bx_credits_err_login_required"><![CDATA[Login required.]]></string>
+    <string name="_bx_credits_err_low_balance"><![CDATA[Low balance.]]></string>
+    <string name="_bx_credits_err_withdraw_minimum"><![CDATA[Withdrawal less then {0} credits isn't available.]]></string>
+    <string name="_bx_credits_err_withdraw_remaining"><![CDATA[Minimum remaining balance after withdrawal should be more then {0} credits.]]></string>
+    <string name="_bx_credits_err_cannot_update_balance"><![CDATA[Cannot update balance.]]></string>
+    <string name="_bx_credits_err_cannot_send"><![CDATA[Cannot send message. Please report.]]></string>
+    <string name="_bx_credits_err_cannot_perform_action"><![CDATA[Cannot perform the action. Please report.]]></string>
+
+
+    <!-- Checkout process -->
+    <string name="_bx_credits_txt_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_txt_checkout_to"><![CDATA[Pay to {0} for:]]></string>
+    <string name="_bx_credits_txt_checkout_price_money"><![CDATA[Price:]]></string>
+    <string name="_bx_credits_txt_checkout_price_credits"><![CDATA[In Credits:]]></string>
+    <string name="_bx_credits_txt_checkout_rate"><![CDATA[Rate:]]></string>
+    <string name="_bx_credits_txt_checkout_qt"><![CDATA[qt.]]></string>
+
+    <!-- Subscribe process -->
+    <string name="_bx_credits_txt_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_credits_txt_subscribe_for"><![CDATA[Subscribe for:]]></string>
+    <string name="_bx_credits_txt_subscribe_lifetime"><![CDATA[lifetime]]></string>    
+    <string name="_bx_credits_txt_subscribe_period_mask"><![CDATA[{0} {1}]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_year"><![CDATA[yr.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_month"><![CDATA[mo.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_week"><![CDATA[wk.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_day"><![CDATA[d.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_hour"><![CDATA[hr.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_minute"><![CDATA[min.]]></string>
+    <string name="_bx_credits_txt_subscribe_trial"><![CDATA[Trial:]]></string>
+    <string name="_bx_credits_txt_subscribe_trial_mask"><![CDATA[{0} {1}]]></string>
+
+    <string name="_bx_credits_err_unknown_buyer"><![CDATA[Login required.]]></string>
+    <string name="_bx_credits_err_unknown_seller"><![CDATA[Unknown seller.]]></string>
+    <string name="_bx_credits_err_incorrect_data"><![CDATA[Incorrect input data. Please report.]]></string>
+</resources>

+ 32 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/disable.sql

@@ -0,0 +1,32 @@
+
+-- SETTINGS
+SET @iTypeId = (SELECT `ID` FROM `sys_options_types` WHERE `name` = 'bx_credits' LIMIT 1);
+SET @iCategId = (SELECT `ID` FROM `sys_options_categories` WHERE `type_id` = @iTypeId LIMIT 1);
+DELETE FROM `sys_options` WHERE `category_id` = @iCategId;
+DELETE FROM `sys_options_categories` WHERE `type_id` = @iTypeId;
+DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
+
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `module` = 'bx_credits';
+DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_credits' OR `object` IN ('bx_credits_home', 'bx_credits_checkout', 'bx_credits_orders_common', 'bx_credits_orders_administration', 'bx_credits_history_common', 'bx_credits_history_administration');
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = 'bx_credits';
+DELETE FROM `sys_menu_sets` WHERE `module` = 'bx_credits';
+DELETE FROM `sys_menu_items` WHERE `module` = 'bx_credits' OR `set_name` IN ('bx_credits_submenu', 'bx_credits_orders_submenu');
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` LIKE 'bx_credits_%';
+DELETE FROM `sys_grid_fields` WHERE `object` LIKE 'bx_credits_%';
+DELETE FROM `sys_grid_actions` WHERE `object` LIKE 'bx_credits_%';
+
+-- ALERTS
+SET @iHandler := (SELECT `id` FROM `sys_alerts_handlers` WHERE `name` = 'bx_credits' LIMIT 1);
+DELETE FROM `sys_alerts` WHERE `handler_id` = @iHandler;
+DELETE FROM `sys_alerts_handlers` WHERE `id` = @iHandler;
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = 'bx_credits';
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name` LIKE 'bx_credits_%';

+ 221 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/enable.sql

@@ -0,0 +1,221 @@
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_credits', '_bx_credits', 'bx_credits@modules/boonex/credits/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_credits', '_bx_credits', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_credits_enable_withdraw', '', @iCategId, '_bx_credits_option_enable_withdraw', 'checkbox', '', '', '', 1),
+('bx_credits_withdraw_email', '', @iCategId, '_bx_credits_option_withdraw_email', 'digit', '', '', '', 2),
+('bx_credits_withdraw_clearing', '30', @iCategId, '_bx_credits_option_withdraw_clearing', 'digit', '', '', '', 3),
+('bx_credits_withdraw_minimum', '500', @iCategId, '_bx_credits_option_withdraw_minimum', 'digit', '', '', '', 4),
+('bx_credits_withdraw_remaining', '100', @iCategId, '_bx_credits_option_withdraw_remaining', 'digit', '', '', '', 5),
+
+('bx_credits_precision', '2', @iCategId, '_bx_credits_option_precision', 'digit', '', '', '', 10),
+('bx_credits_conversion_rate_use', '1.0', @iCategId, '_bx_credits_option_conversion_rate_use', 'digit', '', '', '', 11),
+('bx_credits_conversion_rate_withdraw', '1.0', @iCategId, '_bx_credits_option_conversion_rate_withdraw', 'digit', '', '', '', 12),
+
+('bx_credits_code', '', @iCategId, '_bx_credits_option_code', 'digit', '', '', '', 20),
+('bx_credits_icon', 'copyright', @iCategId, '_bx_credits_option_icon', 'digit', '', '', '', 21),
+
+('bx_credits_enable_provider', '', @iCategId, '_bx_credits_enable_provider', 'checkbox', '', '', '', 30);
+
+
+-- PAGE: module home
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_home', 'credits-home', '_bx_credits_page_title_sys_home', '_bx_credits_page_title_home', 'bx_credits', 5, 2147483647, 1, 'page.php?i=credits-home', '', '', '', 0, 1, 0, 'BxCreditsPageBrowse', 'modules/boonex/credits/classes/BxCreditsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_credits_home', 1, 'bx_credits', '_bx_credits_page_block_title_sys_bundles', '_bx_credits_page_block_title_bundles', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:17:"get_block_bundles";}', 0, 1, 1, 0);
+
+-- PAGE: checkout
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `type_id`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_checkout', 'credits-checkout', '_bx_credits_page_title_sys_checkout', '_bx_credits_page_title_checkout', 'bx_credits', 2, 5, 2147483647, 1, 'page.php?i=credits-checkout', '', '', '', 0, 1, 0, 'BxCreditsPageBrowse', 'modules/boonex/credits/classes/BxCreditsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_credits_checkout', 1, 'bx_credits', '_bx_credits_page_block_title_sys_checkout', '_bx_credits_page_block_title_checkout', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:18:"get_block_checkout";}', 0, 0, 1, 0);
+
+-- PAGE: profile's orders
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_orders_common', '_bx_credits_page_title_sys_orders_common', '_bx_credits_page_title_orders_common', 'bx_credits', 5, 2147483647, 1, 'credits-orders-common', '', '', '', '', 0, 1, 0, 'BxCreditsPageOrders', 'modules/boonex/credits/classes/BxCreditsPageOrders.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_credits_orders_common', 1, 'bx_credits', '_bx_credits_page_block_title_sys_orders_common_note', '_bx_credits_page_block_title_orders_common_note', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:21:"get_block_orders_note";}', 0, 0, 1, 0),
+('bx_credits_orders_common', 1, 'bx_credits', '_bx_credits_page_block_title_sys_orders_common', '_bx_credits_page_block_title_orders_common', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:16:"get_block_orders";}', 0, 0, 1, 1);
+
+-- PAGE: orders administration
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_orders_administration', '_bx_credits_page_title_sys_orders_administration', '_bx_credits_page_title_orders_administration', 'bx_credits', 5, 192, 1, 'credits-orders-administration', '', '', '', '', 0, 1, 0, 'BxCreditsPageOrders', 'modules/boonex/credits/classes/BxCreditsPageOrders.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_credits_orders_administration', 1, 'bx_credits', '_bx_credits_page_block_title_sys_orders_administration', '_bx_credits_page_block_title_orders_administration', 11, 192, 'service', 'a:3:{s:6:"module";s:10:"bx_credits";s:6:"method";s:16:"get_block_orders";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 0, 1, 0);
+
+-- PAGE: module manage own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_history_common', '_bx_credits_page_title_sys_history_common', '_bx_credits_page_title_history_common', 'bx_credits', 5, 2147483647, 1, 'credits-history-common', 'page.php?i=credits-history-common', '', '', '', 0, 1, 0, 'BxCreditsPageHistory', 'modules/boonex/credits/classes/BxCreditsPageHistory.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_credits_history_common', 1, 'bx_credits', '_bx_credits_page_block_title_sys_history_common', '_bx_credits_page_block_title_history_common', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:17:"get_block_history";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_history_administration', '_bx_credits_page_title_sys_history_administration', '_bx_credits_page_title_history_administration', 'bx_credits', 5, 192, 1, 'credits-history-administration', 'page.php?i=credits-history-administration', '', '', '', 0, 1, 0, 'BxCreditsPageHistory', 'modules/boonex/credits/classes/BxCreditsPageHistory.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_credits_history_administration', 1, 'bx_credits', '_bx_credits_page_block_title_sys_history_administration', '_bx_credits_page_block_title_history_administration', 11, 192, 'service', 'a:3:{s:6:"module";s:10:"bx_credits";s:6:"method";s:17:"get_block_history";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 1, 0);
+
+
+-- MENU: add to site menu
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_credits', 'credits-home', '_bx_credits_menu_item_title_system_credits', '_bx_credits_menu_item_title_credits', 'page.php?i=credits-home', '', '', 'copyright col-green3', 'bx_credits_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_credits', 'credits-home', '_bx_credits_menu_item_title_system_credits', '_bx_credits_menu_item_title_credits', 'page.php?i=credits-home', '', '', 'copyright col-green3', 'bx_credits_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- MENU: member toolbar
+SET @iMenuToolbarMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_toolbar_member' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_toolbar_member', 'bx_credits', 'credits-history', '_bx_credits_menu_item_title_system_history', '_bx_credits_menu_item_title_history', 'page.php?i=credits-history-common', '', '', '', '', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:26:"get_menu_item_addon_amount";}', '', 0, 2147483646, 0, 1, 0);
+
+-- MENU: Notifications
+SET @iAccountNotificationsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' AND `order` < 9999);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', 'bx_credits', 'notifications-credits', '_bx_credits_menu_item_title_system_notifications', '_bx_credits_menu_item_title_notifications', 'page.php?i=credits-history-common', '', '', 'copyright col-green3', '', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:26:"get_menu_item_addon_amount";}', '', '0', 2147483646, 1, 1, @iAccountNotificationsMenuOrder + 1);
+
+-- MENU: account dashboard
+SET @iAccountDashboardMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard' LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('sys_account_dashboard', 'bx_credits', 'credits-manage', '_bx_credits_menu_item_title_system_manage', '_bx_credits_menu_item_title_manage', 'page.php?i=credits-history-common', '', '', 'copyright col-green3', '', '', 2147483646, 1, 0, 1, @iAccountDashboardMenuOrder + 1);
+
+-- MENU: module sub-menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_submenu', '_bx_credits_menu_title_submenu', 'bx_credits_submenu', 'bx_credits', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_credits_submenu', 'bx_credits', '_bx_credits_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_credits_submenu', 'bx_credits', 'credits-home', '_bx_credits_menu_item_title_system_home', '_bx_credits_menu_item_title_home', 'page.php?i=credits-home', '', '', '', '', 2147483647, 0, 1, 1);
+
+-- MENU: manage submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_manage_submenu', '_bx_credits_menu_title_manage_submenu', 'bx_credits_manage_submenu', 'bx_credits', 6, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_credits_manage_submenu', 'bx_credits', '_bx_credits_menu_set_title_manage_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_credits_manage_submenu', 'bx_credits', 'credits-history-common', '_bx_credits_menu_item_title_system_history_common', '_bx_credits_menu_item_title_history_common', 'page.php?i=credits-history-common', '', '_self', '', '', '', 2147483646, 1, 0, 1, 1),
+('bx_credits_manage_submenu', 'bx_credits', 'credits-history-administration', '_bx_credits_menu_item_title_system_history_administration', '_bx_credits_menu_item_title_history_administration', 'page.php?i=credits-history-administration', '', '_self', '', '', '', 192, 1, 0, 1, 2),
+('bx_credits_manage_submenu', 'bx_credits', 'credits-orders-common', '_bx_credits_menu_item_title_system_orders_common', '_bx_credits_menu_item_title_orders_common', 'page.php?i=credits-orders-common', '', '_self', '', '', '', 2147483646, 1, 0, 1, 3),
+('bx_credits_manage_submenu', 'bx_credits', 'credits-orders-administration', '_bx_credits_menu_item_title_system_orders_administration', '_bx_credits_menu_item_title_orders_administration', 'page.php?i=credits-orders-administration', '', '_self', '', '', '', 192, 1, 0, 1, 4);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_credits', 'credits-history-administration', '_bx_credits_menu_item_title_system_admt_credits', '_bx_credits_menu_item_title_admt_credits', 'page.php?i=credits-history-administration', '', '_self', 'copyright', 'a:2:{s:6:"module";s:10:"bx_credits";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+
+-- GRIDS: bundles
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_credits_bundles', 'Sql', 'SELECT * FROM `bx_credits_bundles` WHERE 1 ', 'bx_credits_bundles', 'id', 'order', 'active', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 192, 'BxCreditsGridBundles', 'modules/boonex/credits/classes/BxCreditsGridBundles.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_credits_bundles', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_credits_bundles', 'order', '', '1%', 0, '', '', 2),
+('bx_credits_bundles', 'name', '_bx_credits_grid_column_title_name', '23%', 0, 32, '', 3),
+('bx_credits_bundles', 'title', '_bx_credits_grid_column_title_title', '30%', 1, 16, '', 4),
+('bx_credits_bundles', 'amount', '_bx_credits_grid_column_title_amount', '10%', 0, 16, '', 5),
+('bx_credits_bundles', 'bonus', '_bx_credits_grid_column_title_bonus', '5%', 0, 16, '', 6),
+('bx_credits_bundles', 'price', '_bx_credits_grid_column_title_price', '10%', 0, 16, '', 7),
+('bx_credits_bundles', 'actions', '', '20%', 0, '', '', 8);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_credits_bundles', 'independent', 'add', '_bx_credits_grid_action_title_add', '', 0, 0, 1),
+('bx_credits_bundles', 'single', 'edit', '_bx_credits_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_credits_bundles', 'single', 'delete', '_bx_credits_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_credits_bundles', 'bulk', 'delete', '_bx_credits_grid_action_title_delete', '', 0, 1, 1);
+
+-- GRIDS: orders
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_credits_orders_administration', 'Sql', 'SELECT `to`.`id` AS `id`, `to`.`profile_id` AS `profile_id`, `to`.`bundle_id` AS `bundle_id`, `tb`.`title` AS `bundle`, `to`.`order` AS `transaction`, `to`.`license` AS `license`, `to`.`type` AS `type`, `to`.`added` AS `added`, `to`.`expired` AS `expired` FROM `bx_credits_orders` AS `to` LEFT JOIN `bx_credits_bundles` AS `tb` ON `to`.`bundle_id`=`tb`.`id` WHERE 1 ', 'bx_credits_orders', 'id', 'added', '', '', 20, NULL, 'start', '', 'tb`.`title,to`.`order,to`.`license,to`.`type', '', 'like', '', '', 192, 'BxCreditsGridOrdersAdministration', 'modules/boonex/credits/classes/BxCreditsGridOrdersAdministration.php'),
+('bx_credits_orders_common', 'Sql', 'SELECT `to`.`id` AS `id`, `to`.`profile_id` AS `profile_id`, `to`.`bundle_id` AS `bundle_id`, `tb`.`title` AS `bundle`, `to`.`order` AS `transaction`, `to`.`license` AS `license`, `to`.`type` AS `type`, `to`.`added` AS `added`, `to`.`expired` AS `expired` FROM `bx_credits_orders` AS `to` LEFT JOIN `bx_credits_bundles` AS `tb` ON `to`.`bundle_id`=`tb`.`id` WHERE 1 ', 'bx_credits_orders', 'id', 'added', '', '', 20, NULL, 'start', '', 'tb`.`title,to`.`order,to`.`license,to`.`type', '', 'like', '', '', 2147483647, 'BxCreditsGridOrdersCommon', 'modules/boonex/credits/classes/BxCreditsGridOrdersCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_credits_orders_administration', 'profile_id', '_bx_credits_grid_column_title_ord_profile_id', '10%', 0, '28', '', 1),
+('bx_credits_orders_administration', 'bundle', '_bx_credits_grid_column_title_ord_bundle', '20%', 1, '28', '', 2),
+('bx_credits_orders_administration', 'transaction', '_bx_credits_grid_column_title_ord_transaction', '10%', 0, '32', '', 3),
+('bx_credits_orders_administration', 'type', '_bx_credits_grid_column_title_ord_type', '5%', 1, '12', '', 4),
+('bx_credits_orders_administration', 'added', '_bx_credits_grid_column_title_ord_added', '10%', 1, '25', '', 5),
+('bx_credits_orders_administration', 'expired', '_bx_credits_grid_column_title_ord_expired', '10%', 1, '25', '', 6),
+
+('bx_credits_orders_common', 'bundle', '_bx_credits_grid_column_title_ord_bundle', '20%', 1, '28', '', 1),
+('bx_credits_orders_common', 'transaction', '_bx_credits_grid_column_title_ord_transaction', '10%', 0, '32', '', 2),
+('bx_credits_orders_common', 'type', '_bx_credits_grid_column_title_ord_type', '10%', 1, '12', '', 3),
+('bx_credits_orders_common', 'added', '_bx_credits_grid_column_title_ord_added', '10%', 1, '25', '', 4),
+('bx_credits_orders_common', 'expired', '_bx_credits_grid_column_title_ord_expired', '10%', 1, '25', '', 5);
+
+-- GRIDS: history
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_credits_history_administration', 'Sql', 'SELECT * FROM `bx_credits_history` WHERE 1 ', 'bx_credits_history', 'id', 'date', '', '', 20, NULL, 'start', '', 'direction,order,info', '', 'like', '', '', 192, 'BxCreditsGridHistoryAdministration', 'modules/boonex/credits/classes/BxCreditsGridHistoryAdministration.php'),
+('bx_credits_history_common', 'Sql', 'SELECT * FROM `bx_credits_history` WHERE 1 ', 'bx_credits_history', 'id', 'date', '', '', 20, NULL, 'start', '', 'direction,order,info', '', 'like', '', '', 2147483647, 'BxCreditsGridHistoryCommon', 'modules/boonex/credits/classes/BxCreditsGridHistoryCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_credits_history_administration', 'first_pid', '_bx_credits_grid_column_title_htr_first_pid', '15%', 0, '', '', 1),
+('bx_credits_history_administration', 'direction', '_bx_credits_grid_column_title_htr_direction', '10%', 0, '', '', 2),
+('bx_credits_history_administration', 'second_pid', '_bx_credits_grid_column_title_htr_second_pid', '15%', 0, '', '', 3),
+('bx_credits_history_administration', 'amount', '_bx_credits_grid_column_title_htr_amount', '10%', 1, '', '', 4),
+('bx_credits_history_administration', 'order', '_bx_credits_grid_column_title_htr_order', '15%', 0, '16', '', 5),
+('bx_credits_history_administration', 'info', '_bx_credits_grid_column_title_htr_info', '15%', 1, '24', '', 6),
+('bx_credits_history_administration', 'date', '_bx_credits_grid_column_title_htr_date', '10%', 0, '', '', 7),
+('bx_credits_history_administration', 'cleared', '_bx_credits_grid_column_title_htr_cleared', '10%', 0, '', '', 8),
+
+('bx_credits_history_common', 'direction', '_bx_credits_grid_column_title_htr_direction', '10%', 0, '', '', 1),
+('bx_credits_history_common', 'second_pid', '_bx_credits_grid_column_title_htr_pid', '25%', 0, '', '', 2),
+('bx_credits_history_common', 'amount', '_bx_credits_grid_column_title_htr_amount', '15%', 1, '', '', 3),
+('bx_credits_history_common', 'order', '_bx_credits_grid_column_title_htr_order', '15%', 0, '16', '', 4),
+('bx_credits_history_common', 'info', '_bx_credits_grid_column_title_htr_info', '15%', 1, '32', '', 5),
+('bx_credits_history_common', 'date', '_bx_credits_grid_column_title_htr_date', '10%', 0, '', '', 6),
+('bx_credits_history_common', 'cleared', '_bx_credits_grid_column_title_htr_cleared', '10%', 0, '', '', 7);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_credits_history_administration', 'independent', 'grant', '_bx_credits_grid_action_title_htr_grant', '', 0, 0, 1),
+('bx_credits_history_administration', 'independent', 'withdraw_confirm', '_bx_credits_grid_action_title_htr_withdraw_confirm', '', 0, 0, 2),
+
+('bx_credits_history_common', 'independent', 'send', '_bx_credits_grid_action_title_htr_send', '', 0, 0, 1),
+('bx_credits_history_common', 'independent', 'withdraw_request', '_bx_credits_grid_action_title_htr_withdraw_request', '', 0, 0, 2);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_credits', 'BxCreditsAlertsResponse', 'modules/boonex/credits/classes/BxCreditsAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('profile', 'add', @iHandler),
+('profile', 'delete', @iHandler);
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_credits', '_bx_credits_et_txt_name_granted', 'bx_credits_granted', '_bx_credits_et_txt_subject_granted', '_bx_credits_et_txt_body_granted'),
+('bx_credits', '_bx_credits_et_txt_name_received', 'bx_credits_received', '_bx_credits_et_txt_subject_received', '_bx_credits_et_txt_body_received'),
+('bx_credits', '_bx_credits_et_txt_name_purchased', 'bx_credits_purchased', '_bx_credits_et_txt_subject_purchased', '_bx_credits_et_txt_body_purchased'),
+('bx_credits', '_bx_credits_et_txt_name_in', 'bx_credits_in', '_bx_credits_et_txt_subject_in', '_bx_credits_et_txt_body_in'),
+('bx_credits', '_bx_credits_et_txt_name_out', 'bx_credits_out', '_bx_credits_et_txt_subject_out', '_bx_credits_et_txt_body_out'),
+('bx_credits', '_bx_credits_et_txt_name_withdraw_requested', 'bx_credits_withdraw_requested', '_bx_credits_et_txt_subject_withdraw_requested', '_bx_credits_et_txt_body_withdraw_requested'),
+('bx_credits', '_bx_credits_et_txt_name_withdraw_sent', 'bx_credits_withdraw_sent', '_bx_credits_et_txt_subject_withdraw_sent', '_bx_credits_et_txt_body_withdraw_sent');
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_credits_clearing', '0 0 * * *', 'BxCreditsCronClearing', 'modules/boonex/credits/classes/BxCreditsCronClearing.php', '');

+ 176 - 0
modules/boonex/credits/updates/13.0.1_13.0.2/source/install/sql/install.sql

@@ -0,0 +1,176 @@
+-- TABLE: bundles
+CREATE TABLE IF NOT EXISTS `bx_credits_bundles` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `added` int(11) NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `amount` int(11) NOT NULL DEFAULT '0',
+  `bonus` int(11) NOT NULL DEFAULT '0',
+  `price` float NOT NULL DEFAULT '0',
+  `active` tinyint(4) NOT NULL DEFAULT '0',
+  `order` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: orders
+CREATE TABLE IF NOT EXISTS `bx_credits_orders` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `bundle_id` int(11) unsigned NOT NULL default '0',
+  `count` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `type` varchar(16) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  `new` tinyint(1) NOT NULL default '1',
+  PRIMARY KEY (`id`),
+  KEY `order_id` (`bundle_id`, `profile_id`),
+  KEY `license` (`license`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_credits_orders_deleted` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `bundle_id` int(11) unsigned NOT NULL default '0',
+  `count` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `type` varchar(16) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  `new` tinyint(1) NOT NULL default '1',
+  `reason` varchar(16) NOT NULL default '',
+  `deleted` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `order_id` (`bundle_id`, `profile_id`),
+  KEY `license` (`license`)
+);
+
+-- TABLE: profiles
+CREATE TABLE IF NOT EXISTS `bx_credits_profiles` (
+  `id` int(11) NOT NULL DEFAULT '0',
+  `balance` float NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: history
+CREATE TABLE IF NOT EXISTS `bx_credits_history` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `first_pid` int(11) NOT NULL DEFAULT '0',
+  `second_pid` int(11) NOT NULL DEFAULT '0',
+  `amount` float NOT NULL DEFAULT '0',
+  `type` varchar(16) NOT NULL default '',
+  `direction` enum('in', 'out') NOT NULL DEFAULT 'in',
+  `order` varchar(32) NOT NULL default '',
+  `data` text NOT NULL default '',
+  `info` varchar(255) NOT NULL DEFAULT '',
+  `date` int(11) NOT NULL DEFAULT '0',
+  `cleared` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`)
+);
+
+
+-- FORMS: credit
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_credit', 'bx_credits', '_bx_credits_form_credit', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', '', '', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxCreditsFormCredit', 'modules/boonex/credits/classes/BxCreditsFormCredit.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_credits_credit', 'bx_credits_credit_send', 'bx_credits', 0, '_bx_credits_form_credit_display_send'),
+('bx_credits_credit', 'bx_credits_credit_grant', 'bx_credits', 0, '_bx_credits_form_credit_display_grant'),
+('bx_credits_credit', 'bx_credits_credit_withdraw_request', 'bx_credits', 0, '_bx_credits_form_credit_display_withdraw_request'),
+('bx_credits_credit', 'bx_credits_credit_withdraw_confirm', 'bx_credits', 0, '_bx_credits_form_credit_display_withdraw_confirm');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_credits_credit', 'bx_credits', 'balance', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_balance', '_bx_credits_form_credit_input_balance', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'cleared', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_cleared', '_bx_credits_form_credit_input_cleared', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'rate', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_rate', '_bx_credits_form_credit_input_rate', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'result', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_result', '_bx_credits_form_credit_input_result', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'amount', '', '', 0, 'text', '_bx_credits_form_credit_input_sys_amount', '_bx_credits_form_credit_input_amount', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_credits_form_credit_input_amount_err', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'message', '', '', 0, 'textarea', '_bx_credits_form_credit_input_sys_message', '_bx_credits_form_credit_input_message', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'profile', '', '', 0, 'custom', '_bx_credits_form_credit_input_sys_profile', '_bx_credits_form_credit_input_profile', '', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_credits_credit', 'bx_credits', 'do_submit', '_bx_credits_form_credit_input_do_submit', '', 0, 'submit', '_bx_credits_form_credit_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_credits_credit', 'bx_credits', 'do_cancel', '_bx_credits_form_credit_input_do_cancel', '', 0, 'button', '_bx_credits_form_credit_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_credits_credit_send', 'profile', 2147483647, 1, 1),
+('bx_credits_credit_send', 'amount', 2147483647, 1, 2),
+('bx_credits_credit_send', 'message', 2147483647, 1, 3),
+('bx_credits_credit_send', 'controls', 2147483647, 1, 4),
+('bx_credits_credit_send', 'do_submit', 2147483647, 1, 5),
+('bx_credits_credit_send', 'do_cancel', 2147483647, 1, 6),
+
+('bx_credits_credit_grant', 'profile', 2147483647, 1, 1),
+('bx_credits_credit_grant', 'amount', 2147483647, 1, 2),
+('bx_credits_credit_grant', 'message', 2147483647, 1, 3),
+('bx_credits_credit_grant', 'controls', 2147483647, 1, 4),
+('bx_credits_credit_grant', 'do_submit', 2147483647, 1, 5),
+('bx_credits_credit_grant', 'do_cancel', 2147483647, 1, 6),
+
+('bx_credits_credit_withdraw_request', 'balance', 2147483647, 1, 1),
+('bx_credits_credit_withdraw_request', 'cleared', 2147483647, 1, 2),
+('bx_credits_credit_withdraw_request', 'rate', 2147483647, 1, 3),
+('bx_credits_credit_withdraw_request', 'amount', 2147483647, 1, 4),
+('bx_credits_credit_withdraw_request', 'result', 2147483647, 1, 5),
+('bx_credits_credit_withdraw_request', 'message', 2147483647, 1, 6),
+('bx_credits_credit_withdraw_request', 'controls', 2147483647, 1, 7),
+('bx_credits_credit_withdraw_request', 'do_submit', 2147483647, 1, 8),
+('bx_credits_credit_withdraw_request', 'do_cancel', 2147483647, 1, 9),
+
+('bx_credits_credit_withdraw_confirm', 'profile', 2147483647, 1, 1),
+('bx_credits_credit_withdraw_confirm', 'amount', 2147483647, 1, 2),
+('bx_credits_credit_withdraw_confirm', 'message', 2147483647, 1, 3),
+('bx_credits_credit_withdraw_confirm', 'controls', 2147483647, 1, 4),
+('bx_credits_credit_withdraw_confirm', 'do_submit', 2147483647, 1, 5),
+('bx_credits_credit_withdraw_confirm', 'do_cancel', 2147483647, 1, 6);
+
+-- FORMS: bundle
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_credits_bundle', 'bx_credits', '_bx_credits_form_bundle', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_credits_bundles', 'id', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxCreditsFormBundle', 'modules/boonex/credits/classes/BxCreditsFormBundle.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_credits_bundle', 'bx_credits_bundle_add', 'bx_credits', 0, '_bx_credits_form_bundle_display_add'),
+('bx_credits_bundle', 'bx_credits_bundle_edit', 'bx_credits', 0, '_bx_credits_form_bundle_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_credits_bundle', 'bx_credits', 'title', '', '', 0, 'text_translatable', '_bx_credits_form_bundle_input_sys_title', '_bx_credits_form_bundle_input_title', '', 1, 0, 0, '', '', '', 'AvailTranslatable', 'a:1:{i:0;s:5:"title";}', '_bx_credits_form_bundle_input_title_err', 'Xss', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'name', '', '', 0, 'text', '_bx_credits_form_bundle_input_sys_name', '_bx_credits_form_bundle_input_name', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_credits_form_bundle_input_name_err', 'Xss', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'amount', '', '', 0, 'text', '_bx_credits_form_bundle_input_sys_amount', '_bx_credits_form_bundle_input_amount', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_credits_form_bundle_input_amount_err', 'Xss', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'bonus', '', '', 0, 'text', '_bx_credits_form_bundle_input_sys_bonus', '_bx_credits_form_bundle_input_bonus', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'price', '', '', 0, 'price', '_bx_credits_form_bundle_input_sys_price', '_bx_credits_form_bundle_input_price', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_credits_form_bundle_input_price_err', 'Xss', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_credits_bundle', 'bx_credits', 'do_submit', '_bx_credits_form_bundle_input_do_submit', '', 0, 'submit', '_bx_credits_form_bundle_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_credits_bundle', 'bx_credits', 'do_cancel', '_bx_credits_form_bundle_input_do_cancel', '', 0, 'button', '_bx_credits_form_bundle_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_credits_bundle_add', 'name', 2147483647, 1, 1),
+('bx_credits_bundle_add', 'title', 2147483647, 1, 2),
+('bx_credits_bundle_add', 'amount', 2147483647, 1, 3),
+('bx_credits_bundle_add', 'bonus', 2147483647, 1, 4),
+('bx_credits_bundle_add', 'price', 2147483647, 1, 5),
+('bx_credits_bundle_add', 'controls', 2147483647, 1, 6),
+('bx_credits_bundle_add', 'do_submit', 2147483647, 1, 7),
+('bx_credits_bundle_add', 'do_cancel', 2147483647, 1, 8),
+
+('bx_credits_bundle_edit', 'name', 2147483647, 1, 1),
+('bx_credits_bundle_edit', 'title', 2147483647, 1, 2),
+('bx_credits_bundle_edit', 'amount', 2147483647, 1, 3),
+('bx_credits_bundle_edit', 'bonus', 2147483647, 1, 4),
+('bx_credits_bundle_edit', 'price', 2147483647, 1, 5),
+('bx_credits_bundle_edit', 'controls', 2147483647, 1, 6),
+('bx_credits_bundle_edit', 'do_submit', 2147483647, 1, 7),
+('bx_credits_bundle_edit', 'do_cancel', 2147483647, 1, 8);
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_credits', '_bx_credits', '_bx_credits', 'bx_credits@modules/boonex/credits/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_credits', 'extensions', '{url_studio}module.php?name=bx_credits', '', 'bx_credits@modules/boonex/credits/|std-icon.svg', '_bx_credits', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));

+ 51 - 0
modules/boonex/decorous/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Decorous',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/decorous/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'decorous_update_1301_1302',
+
+    'module_dir' => 'boonex/decorous/',
+    'module_uri' => 'decorous',
+
+    'db_prefix' => 'bx_decorous_',
+    'class_prefix' => 'BxDecorous',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Decorous Template',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 26 - 0
modules/boonex/decorous/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxDecorousUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function update($aParams)
+    {
+        $aResult = parent::update($aParams);
+        if(!$aResult['result'])
+            return $aResult;
+
+        $oCacheUtilities = BxDolCacheUtilities::getInstance();
+        $oCacheUtilities->clear('css');
+        $oCacheUtilities->clear('template');
+
+        return $aResult;
+    }
+}

+ 49 - 0
modules/boonex/decorous/updates/13.0.1_13.0.2/source/data/template/bx_persons/cover.html

@@ -0,0 +1,49 @@
+<div class="bx-menu-toolbar-padding">
+    <div class="bx-base-pofile-cover-wrapper __class__">
+        <div class="bx-base-pofile-cover bx-def-cover-color-bg bx-def-box-sizing">
+            <div class="bx-base-pofile-cover-image bx-def-page-width bx-def-centered bx-def-padding-leftright bx-def-box-sizing">
+                <div class="bx-base-pofile-cover-image-cnt bx-def-box-sizing">
+                    <a class="bx-base-pofile-cover-image bx-def-box-sizing" href="__cover_href__" onclick="$('#__cover_popup_id__').dolPopupImage('__cover_url__', this)">
+                        <img class="bx-base-pofile-cover-image" style="background-image:url(__cover_url__)" src="<bx_icon_url:spacer.gif />"/>
+                    </a>
+                    <div class="bx-cover-gradient"></div>
+                </div>
+            </div>
+            <div class="bx-base-pofile-cover-info">
+                <bx_if:show_avatar>
+                    <div class="bx-base-pofile-cover-thumb bx-def-ava-big-size __add_class__">
+                        <a class="bx-base-pofile-cover-thumb" href="__picture_href__" onclick="$('#__picture_popup_id__').dolPopupImage('__picture_url__', $(this).parent()); event.stopPropagation();">
+                            <img class="bx-base-pofile-unit-thumb bx-def-ava-big bx-def-ava-big-size __img_class__" src="__ava_url__" <bx_if:show_ava_letter> style="display:none" </bx_if:show_ava_letter> />
+                            <p class="bx-base-pofile-unit-thumb bx-def-ava-big bx-def-ava-big-size bx-def-border __img_class__-placeholder" style="background-color:rgba(__color__);<bx_if:show_ava_image>display:none</bx_if:show_ava_image>">__letter__</p>
+                        </a>
+                        <bx_if:show_online>
+                            <div class="bx-base-pofile-unit-online"></div>
+                        </bx_if:show_online>
+                    </div>
+                </bx_if:show_avatar>
+                <div class="bx-base-pofile-ci-cnt bx-def-padding">
+                    <div class="bx-base-pofile-cover-user">
+                        <div class="bx-base-profile-cover-title-bages bx-def-centered">
+                            <h1 class="bx-def-unit-info">__title__ </h1>
+                            <div class="bx-base-profile-cover-meta flex flex-row flex-wrap justify-center lg:justify-start text-sm">__meta__</div>
+                        </div>
+                        <div class="bx-base-pofile-cover-actions bx-def-margin-top bx-def-margin-sec-leftright-neg" onclick="event.stopPropagation();">__action_menu__</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    __cover_popup__
+    __picture_popup__
+</div>
+<script>
+    setTimeout(function () {
+        var sPath = '.bx-base-pofile-cover-wrapper .bx-base-pofile-unit-thumb';
+        if ($(sPath).length) {
+            var body = $("html, body");
+            if (body.scrollTop() == 0) {
+				body.animate({ scrollTop: $(sPath).offset().top - $('#bx-toolbar').height() - 16 + "px" }, 'slow');
+            }
+        }
+    }, 500);
+</script>

+ 14 - 0
modules/boonex/decorous/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less

@@ -0,0 +1,14 @@
+@import '../../../../../../../template/css/editor.less';
+
+// quill style
+.ql-toolbar.ql-snow{
+    border-radius: 0 !important;
+}
+.ql-toolbar.ql-snow,
+.ql-container.ql-snow{
+     border-color: #d9d9d9 !important; 
+}
+
+.ql-editor{
+	min-height: 95px;
+}

+ 68 - 0
modules/boonex/decorous/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Decorous Decorous template
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_TEMPLATE,
+    'name' => 'bx_decorous',
+    'title' => 'Decorous',
+    'note' => 'Design template',
+    'version' => '13.0.2',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/decorous/',
+    'home_uri' => 'decorous',
+
+    'db_prefix' => 'bx_decorous_',
+    'class_prefix' => 'BxDecorous',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Decorous Template',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'enable' => array(
+        'execute_sql' => 1
+    ),
+    'disable' => array(
+        'execute_sql' => 1
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 56 - 0
modules/boonex/events/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Events',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/events/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'events_update_1301_1302',
+
+    'module_dir' => 'boonex/events/',
+    'module_uri' => 'events',
+
+    'db_prefix' => 'bx_events_',
+    'class_prefix' => 'BxEvents',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Events',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(
+        'template/images/no-pciture-big.png',
+        'template/images/no-picture-icon.png',
+        'template/images/no-picture-preview.png',
+        'template/images/no-picture-thumb.png',
+    ),
+);

+ 13 - 0
modules/boonex/events/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxEventsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 152 - 0
modules/boonex/events/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_events',
+    'title' => 'Events',
+    'note' => 'Events functionality.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/events/',
+    'home_uri' => 'events',
+
+    'db_prefix' => 'bx_events_',
+    'class_prefix' => 'BxEvents',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Events',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+    	'sys_profiles_friends' => array ('type' => 'profiles'),
+		'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_events_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_events_icon', 
+    	'bx_events_thumb', 
+    	'bx_events_avatar', 
+        'bx_events_avatar_big', 
+    	'bx_events_picture', 
+    	'bx_events_cover', 
+    	'bx_events_cover_thumb',
+    	'bx_events_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_events',
+    	'bx_events_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+    	'update_relations' => 1,        
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 19 - 0
modules/boonex/events/updates/13.0.1_13.0.2/source/template/images/no-picture.svg

@@ -0,0 +1,19 @@
+<svg width="240" height="240" viewBox="0 0 240 240" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M20 120C20 108.444 20.4639 97.9794 21.4648 88.5246C21.9851 83.609 26.2086 80 31.1517 80H208.848C213.791 80 218.015 83.609 218.535 88.5246C219.536 97.9794 220 108.444 220 120C220 203.412 195.829 230 120 230C44.171 230 20 203.412 20 120ZM132.554 110.438C127.419 100.032 112.581 100.032 107.446 110.438L102.685 120.084C100.646 124.216 96.7037 127.08 92.1438 127.743L81.4983 129.29C70.0152 130.958 65.4301 145.07 73.7393 153.169L81.4425 160.678C84.7421 163.894 86.2477 168.528 85.4688 173.07L83.6504 183.672C81.6888 195.109 93.6929 203.83 103.964 198.431L113.485 193.425C117.564 191.281 122.436 191.281 126.515 193.425L136.036 198.431C146.307 203.83 158.311 195.109 156.35 183.672L154.531 173.07C153.752 168.528 155.258 163.894 158.558 160.678L166.261 153.169C174.57 145.07 169.985 130.958 158.502 129.29L147.856 127.743C143.296 127.08 139.354 124.216 137.315 120.084L132.554 110.438Z" fill="url(#paint0_linear_429_6025)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M120 10C175.201 10 203.026 24.0902 214.08 63.9351C214.936 67.0177 212.555 70 209.356 70H30.6428C27.4438 70 25.0635 67.0177 25.9187 63.9351C36.9725 24.0902 64.7981 10 120 10ZM89.999 30C84.4762 30 79.999 34.4772 79.999 40C79.999 45.5228 84.4762 50 89.999 50H149.999C155.522 50 159.999 45.5228 159.999 40C159.999 34.4772 155.522 30 149.999 30H89.999Z" fill="url(#paint1_linear_429_6025)"/>
+<path d="M115.516 114.085C117.35 110.369 122.65 110.369 124.484 114.085L133.531 132.417C134.26 133.893 135.667 134.916 137.296 135.153L157.527 138.092C161.628 138.688 163.266 143.728 160.298 146.621L145.659 160.891C144.48 162.039 143.943 163.694 144.221 165.316L147.677 185.466C148.377 189.55 144.09 192.665 140.422 190.736L122.327 181.223C120.87 180.457 119.13 180.457 117.673 181.223L99.5781 190.736C95.91 192.665 91.6228 189.55 92.3234 185.466L95.7792 165.316C96.0574 163.694 95.5197 162.039 94.3412 160.891L79.7019 146.621C76.7343 143.728 78.3719 138.688 82.473 138.092L102.704 135.153C104.333 134.916 105.74 133.893 106.469 132.417L115.516 114.085Z" fill="url(#paint2_linear_429_6025)"/>
+<defs>
+<linearGradient id="paint0_linear_429_6025" x1="120" y1="80" x2="120" y2="230" gradientUnits="userSpaceOnUse">
+<stop stop-color="#7DD3FC"/>
+<stop offset="1" stop-color="#0EA5E9"/>
+</linearGradient>
+<linearGradient id="paint1_linear_429_6025" x1="120" y1="10" x2="120" y2="70" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB7185"/>
+<stop offset="1" stop-color="#F43F5E"/>
+</linearGradient>
+<linearGradient id="paint2_linear_429_6025" x1="120" y1="105" x2="120" y2="205" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB923C"/>
+<stop offset="1" stop-color="#EA580C"/>
+</linearGradient>
+</defs>
+</svg>

+ 51 - 0
modules/boonex/files/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Files',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/files/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'files_update_1301_1302',
+
+    'module_dir' => 'boonex/files/',
+    'module_uri' => 'files',
+
+    'db_prefix' => 'bx_files_',
+    'class_prefix' => 'BxFiles',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/files/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxFilesUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 135 - 0
modules/boonex/files/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_files',
+    'title' => 'Files',
+    'note' => 'Basic blogging module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/files/',
+    'home_uri' => 'files',
+
+    'db_prefix' => 'bx_files_',
+    'class_prefix' => 'BxFiles',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+    	'trigger_group_view_submenu',
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_files_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_files_preview',
+        'bx_files_gallery',
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_files',
+    	'bx_files_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications',
+    ),
+
+);
+
+/** @} */

+ 11 - 0
modules/boonex/files/updates/13.0.1_13.0.2/source/template/entry-text.html

@@ -0,0 +1,11 @@
+<div class="bx-content-description-before">__content_description_before__</div>
+<div class="bx-content-description">
+    <div class="bx-files-entity-preview bx-def-border-radius-block">__entry_preview__</div>
+    <bx_if:show_content>
+        <div class="bx-base-text-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-margin-top bx-def-vanilla-html prose dark:prose-invert">
+            <h1>__entry_title__</h1>
+            __entry_text__
+        </div>
+    </bx_if:show_content>
+</div>
+<div class="bx-content-description-after">__content_description_after__</div>

+ 51 - 0
modules/boonex/forum/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Discussions',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/forum/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'forum_update_1301_1302',
+
+    'module_dir' => 'boonex/forum/',
+    'module_uri' => 'forum',
+
+    'db_prefix' => 'bx_forum_',
+    'class_prefix' => 'BxForum',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Discussions',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/forum/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxForumUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 702 - 0
modules/boonex/forum/updates/13.0.1_13.0.2/source/classes/BxForumGrid.php

@@ -0,0 +1,702 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+define('BX_FORUM_FILTER_STATUS_RESOLVED', 1);
+define('BX_FORUM_FILTER_STATUS_UNRESOLVED', 0);
+
+define('BX_FORUM_FILTER_ORDER_RECENT', 'latest');
+define('BX_FORUM_FILTER_ORDER_NEW', 'new');
+define('BX_FORUM_FILTER_ORDER_TOP', 'top');
+define('BX_FORUM_FILTER_ORDER_UPDATED', 'updated');
+define('BX_FORUM_FILTER_ORDER_POPULAR', 'popular');
+define('BX_FORUM_FILTER_ORDER_FEATURED', 'featured');
+define('BX_FORUM_FILTER_ORDER_FAVORITE', 'favorite');
+define('BX_FORUM_FILTER_ORDER_PARTAKEN', 'partaken');
+
+class BxForumGrid extends BxTemplGrid
+{
+    protected $_oModule;
+    protected $_sDefaultSource; 
+    
+    protected $_sFilter1Name;
+    protected $_sFilter1Value;
+    protected $_aFilter1Values;
+    
+    protected $_sFilter2Name;
+    protected $_sFilter2Value;
+    protected $_aFilter2Values;
+    
+    protected $_sFilter3Name;
+    protected $_sFilter3Value;
+    protected $_aFilter3Values;
+    
+    protected $_sParamsDivider;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_forum');
+
+        parent::__construct ($aOptions, $oTemplate);
+        
+        $this->_sFilter1Name = 'filter1';
+        $this->_aFilter1Values = array(
+            '' => _t('_bx_forum_grid_filter_resolved_all'),
+            BX_FORUM_FILTER_STATUS_RESOLVED => _t('_bx_forum_grid_filter_resolved_resolved'),
+            BX_FORUM_FILTER_STATUS_UNRESOLVED => _t('_bx_forum_grid_filter_resolved_unresolved'),
+        );
+        
+        $sFilter1 = bx_get($this->_sFilter1Name);
+        if(!empty($sFilter1)) {
+            $this->_sFilter1Value = bx_process_input($sFilter1);
+            $this->_aQueryAppend['filter1'] = $this->_sFilter1Value;
+        }
+        
+        $this->_sFilter2Name = 'filter2';
+        $aBadges = BxDolBadges::getInstance()->getData(['type' => 'by_module', 'module' => $this->_oModule->_aModule['name']]);
+        
+        $this->_aFilter2Values = [];
+        
+        if (count($aBadges) > 0){
+            $this->_aFilter2Values[''] = _t('_bx_forum_grid_filter_badges_all');
+        }
+        
+        foreach($aBadges as $aBadge) {
+            $this->_aFilter2Values[$aBadge['id']] = $aBadge['text'];
+        }
+        
+
+        $sFilter2 = bx_get($this->_sFilter1Name);
+        if(!empty($sFilter2)) {
+            $this->_sFilter2Value = bx_process_input($sFilter2);
+            $this->_aQueryAppend['filter2'] = $this->_sFilter2Value;
+        }
+        
+        $this->_sFilter3Name = 'filter3';
+        $this->_aFilter3Values = array(
+            BX_FORUM_FILTER_ORDER_RECENT => _t('_bx_forum_grid_filter_order_recent'),
+            BX_FORUM_FILTER_ORDER_NEW => _t('_bx_forum_grid_filter_order_new'),
+            BX_FORUM_FILTER_ORDER_TOP => _t('_bx_forum_grid_filter_order_top'),
+            BX_FORUM_FILTER_ORDER_UPDATED => _t('_bx_forum_grid_filter_order_updated'),
+            BX_FORUM_FILTER_ORDER_POPULAR => _t('_bx_forum_grid_filter_order_popular'),
+            BX_FORUM_FILTER_ORDER_FEATURED => _t('_bx_forum_grid_filter_order_featured'),
+            BX_FORUM_FILTER_ORDER_FAVORITE => _t('_bx_forum_grid_filter_order_favorite'),
+            BX_FORUM_FILTER_ORDER_PARTAKEN => _t('_bx_forum_grid_filter_order_partaken'),
+        );
+        
+        $sFilter3 = bx_get($this->_sFilter3Name);
+        if(!empty($sFilter3)) {
+            $this->_sFilter1Value = bx_process_input($sFilter3);
+            $this->_aQueryAppend['filter3'] = $this->_sFilter1Value;
+        }
+        
+        $this->_sParamsDivider = '#-#';
+
+        $this->_sDefaultSortingOrder = 'DESC';
+        $this->_sDefaultSource = $this->_aOptions['source'];
+    }
+
+    public function setBrowseParams($aParams)
+    {
+        if(isset($aParams['ajax_paginate'])) {
+            if(!$aParams['ajax_paginate']) {
+                list($sPageLink, $aPageParams) = bx_get_base_url_inline();
+
+                $aPageParams[$this->_aOptions['paginate_get_start']] = '{start}';
+                $this->_aOptions['paginate_url'] = BxDolPermalinks::getInstance()->permalink(bx_append_url_params($sPageLink, $aPageParams));
+            }
+
+            unset($aParams['ajax_paginate']);
+        }
+        
+        if ($aParams['type'])
+            $this->_sFilter3Value = $aParams['type'];
+
+        parent::setBrowseParams($aParams);
+
+    	$sField = 'added';
+    	if(!empty($this->_aBrowseParams['type']))
+            switch($this->_aBrowseParams['type']) {
+                case 'new':
+                case 'index':
+                case 'author':
+                case 'favorite':
+                case 'category':
+                    $sField = 'added';
+                    break;
+
+                case 'featured':
+                    $sField = 'featured';
+                    break;
+
+                case 'updated':
+                    $sField = 'changed';
+                    break;
+
+                case 'latest':
+                    $sField = 'lr_timestamp';
+                    break;
+
+                case 'popular':
+                    $sField = 'views';
+                    break;
+            }
+
+        $this->_aOptions['field_order'] = $sField;
+        $this->_aOptions['paginate_per_page'] = !empty($this->_aBrowseParams['per_page']) ? (int)$this->_aBrowseParams['per_page'] : (int)$this->_oModule->_oDb->getParam('bx_forum_per_page_browse');
+    }
+
+    public function getCode ($isDisplayHeader = true)
+    {
+        $sCode = parent::getCode($isDisplayHeader);
+        if(empty($sCode))
+            return '';
+
+    	return $this->_oModule->_oTemplate->parseHtmlByName('units.html', array(
+            'code' => $sCode,
+            'js_code' => $this->_oModule->_oTemplate->getJsCode('main')
+        ));
+    }
+
+    protected function _getActionAdd ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if($this->_oModule->checkAllowedAdd() !== CHECK_ACTION_RESULT_ALLOWED)
+            return '';
+
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->_oModule->_oConfig->CNF['URI_ADD_ENTRY']);
+
+        unset($a['attr']['bx_grid_action_independent']);
+        $a['attr'] = array_merge($a['attr'], array(
+    		"onclick" => "window.open('" . $sUrl . "','_self');"
+    	));
+
+        return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getRowHead ()
+    {
+    	return array();
+    }
+
+    protected function _getCellDefault ($mixedValue, $sKey, $aField, $aRow)
+    {
+        $aField['attr_cell']['class'] = 'bx-grid-table-cell-' . $sKey;
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAuthor($mixedValue, $sKey, $aField, $aRow)
+    {
+    	$mixedValue = $this->_oModule->_oTemplate->getEntryAuthor($aRow);
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellCategory($mixedValue, $sKey, $aField, $aRow)
+    {
+        $sIcon = $this->_oModule->_oTemplate->parseHtmlByName('default_category.html', []);
+        $o = BxDolCategory::getObjectInstance('bx_forum_cats');
+        
+        $aCategoryData = $this->_oModule->_oDb->getCategories(array('type' => 'by_category', 'category' => $aRow['cat']));
+
+        if(isset($aCategoryData['icon']))
+            $sIcon = $this->_oTemplate->getImage($aCategoryData['icon'], array('class' => 'sys-icon'));
+        
+        $mixedValue = $this->_oModule->_oTemplate->parseHtmlByName('thumb.html', ['icon' => $sIcon, 'title' => $o->getCategoryTitle($aRow['cat'])]);
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellRating($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oObject = isset($CNF['OBJECT_SCORES']) ? BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], $aRow[$CNF['FIELD_ID']], true, $this->_oModule->_oTemplate) : null;
+        $mixedValue = $oObject ? $oObject->getElementInline() : '';
+        
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellParticipants($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+    	$oObject = isset($CNF['OBJECT_COMMENTS']) ? BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $aRow[$CNF['FIELD_ID']]) : null;
+      
+        $mixedValue = $oObject ? $oObject->getCounter(['show_counter_empty' => true, 'show_counter' => false, 'show_counter_style' => 'simple', 'dynamic_mode' => true, 'caption' => '', 'show_icon' => false, 'caption_empty' => '']) : '';
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellText($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = $this->_oModule->_oTemplate->getEntryPreview($aRow, ['show_meta_counters' => false, 'show_meta_reply' => false]);
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oModule->_oTemplate->addJs(array('main.js'));
+        $this->_oModule->_oTemplate->addCss(array('main.css', 'main-media-phone.css', 'main-media-tablet.css', 'main-media-desktop.css'));
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+        if(strpos($sFilter, $this->_sParamsDivider) !== false)
+            list($this->_sFilter1Value, $this->_sFilter2Value, $this->_sFilter3Value, $sFilter) = explode($this->_sParamsDivider, $sFilter);
+        
+        // featured
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_FEATURED){
+            $this->_aBrowseParams['where'] = ['fld' => 'featured', 'val' => 0, 'opr' => '<>'];
+        }
+        
+        // partaken
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_PARTAKEN){
+            $this->_aBrowseParams['select'] = array(
+                'tbla' => 'tco', 
+                'fld' => 'cmt_author_id',
+            );
+
+            $this->_aBrowseParams['join'] = array(
+                'tp' => 'INNER',
+                'tbl1' => 'bx_forum_cmts',
+                'tbl1a' => 'tco',
+                'fld1' => 'cmt_object_id',
+                'tbl2' => 'bx_forum_discussions',
+                'fld2' => 'id'
+            );
+
+            $this->_aBrowseParams['where'] = array(
+                'tbl' => 'tco', 
+                'fld' => 'cmt_author_id', 
+                'val' => bx_get_logged_profile_id(), 
+                'opr' => '='
+            );
+
+            $this->_aBrowseParams['group_by'] = array(
+                'tbl' => 'bx_forum_discussions', 
+                'fld' => 'id',
+            );
+        }
+        
+        //FAVORITE
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_FAVORITE){
+            $oProfile = BxDolProfile:: getInstance(bx_process_input(bx_get('profile_id'), BX_DATA_INT));
+            if(!$oProfile)
+                $oProfile = BxDolProfile::getInstance();
+            if(!$oProfile)
+                return '';
+            
+            $iProfileId = $oProfile->id();
+            $iProfileAuthor = $oProfile->id();
+            $oFavorite = $this->_oModule->getObjectFavorite();
+            if(!$oFavorite->isPublic() && $iProfileAuthor != bx_get_logged_profile_id())
+                return '';
+            
+            $aConditions = $oFavorite->getConditionsTrack($CNF['TABLE_ENTRIES'], 'id', $iProfileAuthor);
+            if(empty($aConditions) || !is_array($aConditions)) 
+                return '';
+
+            $aJoinGroup = array('grp' => true, 'cnds' => array());
+            if(!empty($aConditions['join']))
+                foreach($aConditions['join'] as $aCondition)
+                    $aJoinGroup['cnds'][] = array(
+                        'tp' => $aCondition['type'],
+                        'tbl1' => $aCondition['table'],
+                        'fld1' => $aCondition['onField'],
+                        'tbl2' => $aCondition['mainTable'],
+                        'fld2' => $aCondition['mainField']
+                    );
+
+            $aWhereGroup = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
+            if(!empty($aConditions['restriction']))
+                foreach($aConditions['restriction'] as $aCondition)
+                    $aWhereGroup['cnds'][] = array(
+                        'tbl' => (!empty($aCondition['table']) ? $aCondition['table'] : ''), 
+                        'fld' => $aCondition['field'], 
+                        'val' => $aCondition['value'], 
+                        'opr' => $aCondition['operator']
+                    );
+            
+            $this->_aBrowseParams['author'] = $iProfileId; 
+            $this->_aBrowseParams['join'] = $aJoinGroup;
+            $this->_aBrowseParams['where'] = $aWhereGroup; 
+        }
+        
+        $CNF = $this->_oModule->_oConfig->CNF;
+        
+    	$sSelectClause = $sJoinClause = $sWhereClause = $sGroupByClause = '';
+
+    	//--- Check status
+    	$sWhereClause .= " AND `{$CNF['TABLE_ENTRIES']}`.`" . $this->_oModule->_oConfig->CNF['FIELD_STATUS'] . "`='active'";
+    	$sWhereClause .= " AND `{$CNF['TABLE_ENTRIES']}`.`" . $this->_oModule->_oConfig->CNF['FIELD_STATUS_ADMIN'] . "`='active'";
+
+    	//--- Check privacy
+    	$iAuthorId = 0;
+    	if(!empty($this->_aBrowseParams['author'])) {
+            $oProfileAuthor = BxDolProfile::getInstance((int)$this->_aBrowseParams['author']);
+            if($oProfileAuthor)
+                $iAuthorId = $oProfileAuthor->id();
+    	}
+
+        $sPrivacy = $this->_oModule->_oConfig->CNF['OBJECT_PRIVACY_VIEW'];
+        $oPrivacy = BxDolPrivacy::getObjectInstance($sPrivacy);
+        $aCondition = $oPrivacy ? $oPrivacy->getContentPublicAsSQLPart($iAuthorId) : array();
+        if(isset($aCondition['join']))
+            $sJoinClause .= $aCondition['join'];
+        if(isset($aCondition['where']))
+            $sWhereClause .= $aCondition['where'];
+
+        //--- Check browse params
+        if(!empty($this->_aBrowseParams['select']) && is_array($this->_aBrowseParams['select'])) {
+            $sSelectClauseBrowse = $this->_getSqlSelectFromGroup($this->_aBrowseParams['select']);
+            if(!empty($sSelectClauseBrowse))
+                $sSelectClause .= ", " . $sSelectClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['join']) && is_array($this->_aBrowseParams['join'])) {
+            $sJoinClauseBrowse = $this->_getSqlJoinFromGroup($this->_aBrowseParams['join']);
+            if(!empty($sJoinClauseBrowse))
+                $sJoinClause .= " " . $sJoinClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['where']) && is_array($this->_aBrowseParams['where'])) {
+            $sWhereClauseBrowse = $this->_getSqlWhereFromGroup($this->_aBrowseParams['where']);
+            if(!empty($sWhereClauseBrowse))
+                $sWhereClause .= " AND " . $sWhereClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['group_by']) && is_array($this->_aBrowseParams['group_by'])) {
+            $sGroupByClauseBrowse = $this->_getSqlGroupByFromGroup($this->_aBrowseParams['group_by']);
+            if(!empty($sGroupByClauseBrowse))
+                $sGroupByClause .= " GROUP BY " . $sGroupByClauseBrowse;
+        }
+        
+        $sFilterSql = "";
+
+        // filter by resolved status
+        if(isset($this->_sFilter1Value) && $this->_sFilter1Value != ''){
+            $sWhereClause .= " AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_RESOLVABLE'] . "` = 1 AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_RESOLVE'] . "` = " . $this->_sFilter1Value;
+        }
+        
+        // filter out posts of suspended members
+        $sJoinClause .= " INNER JOIN `sys_profiles` AS `p` ON (`p`.`id` = `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_AUTHOR']}` AND `p`.`status` = 'active') ";
+
+        // filter out posts by content filter
+        $oCf = BxDolContentFilter::getInstance();
+        if($oCf->isEnabled())
+            $sWhereClause .= $oCf->getSQLParts ($CNF['TABLE_ENTRIES'], $CNF['FIELD_CF']);
+
+        // filter by badges
+        if(isset($this->_sFilter2Value) && $this->_sFilter2Value != ''){
+            
+            $aObjects = BxDolBadges::getInstance()->getData(['type' => 'by_module&badge', 'badge_id' => $this->_sFilter2Value, 'module' => $this->_oModule->_aModule['name']]);
+            $sWhereClause .= " AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_ID'] . "` IN (" . implode(',', $aObjects ) . ")";
+        }
+        $this->_aOptions['source'] = sprintf($this->_sDefaultSource, $sSelectClause, $sJoinClause, $sWhereClause, $sGroupByClause);
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+
+    protected function _getDataSqlOrderClause($sOrderByFilter, $sOrderField, $sOrderDir, $bFieldsOnly = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->_sFilter3Value) && $this->_sFilter3Value != ''){
+            $sOrderField = $this->_aBrowseParams['type'] = $this->_sFilter3Value;
+            if (!empty($this->_aBrowseParams['type']) && $this->_aBrowseParams['type'] != 'partaken'){
+                $this->_aBrowseParams['type'] = $this->_aBrowseParams['type'] = $this->_sFilter3Value;
+            }
+        }
+        
+    	$sOrder = parent::_getDataSqlOrderClause($sOrderByFilter, $sOrderField, $sOrderDir, true);
+                
+        if(!empty($this->_aBrowseParams['type']))
+            switch($this->_aBrowseParams['type']) {
+                case 'top':
+                    $aPartsUp = $aPartsDown = array(0);
+                    if(($oVote = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], 0, false)) !== false && $oVote->isEnabled()) {
+                        $aVote = $oVote->getSystemInfo();
+                        if(!empty($aVote['trigger_table']) && !empty($aVote['trigger_field_count']))
+                            $aPartsUp[] = '`' . $aVote['trigger_table'] . '`.`' . $aVote['trigger_field_count'] . '`';
+                    }
+
+                    if(($oReaction = BxDolVote::getObjectInstance($CNF['OBJECT_REACTIONS'], 0, false)) !== false && $oReaction->isEnabled()) {
+                        $aReaction = $oReaction->getSystemInfo();
+                        if(!empty($aReaction['trigger_table']) && !empty($aReaction['trigger_field_count']))
+                            $aPartsUp[] = '`' . $aReaction['trigger_table'] . '`.`' . $aReaction['trigger_field_count'] . '`';
+                    }
+
+                    if(($oScore = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], 0, false)) !== false && $oScore->isEnabled()) {
+                        $aScore = $oScore->getSystemInfo();
+                        if(!empty($aScore['trigger_table']) && !empty($aScore['trigger_field_cup']) && !empty($aScore['trigger_field_cdown'])) {
+                            $aPartsUp[] = '`' . $aScore['trigger_table'] . '`.`' . $aScore['trigger_field_cup'] . '`';
+                            $aPartsDown[] = '`' . $aScore['trigger_table'] . '`.`' . $aScore['trigger_field_cdown'] . '`';
+                        }
+                    }
+
+                    $sOrder = pow(10, 8) . ' * ((' . implode(' + ', $aPartsUp) . ') - (' . implode(' + ', $aPartsDown) . ')) / (UNIX_TIMESTAMP() - `' . $this->_aOptions['table'] . '`.`' . $CNF['FIELD_ADDED'] . '`) ' . $this->_sDefaultSortingOrder;
+                    break;
+
+                case 'partaken':
+                    $sOrder = 'MAX(`tco`.`cmt_time`) ' . $this->_sDefaultSortingOrder;
+                    break;
+            }           
+
+    	return " ORDER BY `" . $CNF['FIELD_STICK'] . "` DESC, " . $sOrder;
+    }
+
+    protected function _getSqlSelectFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlSelectFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = ", ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlSelectFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlSelectFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['fld']))
+            return $sResult;
+
+        $sResult = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbla']))
+            $sResult = "`" . $aCnd['tbla'] . "`." . $sResult;
+        else if(!empty($aCnd['tbl']))
+            $sResult = "`" . $aCnd['tbl'] . "`." . $sResult;
+
+        return $sResult;
+    }
+
+    protected function _getSqlJoinFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlJoinFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = " ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlJoinFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlJoinFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['tp'], $aCnd['tbl1'], $aCnd['fld1'], $aCnd['fld2']))
+            return $sResult;
+
+        $sTbl1A = $aCnd['tbl1'];
+        if(!empty($aCnd['tbl1a']))
+            $sTbl1A = $aCnd['tbl1a'];
+
+        $sField1 = "`" . $sTbl1A . "`.`" . $aCnd['fld1'] . "`";
+
+        $sField2 = "`" . $aCnd['fld2'] . "`";
+        if(!empty($aCnd['tbl2a']))
+            $sField2 = "`" . $aCnd['tbl2a'] . "`." . $sField2;
+        else if(!empty($aCnd['tbl2']))
+            $sField2 = "`" . $aCnd['tbl2'] . "`." . $sField2;
+
+        return $aCnd['tp'] . " JOIN `" . $aCnd['tbl1'] . "` AS `" . $sTbl1A . "` ON (" . $sField1 . " = " . $sField2 . ")";
+    }
+
+    protected function _getSqlWhereFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlWhereFromCondition($aGrp);
+
+        $sResult = "";
+        if(!isset($aGrp['opr'], $aGrp['cnds']) || empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = " " . $aGrp['opr'] . " ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sMethod = '_getSqlWhereFrom' . (isset($aGrp['grp']) && (bool)$aGrp['grp'] === true ? 'Group' : 'Condition');
+            $sResultCnd = $this->$sMethod($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        $sResult = trim($sResult, $sOprGrp);
+        if(!empty($sResult))
+            $sResult = "(" . $sResult . ")";
+
+    	return $sResult;
+    }
+
+    protected function _getSqlWhereFromCondition($aCnd)
+    {
+        $sResult = "";
+        if(!isset($aCnd['fld'], $aCnd['val'], $aCnd['opr']))
+            return $sResult;
+
+        $sMethod = '_getSqlWhereFromCondition' . bx_gen_method_name($aCnd['fld']);
+        if(method_exists($this, $sMethod)) {
+            $mixedResult = $this->$sMethod($aCnd);
+            if(is_array($mixedResult) && isset($mixedResult['fld'], $mixedResult['val'], $mixedResult['opr']))
+                $aCnd = $mixedResult;
+            else
+                return $mixedResult;
+        }
+        
+        $sField = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbl']))
+            $sField = "`" . $aCnd['tbl'] . "`." . $sField;
+
+        switch($aCnd['opr']) {
+            case 'IN':
+                if(empty($aCnd['val']) || !is_array($aCnd['val']))
+                    break;
+
+                $sResult .= $sField . " IN (" . $this->_oModule->_oDb->implode_escape($aCnd['val']) . ")";
+                break;
+
+            case 'LIKE':
+                $sResult .= $sField . " LIKE " . $this->_oModule->_oDb->escape('%' . $aCnd['val'] . '%');
+                break;
+
+            default:
+                $sResult .= $sField . " " . $aCnd['opr'] . " " . $this->_oModule->_oDb->escape($aCnd['val']);
+        }
+
+        return $sResult;
+    }
+
+    protected function _getSqlGroupByFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlGroupByFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = ", ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlGroupByFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlGroupByFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['fld']))
+            return $sResult;
+
+        $sResult = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbla']))
+            $sResult = "`" . $aCnd['tbla'] . "`." . $sResult;
+        else if(!empty($aCnd['tbl']))
+            $sResult = "`" . $aCnd['tbl'] . "`." . $sResult;
+
+        return $sResult;
+    }
+
+    protected function _getSqlWhereFromConditionAuthorComment($aCnd)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aEntriesIds = $this->_oModule->_oDb->getComments(array('type' => 'entries_author_search', 'author' => $aCnd['val']));
+        if(!empty($aEntriesIds) && is_array($aEntriesIds))
+            return array('tbl' => $CNF['TABLE_ENTRIES'], 'fld' => 'id', 'val' => $aEntriesIds, 'opr' => 'IN');
+
+        return '';
+    }
+
+    protected function _getSqlWhereFromConditionKeywordComment($aCnd)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aEntriesIds = $this->_oModule->_oDb->getComments(array('type' => 'entries_keyword_search', 'keyword' => $aCnd['val']));
+        if(!empty($aEntriesIds) && is_array($aEntriesIds))
+            return array('tbl' => $CNF['TABLE_ENTRIES'], 'fld' => 'id', 'val' => $aEntriesIds, 'opr' => 'IN');
+
+        return '';
+    }
+    
+    protected function _getFilterControls ()
+    {
+        parent::_getFilterControls();
+        return  $this->_getFilterSelectOne($this->_sFilter3Name, $this->_sFilter3Value, $this->_aFilter3Values) . $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values) . (count($this->_aFilter2Values) > 0 ? $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values) : '') . $this->_getSearchInput();
+    }
+    
+    protected function _getSearchInput()
+    {
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('main');
+        $aInputSearch = array(
+            'type' => 'text',
+            'name' => 'search',
+            'attrs' => array(
+                'id' => 'bx-grid-search-' . $this->_sObject,
+                'onKeyup' => 'javascript:$(this).off(\'keyup focusout\'); ' . $sJsObject . '.onChangeFilter(this)',
+                'onBlur' => 'javascript:' . $sJsObject . '.onChangeFilter(this)',
+            )
+        );
+
+        $oForm = new BxTemplFormView(array());
+        return $oForm->genRow($aInputSearch);
+    }
+    
+    protected function _getFilterSelectOne($sFilterName, $sFilterValue, $aFilterValues)
+    {
+        if(empty($sFilterName) || empty($aFilterValues))
+            return '';
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('main');
+
+        foreach($aFilterValues as $sKey => $sValue)
+            $aFilterValues[$sKey] = _t($sValue);
+
+        $aInputModules = array(
+            'type' => 'select',
+            'name' => $sFilterName,
+            'attrs' => array(
+                'id' => 'bx-grid-' . $sFilterName . '-' . $this->_sObject,
+                'onChange' => 'javascript:' . $sJsObject . '.onChangeFilter(this)'
+            ),
+            'value' => $sFilterValue,
+            'values' => $aFilterValues
+        );
+
+        $oForm = new BxTemplFormView(array());
+        return $oForm->genRow($aInputModules);
+    }
+}
+
+/** @} */

+ 149 - 0
modules/boonex/forum/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,149 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_forum',
+    'title' => 'Discussions',
+    'note' => 'Discussions module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/forum/',
+    'home_uri' => 'forum',
+
+    'db_prefix' => 'bx_forum_',
+    'class_prefix' => 'BxForum',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Discussions',
+    
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_forum_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_forum_preview',
+        'bx_forum_gallery',
+        'bx_forum_cover',
+        
+        'bx_forum_preview_photos',
+        'bx_forum_gallery_photos',
+        'bx_forum_view_photos',
+
+        'bx_forum_videos_poster',
+        'bx_forum_videos_poster_preview',
+        'bx_forum_videos_mp4',
+        'bx_forum_videos_mp4_hd',
+        
+        'bx_forum_preview_files',
+        'bx_forum_gallery_files',
+        
+        'bx_forum_preview_cmts',
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_forum',
+    	'bx_forum_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+	'enable_success' => array(
+    	'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+);
+
+/** @} */

+ 13 - 0
modules/boonex/forum/updates/13.0.1_13.0.2/source/template/score_element_inline.html

@@ -0,0 +1,13 @@
+<span id="__html_id__" class="sys-action __style_prefix__ __class__ inline-flex items-center whitespace-nowrap" bx_score_data_score="__score__" bx_score_data_cup="__cup__" bx_score_data_cdown="__cdown__">
+    <span class="sys-action-cnt __style_prefix__-cnt bx-def-valign-center relative z-0 inline-flex shadow-sm rounded-md">
+        <bx_if:show_do_vote_up>
+            <span class="sys-action-element-holder __style_prefix__-element-holder __style_prefix__-eh-up relative inline-flex items-center px-2 py-1 rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-300 dark:border-gray-700">__do_vote__</span>
+        </bx_if:show_do_vote_up>
+        <bx_if:show_counter>
+            <span class="sys-action-counter-holder __style_prefix__-counter-holder -ml-px relative inline-flex items-center px-2 py-1 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-300 dark:border-gray-700 text-center justify-center"<bx_if:show_hidden> style="display:none"</bx_if:show_hidden>>__counter__</span>
+        </bx_if:show_counter>
+        <bx_if:show_do_vote_down>
+            <span class="sys-action-element-holder __style_prefix__-element-holder __style_prefix__-eh-down  -ml-px relative inline-flex items-center px-2 py-1 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 dark:bg-gray-800 dark:hover:bg-gray-700 dark:text-gray-300 dark:border-gray-700">__do_vote__</span>
+        </bx_if:show_do_vote_down>
+</span>__script__
+</span>

+ 56 - 0
modules/boonex/groups/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Groups',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/groups/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'groups_update_1301_1302',
+
+    'module_dir' => 'boonex/groups/',
+    'module_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(
+        'template/images/no-pciture-big.png',
+        'template/images/no-picture-icon.png',
+        'template/images/no-picture-preview.png',
+        'template/images/no-picture-thumb.png',
+    ),
+);

+ 13 - 0
modules/boonex/groups/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxGroupsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 152 - 0
modules/boonex/groups/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_groups',
+    'title' => 'Groups',
+    'note' => 'Basic group profiles functionality.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/groups/',
+    'home_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+    	'sys_profiles_friends' => array ('type' => 'profiles'),
+		'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_groups_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_groups_icon', 
+    	'bx_groups_thumb', 
+    	'bx_groups_avatar', 
+        'bx_groups_avatar_big', 
+    	'bx_groups_picture', 
+    	'bx_groups_cover', 
+    	'bx_groups_cover_thumb',
+        'bx_groups_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_groups',
+    	'bx_groups_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+    	'update_relations' => 1,        
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 24 - 0
modules/boonex/groups/updates/13.0.1_13.0.2/source/template/images/no-picture.svg

@@ -0,0 +1,24 @@
+<svg width="240" height="240" viewBox="0 0 240 240" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M60.8307 70.0068C60.5544 70.0023 60.2774 70 60 70C32.3858 70 10 92.3858 10 120C10 147.614 32.3858 170 60 170C87.6142 170 110 147.614 110 120C110 119.723 109.998 119.446 109.993 119.169C84.8736 114.952 65.0479 95.1264 60.8307 70.0068Z" fill="url(#paint0_linear_429_5623)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M169.993 60.8307C169.998 60.5544 170 60.2774 170 60C170 32.3858 147.614 10 120 10C92.3858 10 70 32.3858 70 60C70 87.6142 92.3858 110 120 110C120.277 110 120.554 109.998 120.831 109.993C125.048 84.8736 144.874 65.0479 169.993 60.8307Z" fill="url(#paint1_linear_429_5623)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M70.0068 179.169C70.0023 179.446 70 179.723 70 180C70 207.614 92.3858 230 120 230C147.614 230 170 207.614 170 180C170 152.386 147.614 130 120 130C119.723 130 119.446 130.002 119.169 130.007C114.952 155.126 95.1264 174.952 70.0068 179.169Z" fill="url(#paint2_linear_429_5623)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M180 170C207.614 170 230 147.614 230 120C230 92.3858 207.614 70 180 70C152.386 70 130 92.3858 130 120C130 120.277 130.002 120.554 130.007 120.831C155.126 125.048 174.952 144.874 179.169 169.993C179.446 169.998 179.723 170 180 170Z" fill="url(#paint3_linear_429_5623)"/>
+<defs>
+<linearGradient id="paint0_linear_429_5623" x1="60" y1="70" x2="60" y2="170" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB7185"/>
+<stop offset="1" stop-color="#E11D48"/>
+</linearGradient>
+<linearGradient id="paint1_linear_429_5623" x1="120" y1="10" x2="120" y2="110" gradientUnits="userSpaceOnUse">
+<stop stop-color="#34D399"/>
+<stop offset="1" stop-color="#059669"/>
+</linearGradient>
+<linearGradient id="paint2_linear_429_5623" x1="120" y1="130" x2="120" y2="230" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB923C"/>
+<stop offset="1" stop-color="#EA580C"/>
+</linearGradient>
+<linearGradient id="paint3_linear_429_5623" x1="180" y1="70" x2="180" y2="170" gradientUnits="userSpaceOnUse">
+<stop stop-color="#60A5FA"/>
+<stop offset="1" stop-color="#2563EB"/>
+</linearGradient>
+</defs>
+</svg>

+ 51 - 0
modules/boonex/lucid/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Lucid',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/lucid/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'lucid_update_1301_1302',
+
+    'module_dir' => 'boonex/lucid/',
+    'module_uri' => 'lucid',
+
+    'db_prefix' => 'bx_lucid_',
+    'class_prefix' => 'BxLucid',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Lucid Template',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 26 - 0
modules/boonex/lucid/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+class BxLucidUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function update($aParams)
+    {
+        $aResult = parent::update($aParams);
+        if(!$aResult['result'])
+            return $aResult;
+
+        $oCacheUtilities = BxDolCacheUtilities::getInstance();
+        $oCacheUtilities->clear('css');
+        $oCacheUtilities->clear('template');
+
+        return $aResult;
+    }
+}

+ 12 - 0
modules/boonex/lucid/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less

@@ -0,0 +1,12 @@
+@import '../../../../../../../template/css/editor.less';
+
+.ql-toolbar.ql-snow{
+    border: none !important;
+    border-bottom: 1px solid rgba(50, 100, 180, 0.2) !important;
+}
+.ql-container.bx-form-input-html-quill-empty.ql-snow{
+    border-radius: 0.3rem;
+}
+.ql-editor{
+	min-height: 95px;
+}

+ 68 - 0
modules/boonex/lucid/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Lucid Lucid template
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_TEMPLATE,
+    'name' => 'bx_lucid',
+    'title' => 'Lucid',
+    'note' => 'Design template',
+    'version' => '13.0.2',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/lucid/',
+    'home_uri' => 'lucid',
+
+    'db_prefix' => 'bx_lucid_',
+    'class_prefix' => 'BxLucid',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Lucid Template',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'enable' => array(
+        'execute_sql' => 1
+    ),
+    'disable' => array(
+        'execute_sql' => 1
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/market/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Market',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/market/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'market_update_1301_1302',
+
+    'module_dir' => 'boonex/market/',
+    'module_uri' => 'market',
+
+    'db_prefix' => 'bx_market_',
+    'class_prefix' => 'BxMarket',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Market',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/market/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxMarketUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 140 - 0
modules/boonex/market/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,140 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_market',
+    'title' => 'Market',
+    'note' => 'Market module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/market/',
+    'home_uri' => 'market',
+
+    'db_prefix' => 'bx_market_',
+    'class_prefix' => 'BxMarket',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Market',
+
+	/**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_market_files',
+        'bx_market_photos'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_market_icon',
+        'bx_market_thumb',
+        'bx_market_cover',
+        'bx_market_screenshot',
+		'bx_market_preview',
+        'bx_market_gallery',
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_market',
+    	'bx_market_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_page_triggers' => 1,
+    	'process_menu_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 42 - 0
modules/boonex/market/updates/13.0.1_13.0.2/source/template/css/entry.css

@@ -0,0 +1,42 @@
+/*--- Entry Cover ---*/
+.bx-cover-wrapper .bx-cover .bx-cover-image img {
+	border-width: 0px;
+	background-position: center center;
+}
+
+/*--- Entry Content ---*/
+div.bx-market-entity-content {}
+
+div.bx-market-ec-title {}
+div.bx-market-ec-description p:first-child {
+    margin-top: 0;
+}
+
+/*--- Entry Screenshots ---*/
+div.bx-market-screenshots {
+	position: relative;
+	height: 120px;
+	height: 7.5rem;
+
+	overflow: hidden;
+}
+div.bx-market-screenshots-cnt {
+	position: relative;
+	white-space: nowrap;
+}
+div.bx-market-ss-item {
+	position: relative;
+	display: inline-block;
+	vertical-align: top;
+
+	margin-right: 2px;
+	margin-right: 0.125rem;
+}
+div.bx-market-ss-item .bx-market-ssi-img {
+	position: relative;
+	display: block;
+
+	background-position: center center;
+	background-repeat: no-repeat;
+	background-color: #ffffff;
+}

+ 24 - 0
modules/boonex/market/updates/13.0.1_13.0.2/source/template/entry-text.html

@@ -0,0 +1,24 @@
+<div class="bx-content-description-before">__content_description_before__</div>
+<div class="bx-content-description">
+    <bx_if:show_image>
+        <div class="bx-base-text-entity-image bx-def-margin-bottom bx-def-font-align-center">
+            <img class="bx-def-border-radius-block" src="__entry_image__" />
+        </div>
+    </bx_if:show_image>
+    <div class="bx-base-text-entity-content bx-market-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-vanilla-html prose dark:prose-invert">
+        <div class="bx-market-ec-title flex">
+            <bx_if:show_icon>
+                <div class="bx-market-ect-icon flex-none mr-4 not-prose"><img class="bx-def-thumb-size bx-def-round-corners" src="__entry_icon__"/></div>
+            </bx_if:show_icon>
+            <div class="bx-market-ect-title bx-base-text-title-bages flex-1">
+                <h1>__entry_title__</h1>
+                <div class="bx-base-bages-container absolute flex -translate-y-5/4">__badges__</div>
+            </div>
+        </div>
+        <div class="bx-market-ec-description">__entry_text__</div>
+    </div>
+    <bx_if:show_screenshots>
+        <div class="bx-market-ec-slideshow bx-def-margin-top">__screenshots__</div>
+    </bx_if:show_screenshots>
+</div>
+<div class="bx-content-description-after">__content_description_after__</div>

+ 51 - 0
modules/boonex/nexus/updates/13.0.0_13.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Nexus',
+    'version_from' => '13.0.0',
+    'version_to' => '13.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/nexus/updates/update_13.0.0_13.0.1/',
+    'home_uri' => 'nexus_update_1300_1301',
+
+    'module_dir' => 'boonex/nexus/',
+    'module_uri' => 'nexus',
+
+    'db_prefix' => 'bx_nexus_',
+    'class_prefix' => 'BxNexus',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Nexus',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/nexus/updates/13.0.0_13.0.1/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxNexusUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 68 - 0
modules/boonex/nexus/updates/13.0.0_13.0.1/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Nexus Nexus - Mobile Apps and Desktop apps connector
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_nexus',
+    'title' => 'Nexus',
+    'note' => 'Nexus - Mobile Apps and Desktop apps connector.',
+    'version' => '13.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/nexus/',
+    'home_uri' => 'nexus',
+
+    'db_prefix' => 'bx_nexus_',
+    'class_prefix' => 'BxNexus',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Nexus',
+    
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 132 - 0
modules/boonex/nexus/updates/13.0.0_13.0.1/source/template/js.html

@@ -0,0 +1,132 @@
+<script>
+    function bx_mobile_apps_show_main_menu () {
+        if ('__main_menu__' == 'default') {
+            if ($('.bx-sidebar-site-trigger').size())
+                bx_sidebar_toggle('site');
+            else if ($('.cd-dropdown-trigger').size())
+                $('.cd-dropdown-trigger').click();
+            else if ($('.cd-side-nav').size())
+                $([$('.cd-side-nav'), $('.cd-nav-trigger')]).toggleClass('nav-is-visible');
+            else
+                bx_menu_slide_inline('#bx-sliding-menu-sys_site', null, 'site');
+        }
+        else {
+            bx_menu_popup('__main_menu__');
+        }
+    }
+
+    function bx_mobile_apps_show_profile_menu () {
+        if ($('.bx-sidebar-account-trigger').size())
+            bx_sidebar_toggle('account');
+        else
+            bx_menu_slide_inline('#bx-sliding-menu-account', null, 'site');
+    }
+
+    function bx_mobile_apps_show_add_menu () {
+        bx_menu_slide_inline('#bx-sliding-menu-sys_add_content', null, 'site');
+    }
+
+    function bx_mobile_apps_show_notifications_menu () {
+        bx_menu_slide('bx_notifications_preview', null, 'site', {id:{value:'bx_notifications_preview', force:1}});
+    }
+
+    function bx_mobile_apps_show_messenger_menu () {
+        document.location = sUrlRoot + 'page.php?i=messenger';
+    }
+
+    function bx_mobile_apps_home () {
+        if (window.history.length > 1)
+            window.history.go(-(window.history.length - 1));
+    }
+
+    function bx_mobile_apps_close_sliding_menus () {
+        if ($('.bx-sliding-menu-main:visible').size()) // hide sliding menu if they are open
+            bx_menu_slide_inline('.bx-sliding-menu-main');
+    }
+
+    function bx_mobile_apps_video_terminated (e) {
+        if (typeof window.glBxVideoCallTerminated !== 'undefined' && window.glBxVideoCallTerminated instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallTerminated.length; i++)
+                if (typeof window.glBxVideoCallTerminated[i] === "function")
+                    window.glBxVideoCallTerminated[i](e);
+        }
+    }
+
+    function bx_mobile_apps_video_joined (e) {
+        if (typeof window.glBxVideoCallJoined !== 'undefined' && window.glBxVideoCallJoined instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallJoined.length; i++)
+                if (typeof window.glBxVideoCallJoined[i] === "function")
+                    window.glBxVideoCallJoined[i](e);
+        }
+    }
+
+    function bx_mobile_apps_video_will_join (e) {
+        if (typeof window.glBxVideoCallWillJoin !== 'undefined' && window.glBxVideoCallWillJoin instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallWillJoin.length; i++)
+                if (typeof window.glBxVideoCallWillJoin[i] === "function")
+                    window.glBxVideoCallWillJoin[i](e);
+        }
+    }
+
+    function bx_mobile_apps_post_message (oJSON) {
+        var sMsg = JSON.stringify(oJSON);
+        if ('undefined' !== typeof(window.ReactNativeWebView))
+            window.ReactNativeWebView.postMessage(sMsg);
+        else
+            window.postMessage(sMsg, '*');
+    }
+
+    bx_mobile_apps_post_message (__msg__);
+
+    if (window && window.process && window.process.type) { // if run in electron
+        const { ipcRenderer, shell } = require('electron')
+        
+        // send all notification badges
+        ipcRenderer.send('message', __msg__);
+
+        // send messenger badge
+        if (typeof window.glBxMessengerOnNotificationChange === 'undefined')
+            window.glBxMessengerOnNotificationChange = [];
+
+        window.glBxMessengerOnNotificationChange.push(function (iNewNumberOfUnreadChats) {
+            sMsg = {
+                'bubbles': {
+                    'notifications-messenger': iNewNumberOfUnreadChats,
+                },
+            };
+            ipcRenderer.send('message', sMsg);
+        });
+
+        if ($.cookie('memberID')) {
+            // force links to open in external browser in electron
+            $(document).ready(function () {
+                document.querySelector('body').addEventListener('click', event => {
+                    let link = event.target.href;
+                    if (event.target.tagName.toLowerCase() !== 'a') 
+                        return;
+                    event.preventDefault();
+                    shell.openExternal(link);
+                });
+            });
+        }
+    }
+
+    // pull to refresh
+    $(document).ready(function () {
+/*
+        if ($('.bx-messenger-block-lots').length)
+            glBxMobileDisablePullToRefresh = true;
+        if ('undefined' === typeof glBxMobileDisablePullToRefresh || false === glBxMobileDisablePullToRefresh) {
+            PullToRefresh.init({
+                instructionsPullToRefresh: '__txt_pull_to_refresh__',
+                instructionsReleaseToRefresh: '__txt_release_to_refresh__',
+                instructionsRefreshing: '__txt_refreshing__',
+                onRefresh() {
+                    window.location.reload();
+                },
+            });
+        }
+*/
+        bx_mobile_apps_post_message({stop_loading: 1});
+    });
+</script>

+ 87 - 0
modules/boonex/nexus/updates/13.0.0_13.0.1/source/template/styles.html

@@ -0,0 +1,87 @@
+<style>
+
+.bx-def-mobile-app-hide {
+    display:none !important;
+}
+.bx-def-mobile-app-show-block {
+    display:block;
+}
+
+html #bx-toolbar {
+    height:0 !important;    
+}
+html .bx-header {
+    border-bottom-width: 0 !important;
+}
+html .bx-shadow-header {
+    box-shadow: none;
+}
+html .bx-menu-toolbar-padding {
+    padding-top:0 !important;
+}
+html #bx-toolbar-content {
+    display:none !important;
+}
+html .cd-side-nav,
+html .cd-main-content .content-wrapper {
+    padding-top:0;
+}
+html .cd-main-content .content-wrapper {
+    margin-left:0;
+}
+html .bx-sliding-menu-fullheight {
+    height:100%;
+}
+html  nav.cd-stretchy-nav {
+    display:none;
+}
+html #bx-footer-wrapper {
+    display:none;
+}
+
+html .bx-decorous .cd-main-content .content-wrapper {
+    padding-top:0;
+}
+html .bx-lucid .cd-main-content .content-wrapper {
+    padding-top:0.625rem;
+}
+html .bx-protean .bx-menu-toolbar-padding {
+    padding-top:0 !important;
+}
+
+html .bx-artificer #bx_notifications_preview {
+    overflow-y:auto;
+    width:100%;
+}
+html .bx-artificer #bx_notifications_preview .bx-sliding-menu-close {
+    display:none;
+}
+html .bx-artificer .bx-ntfs-preview > .max-h-96 {
+    max-height:none;
+}
+html .bx-artificer #bx-sliding-menu-sys_add_content {
+    width:100%;
+}
+
+
+/* main menu & add content menu */
+html #bx-sliding-menu-sys_site.bx-sliding-menu-main, 
+html #bx-sliding-menu-sys_add_content.bx-sliding-menu-main, 
+html #bx-sliding-menu-account.bx-sliding-menu-main {
+    height:100%;
+    overflow-x:hidden;
+    overflow-y:auto;
+}
+html .bx-sliding-menu-main ul.bx-menu-floating-blocks-big {
+    white-space:normal;
+}
+html .bx-sliding-menu-main ul.bx-menu-floating-blocks-big {
+    text-align:center;
+}
+html .cd-side-nav,
+html .bx-sliding-menu, 
+html .bx-sliding-menu-main 
+{
+    top:0 !important;
+}
+</style>

+ 51 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Notifications',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/notifications/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'notifications_update_1301_1302',
+
+    'module_dir' => 'boonex/notifications/',
+    'module_uri' => 'notifications',
+
+    'db_prefix' => 'bx_notifications_',
+    'class_prefix' => 'BxNtfs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Notifications',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxNtfsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 5 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/install/langs/en.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_ntfs_txt_object_post_common"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string_add>
+    <string_add name="_bx_ntfs_txt_object_post_common_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> added by <b class="bx-ntfs-content-profile">{object_owner_name}</b>]]></string_add>
+</resources>

+ 405 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/source/classes/BxNtfsDb.php

@@ -0,0 +1,405 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsDb extends BxBaseModNotificationsDb
+{
+    protected $_sTableEvt2Usr;
+    protected $_sTableQueue;
+
+    /*
+     * Constructor.
+     */
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $this->_aDeliveryTypes = array(
+            BX_BASE_MOD_NTFS_DTYPE_SITE, 
+            BX_BASE_MOD_NTFS_DTYPE_EMAIL, 
+            BX_BASE_MOD_NTFS_DTYPE_PUSH
+        );
+
+        $this->_sTableEvt2Usr = $this->_sPrefix . 'events2users';
+        $this->_sTableQueue = $this->_sPrefix . 'queue';
+    }
+
+    public function markAsRead($iUserId, $iEventId)
+    {
+        $this->queueDeleteByProfile($iUserId, $iEventId);
+
+        return (int)$this->query("INSERT INTO `" . $this->_sTableEvt2Usr . "` (`user_id`, `event_id`) VALUES (:user_id, :event_id) ON DUPLICATE KEY UPDATE `event_id`=:event_id", array(
+            'user_id' => $iUserId,
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function getLastRead($iUserId)
+    {
+        return (int)$this->getOne("SELECT `event_id` FROM `" . $this->_sTableEvt2Usr . "` WHERE `user_id`=:user_id LIMIT 1", array(
+            'user_id' => (int)$iUserId
+        ));
+    }
+
+    public function deleteEvent($aParams, $sWhereAddon = "")
+    {
+        $aEvents = $this->getAll("SELECT * FROM `{$this->_sTable}` WHERE " . $this->arrayToSQL($aParams, " AND ") . $sWhereAddon);
+        if(!empty($aEvents) && is_array($aEvents)) 
+            foreach($aEvents as $aEvent)
+                $this->queueDelete(array('event_id' => $aEvent['id']));
+
+        return parent::deleteEvent($aParams, $sWhereAddon);
+    }
+
+    public function getEvents($aParams, $bReturnCount = false)
+    {
+        bx_alert($this->_oConfig->getName(), 'get_events_before', 0, 0, [
+            'params' => &$aParams,
+        ]);
+
+        if($aParams['browse'] != 'list' || $aParams['type'] != BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS)
+            return parent::getEvents($aParams);
+
+        $bCountOnly = !empty($aParams['count_only']);
+
+        //--- Get query for 'Object Owner' notifications
+        $sLimitClause = isset($aParams['per_page']) ? "LIMIT 0, " . ($aParams['start'] + $aParams['per_page']) : "";
+
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_OBJECT_OWNER;
+        list($sMethod, $sSelectClause, $sJoinClausePo, $sWhereClausePo, $sOrderClausePo) = $this->_getSqlPartsEvents($aParams);
+
+        $sQueryOwner = "SELECT {select}
+            FROM `{$this->_sTable}`
+            LEFT JOIN `{$this->_sTableHandlers}` ON `{$this->_sTable}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$this->_sTable}`.`action`=`{$this->_sTableHandlers}`.`alert_action` " . $sJoinClausePo . "
+            WHERE 1 " . $sWhereClausePo . (!$bCountOnly ? " " . $sOrderClausePo . " " . $sLimitClause : "");
+
+        //--- Get query for 'Connections based' notifications
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_CONNECTIONS;
+        list($sMethod, $sSelectClause, $sJoinClausePc, $sWhereClausePc, $sOrderClausePc) = $this->_getSqlPartsEvents($aParams);
+
+        $sQueryConnections = "SELECT {select}
+            FROM `{$this->_sTable}`
+            LEFT JOIN `{$this->_sTableHandlers}` ON `{$this->_sTable}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$this->_sTable}`.`action`=`{$this->_sTableHandlers}`.`alert_action` " . $sJoinClausePc . "
+            WHERE 1 " . $sWhereClausePc . (!$bCountOnly ? " " . $sOrderClausePc . " " . $sLimitClause : "");
+
+        //--- Combine both queries in one
+        $sUnionMethod = 'getColumn';
+        $sUnionOrderClause = $sUnionLimitClause = '';
+        if(!$bCountOnly) {
+            $sUnionMethod = $sMethod;
+            $sUnionOrderClause = "ORDER BY `date` DESC, `id` DESC";
+            $sUnionLimitClause = isset($aParams['per_page']) ? "LIMIT " . $aParams['start'] . ", " . $aParams['per_page'] : "";
+        }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['browse']);
+
+        /**
+         * Parts: 
+         * PO - notifications related to Owner's content
+         * PC - notifications related to Connections' content
+         */
+        bx_alert($this->_oConfig->getName(), 'get_events', 0, 0, [
+            'browse' => $aParams['browse'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'method' => &$sUnionMethod,
+            'select_clause' => &$sSelectClause,
+            'join_clause_po' => &$sJoinClausePo,
+            'join_clause_pc' => &$sJoinClausePc,
+            'where_clause_po' => &$sWhereClausePo,
+            'where_clause_pc' => &$sWhereClausePc,
+            'order_clause_po' => &$sOrderClausePo,
+            'order_clause_pc' => &$sOrderClausePc,
+            'order_clause' => &$sUnionOrderClause,
+            'limit_clause' => &$sUnionLimitClause,
+            'query_po' => &$sQueryOwner,
+            'query_pc' => &$sQueryConnections,
+        ]);
+
+        $sQuery = "(" . $sQueryOwner . ") UNION (" . $sQueryConnections . ") {order} {limit}";
+        $sQuery = str_replace(['{select}', '{order}', '{limit}'], [$sSelectClause, $sUnionOrderClause, $sUnionLimitClause], $sQuery);
+        $aEntries = $this->$sUnionMethod($sQuery);
+
+        if($bCountOnly)
+            $aEntries = (int)array_sum($aEntries);
+
+        return $aEntries;
+    }
+
+    protected function _getSqlPartsEvents($aParams)
+    {
+        list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
+
+        switch($aParams['browse']) {
+            case 'list':
+                if(!empty($aParams['count_only'])) {
+                    $sMethod = 'getOne';
+                    $sSelectClause = 'COUNT(DISTINCT `' . $this->_sTable . '`.`id`)';
+                }
+                else if(in_array($aParams['type'], array(BX_BASE_MOD_NTFS_TYPE_CONNECTIONS, BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS)))
+                    $sSelectClause = 'DISTINCT ' . $sSelectClause;
+
+                break;
+        }
+
+        return array($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause);
+    }
+
+    protected function _getSqlPartsEventsList($aParams)
+    {
+        $sJoinClause = $sWhereClause = "";
+
+        //--- Apply status filter
+        $sWhereClauseStatus = '';
+        if(isset($aParams['active']))
+            $sWhereClauseStatus = $this->prepareAsString("AND `{$this->_sTable}`.`active`=? ", (int)$aParams['active']);
+
+        //--- Apply modules or handlers filter
+        $sWhereClauseModules = '';
+        if(!empty($aParams['modules']) && is_array($aParams['modules']))
+            $sWhereClauseModules = "AND `" . $this->_sTable . "`.`type` IN (" . $this->implode_escape($aParams['modules']) . ") ";
+
+        if($sWhereClauseModules == '') {
+            $aHidden = $this->_oConfig->getHandlersHidden();
+            $sWhereClauseModules = !empty($aHidden) && is_array($aHidden) ? "AND `" . $this->_sTableHandlers . "`.`id` NOT IN (" . $this->implode_escape($aHidden) . ") " : "";
+        }
+
+        //--- Check flag 'New'
+        $sWhereClauseNew = '';
+        if(!empty($aParams['new']) && !empty($aParams['owner_id']))
+            $sWhereClauseNew = $this->prepareAsString("AND `{$this->_sTable}`.`id`>? ", $this->getLastRead((int)$aParams['owner_id']));
+
+        //--- Check type
+        $sWhereClauseSettings = $sWhereClauseType = '';
+        if(!empty($aParams['owner_id']))
+            switch($aParams['type']) {
+                /*
+                 * Note. It isn't used for now and outdated.
+                 */
+                case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                    $sWhereClauseType = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['owner_id']);
+                    break;
+
+                case BX_BASE_MOD_NTFS_TYPE_OBJECT_OWNER:
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND `{$this->_sTableSettings}`.`type`=?", BX_NTFS_STYPE_PERSONAL);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClauseSettings = "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClauseType = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`<>`{$this->_sTable}`.`object_owner_id` AND ((`{$this->_sTable}`.`owner_id`=? AND `{$this->_sTable}`.`object_privacy_view`<0 AND `{$this->_sTable}`.`owner_id`=ABS(`{$this->_sTable}`.`object_privacy_view`)) OR `{$this->_sTable}`.`object_owner_id`=?) ", $aParams['owner_id'], $aParams['owner_id']);
+                    break;
+
+                case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                    $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+                    $aQueryParts = $oConnection->getConnectedContentAsSQLParts($this->_sPrefix . "events", 'owner_id', $aParams['owner_id']);
+                    if(empty($aQueryParts) || !is_array($aQueryParts) || empty($aQueryParts['join']))
+                        break;
+
+                    $sJoinClause .= " LEFT JOIN `sys_profiles` AS `tsp` ON `{$this->_sTable}`.`owner_id`=`tsp`.`id` " . $aQueryParts['join'];
+
+                    $sWhereClauseType = '';
+                    if(!empty($aQueryParts['fields']['added']))
+                        $sWhereClauseType = "AND `{$this->_sTable}`.`date` > " . $aQueryParts['fields']['added'];
+
+                    list($aModulesProfiles, $aModulesContexts) = $this->_oConfig->getProfileBasedModules();
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND ((`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesProfiles) . ")) || (`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesContexts) . ")))", BX_NTFS_STYPE_FOLLOW_MEMBER, BX_NTFS_STYPE_FOLLOW_CONTEXT);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClauseSettings = "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+                    break;
+
+                case BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS:
+                    /**
+                     * 'personal' notifications are taken by: 
+                     * 1. 'owner_id', in case of somebody performed an action in requested profile's context
+                     * 'object_privacy_view' < 0 AND 'owner_id' == ABS('object_privacy_view'))
+                     * Currently it happens when somebody posted a Direct Timeline post in requested profile.
+                     * 2. 'object_owner_id', in case of somebody performed an action with content 
+                     * owned by the requested profile.
+                     */
+                    $sWhereClauseObjectOwner = $this->prepareAsString("`{$this->_sTable}`.`owner_id` <> `{$this->_sTable}`.`object_owner_id` AND ((`{$this->_sTable}`.`owner_id`=? AND `{$this->_sTable}`.`object_privacy_view`<0 AND `{$this->_sTable}`.`owner_id`=ABS(`{$this->_sTable}`.`object_privacy_view`)) OR `{$this->_sTable}`.`object_owner_id`=?) ", $aParams['owner_id'], $aParams['owner_id']);
+
+                    /**
+                     * 'follow' notifications are taken by connection with `owner_id`
+                     */
+                    $sWhereClauseConnections = '0';
+                    $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+                    $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sTable, 'owner_id', $aParams['owner_id']);
+                    if(!empty($aQueryParts) && is_array($aQueryParts) && !empty($aQueryParts['join'])) {
+                        $sJoinClause .= " LEFT JOIN `sys_profiles` AS `tsp` ON `{$this->_sTable}`.`owner_id`=`tsp`.`id`";
+                        $sJoinClause .= " LEFT JOIN `" . $aQueryParts['join']['table'] . "` AS `" . $aQueryParts['join']['table_alias'] . "` ON (" . $aQueryParts['join']['condition'] . ")";
+
+                        $sWhereClauseConnections = "NOT ISNULL(`c`.`content`) ";
+                        if(!empty($aQueryParts['fields']['added']))
+                            $sWhereClauseConnections .= "AND `{$this->_sTable}`.`date` > `" . $aQueryParts['fields']['added']['table_alias'] . "`.`" . $aQueryParts['fields']['added']['name'] . "` ";
+                    }
+
+                    list($aModulesProfiles, $aModulesContexts) = $this->_oConfig->getProfileBasedModules();
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND (`{$this->_sTableSettings}`.`type`=? OR ((`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesProfiles) . ")) || (`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesContexts) . "))))", BX_NTFS_STYPE_PERSONAL, BX_NTFS_STYPE_FOLLOW_MEMBER, BX_NTFS_STYPE_FOLLOW_CONTEXT);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClauseSettings = "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClauseType = "AND ((" . $sWhereClauseObjectOwner . ") OR (" . $sWhereClauseConnections . ")) ";
+                    break;
+            }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['type'], $aAlertParams['owner_id']);
+
+        bx_alert($this->_oConfig->getName(), 'get_list_by_type', 0, 0, [
+            'type' => $aParams['type'],
+            'owner_id' => $aParams['owner_id'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'join_clause' => &$sJoinClause,
+            'where_clause' => &$sWhereClause,
+            'where_clause_status' => &$sWhereClauseStatus,
+            'where_clause_modules' => &$sWhereClauseModules,
+            'where_clause_new' => &$sWhereClauseNew,
+            'where_clause_settings' => &$sWhereClauseSettings,
+            'where_clause_type' => &$sWhereClauseType
+        ]);
+
+        $sWhereClause .= $sWhereClauseStatus;
+        $sWhereClause .= $sWhereClauseModules;
+        $sWhereClause .= $sWhereClauseNew;
+        $sWhereClause .= $sWhereClauseSettings;
+        $sWhereClause .= $sWhereClauseType;
+
+        return [$sJoinClause, $sWhereClause];
+    }
+
+    public function getEventsToProcess($iLimit = 0)
+    {
+        $aEvents = $this->getAll("SELECT * FROM `" . $this->_sTable . "` WHERE `id`>:id ORDER BY `id` ASC" . ($iLimit != 0 ? ' LIMIT ' . $iLimit : ''), array(
+            'id' => $this->_oConfig->getProcessedEvent()
+        ));
+
+        if(!empty($aEvents) && is_array($aEvents)) {
+            $aEventEnd = end($aEvents);
+
+            $this->_oConfig->setProcessedEvent($aEventEnd['id']);
+
+            reset($aEvents);
+        }
+
+        return $aEvents;
+    }
+
+    public function queueGet($aParams)
+    {
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "*";
+    	$sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['type']) {
+            case 'count':
+            	$aMethod['name'] = 'getOne';
+
+                $sSelectClause = "COUNT(*)";
+                break;
+
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `id`=:id";
+                break;
+
+            case 'all_to_send':
+                $aMethod['name'] = 'getAllWithKey';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = array(
+                    'timeout' => $aParams['timeout']
+                );
+
+                $sWhereClause = " AND `date`+:timeout < UNIX_TIMESTAMP()";
+                $sOrderClause = "`date` ASC";
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : $sOrderClause;
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $this->_sTableQueue . "`
+            WHERE 1" . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function queueAdd($aSet)
+    {
+        if(empty($aSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `" . $this->_sTableQueue . "` SET " . $this->arrayToSQL($aSet)) > 0;
+    }
+
+    public function queueDelete($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ')) > 0;
+    }
+
+    public function queueDeleteByProfile($iProfileId, $iEventId)
+    {
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE `profile_id`=:profile_id AND `event_id`<=:event_id", array(
+            'profile_id' => $iProfileId,
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function queueDeleteByIds($mixedId)
+    {
+        if(empty($mixedId))
+            return false;
+
+        if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+    
+    public function cleanEvents($iClearIntervalInDays)
+    {
+        $this->query("DELETE FROM `{$this->_sTable}` WHERE `date` < :date", array('date' => time() - $iClearIntervalInDays * 86400));
+    }   
+
+    public function filterProfileIdsByModule($aIds, $mixedModule)
+    {
+        if(!is_array($mixedModule))
+            $mixedModule = array($mixedModule);
+
+        return $this->getColumn("SELECT `id` FROM `sys_profiles` WHERE `id` IN (" . $this->implode_escape($aIds) . ") AND `type` IN (" . $this->implode_escape($mixedModule) . ")");
+    }
+}
+
+/** @} */

+ 82 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_notifications',
+    'title' => 'Notifications',
+    'note' => 'Notifications module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/notifications/',
+    'home_uri' => 'notifications',
+
+    'db_prefix' => 'bx_notifications_',
+    'class_prefix' => 'BxNtfs',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Notifications',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations_for_all' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations_for_all' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relation_handlers' => array(
+    	'on_install' => '',
+    	'on_uninstall' => 'delete_module_events',
+	    'on_enable' => 'add_handlers',
+	    'on_disable' => 'delete_handlers',
+    ),
+);
+
+/** @} */

+ 139 - 0
modules/boonex/notifications/updates/13.0.1_13.0.2/source/install/langs/en.xml

@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_ntfs"><![CDATA[Notifications]]></string>
+    <string name="_bx_notifications"><![CDATA[Notifications]]></string>
+
+    <string name="_bx_ntfs_page_title_system_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_title_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_block_title_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_title_system_settings"><![CDATA[Notifications Settings]]></string>
+    <string name="_bx_ntfs_page_title_settings"><![CDATA[Notifications Settings]]></string>
+    <string name="_bx_ntfs_page_block_title_delivery"><![CDATA[Receive via]]></string>
+    <string name="_bx_ntfs_page_block_title_settings"><![CDATA[Notifications]]></string>
+
+    <string name="_bx_ntfs_menu_title_submenu"><![CDATA[Notifications Submenu]]></string>
+    <string name="_bx_ntfs_menu_set_title_submenu"><![CDATA[Notifications Submenu]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_all"><![CDATA[All Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_all"><![CDATA[All Notifications]]></string>
+    <string name="_bx_ntfs_menu_title_settings"><![CDATA[Settings Submenu]]></string>
+    <string name="_bx_ntfs_menu_set_title_settings"><![CDATA[Settings Submenu]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_preview"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_preview"><![CDATA[]]></string>
+
+    <string name="_bx_ntfs_menu_title_preview"><![CDATA[Notifications Preview]]></string>
+    <string name="_bx_ntfs_menu_set_title_preview"><![CDATA[Notifications Preview]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_more"><![CDATA[See all notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_more"><![CDATA[See all notifications]]></string>
+    <string name="_bx_ntfs_lmi_cpt_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_lmi_cpt_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_lmi_cpt_push"><![CDATA[Push]]></string>
+
+    <string name="_bx_ntfs_options_category_system"><![CDATA[System]]></string>
+    <string name="_bx_ntfs_option_events_per_page"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_ntfs_option_events_per_preview"><![CDATA[Number of items in preview]]></string>
+    <string name="_bx_ntfs_option_events_hide_site"><![CDATA[Onsite notifications]]></string>
+    <string name="_bx_ntfs_option_events_hide_email"><![CDATA[Email notifications]]></string>
+    <string name="_bx_ntfs_option_events_hide_push"><![CDATA[Push notifications]]></string>
+    <string name="_bx_ntfs_option_enable_group_settings"><![CDATA[Group Settings]]></string>
+    <string name="_bx_ntfs_option_delivery_timeout"><![CDATA[Delay before sending Email and/or Push notifications (in seconds)]]></string>
+    <string name="_bx_ntfs_option_processed_event"><![CDATA[The last processed event upon notifications sending]]></string>
+    <string name="_bx_ntfs_option_clear_interval"><![CDATA[Notification lifetime, in days (0 - no limit)]]></string>
+
+    <string name="_bx_ntfs_privacy_view"><![CDATA[View event]]></string>
+
+    <string name="_bx_ntfs_alert_action_group_content_updated"><![CDATA[Content was updated]]></string>
+    <string name="_bx_ntfs_alert_action_group_action_required"><![CDATA[Your action required]]></string>
+
+    <string name="_bx_ntfs_alert_action_added"><![CDATA[add]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost"><![CDATA[add comment]]></string>
+    <string name="_bx_ntfs_alert_action_replyPost"><![CDATA[reply to own comment]]></string>
+    <string name="_bx_ntfs_alert_action_doVote"><![CDATA[add vote]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common"><![CDATA[post to timeline]]></string>
+    <string name="_bx_ntfs_alert_action_mention_added_personal"><![CDATA[Someone mentions you]]></string>
+    <string name="_bx_ntfs_alert_action_friendship_added_personal"><![CDATA[You get a new friend]]></string>
+    <string name="_bx_ntfs_alert_action_subscription_added_personal"><![CDATA[You get a new follower]]></string>
+    <string name="_bx_ntfs_alert_action_added_follow_member"><![CDATA[New content]]></string>
+    <string name="_bx_ntfs_alert_action_added_follow_context"><![CDATA[New content]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_personal"><![CDATA[Someone adds a comment on your content]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_follow_member"><![CDATA[New comments]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_follow_context"><![CDATA[New comments]]></string>
+    <string name="_bx_ntfs_alert_action_replyPost_personal"><![CDATA[Someone adds a reply to your comment]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_personal"><![CDATA[Someone adds a like to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_follow_member"><![CDATA[New likes]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_follow_context"><![CDATA[New likes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_personal"><![CDATA[Someone adds an 'Up' vote to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_follow_member"><![CDATA[New 'Up' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_follow_context"><![CDATA[New 'Up' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_personal"><![CDATA[Someone adds a 'Down' vote to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_follow_member"><![CDATA[New 'Down' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_follow_context"><![CDATA[New 'Down' votes]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_personal"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_follow_member"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_follow_context"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_personal"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_follow_member"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_follow_context"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_invitation_notif_personal"><![CDATA[New join invitation]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_personal"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_follow_member"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_follow_context"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_publish_failed_personal"><![CDATA[Delayed publishing failed]]></string>
+    <string name="_bx_ntfs_alert_action_publish_succeeded_personal"><![CDATA[Delayed publishing succeeded]]></string>
+    <string name="_bx_ntfs_alert_action_pending_approval_personal"><![CDATA[New pending approval content]]></string>
+    <string name="_bx_ntfs_alert_action_approved_personal"><![CDATA[Your content was approved]]></string>
+
+    <string name="_bx_ntfs_setting_title_mask"><![CDATA[{0}: {1}]]></string>
+    <string name="_bx_ntfs_setting_type_personal"><![CDATA[Activity related to you]]></string>
+    <string name="_bx_ntfs_setting_type_follow_member"><![CDATA[Activity by members you follow]]></string>
+    <string name="_bx_ntfs_setting_type_follow_context"><![CDATA[Activity in spaces (groups, events, etc.) you follow]]></string>
+    <string name="_bx_ntfs_setting_type_other"><![CDATA[Other Activity]]></string>
+
+    <string name="_bx_ntfs_alert_module_sys_cmts"><![CDATA[Comments]]></string>
+    <string name="_bx_ntfs_alert_module_sys_cmts_reactions"><![CDATA[Comments' Reactions]]></string>
+    <string name="_bx_ntfs_alert_module_meta_mention"><![CDATA[Profiles Mentions]]></string>
+    <string name="_bx_ntfs_alert_module_sys_profiles_subscriptions"><![CDATA[Profiles Subscriptions]]></string>
+    <string name="_bx_ntfs_alert_module_sys_profiles_friends"><![CDATA[Profiles Friends]]></string>
+    <string name="_bx_ntfs_alert_action_connection_added"><![CDATA[add connection]]></string>
+
+    <string name="_bx_ntfs_txt_msg_no_results"><![CDATA[Empty]]></string>
+    <string name="_bx_ntfs_txt_err_nothing_changed"><![CDATA[Nothing was changed.]]></string>
+    <string name="_bx_ntfs_txt_err_cannot_perform"><![CDATA[Cannot perform the action.]]></string>
+    <string name="_bx_ntfs_txt_object_added"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_added_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> added by <b class="bx-ntfs-content-profile">{object_owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_post_common"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_post_common_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> added by <b class="bx-ntfs-content-profile">{object_owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_approved"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> approved {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_approved_in_context"><![CDATA[<b class="bx-ntfs-content-entry">{entry_caption}</b> {entry_sample} was approved in <b class="bx-ntfs-content-profile">{owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_publish_failed"><![CDATA[Failed to publish your {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_publish_succeeded"><![CDATA[Your {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> was published successfully]]></string>
+    <string name="_bx_ntfs_txt_object_pending_approval"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a pending approval {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_subobject_added"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_subobject_added_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ntfs_push_new_event_subject"><![CDATA[New on "{0}"]]></string>
+
+    <string name="_bx_ntfs_email_new_event"><![CDATA[New notification]]></string>
+    <string name="_bx_ntfs_email_new_event_subject"><![CDATA[New notification on "{site_name}"]]></string>
+    <string name="_bx_ntfs_email_new_event_body"><![CDATA[{email_header}
+<p> </p>
+{content}
+<p> </p>
+{email_footer}]]></string>
+
+    <string name="_bx_ntfs_grid_column_title_active"><![CDATA[Active]]></string>
+    <string name="_bx_ntfs_grid_column_title_unit"><![CDATA[Module]]></string>
+    <string name="_bx_ntfs_grid_column_title_type"><![CDATA[Type]]></string>
+    <string name="_bx_ntfs_grid_column_title_title"><![CDATA[Notification]]></string>
+    <string name="_bx_ntfs_grid_column_title_title_warning"><![CDATA[The setting's value is corrupted. It is recommended to enable/disable it and reload the page.]]></string>
+    <string name="_bx_ntfs_grid_column_title_value"><![CDATA[Default value]]></string>
+    <string name="_bx_ntfs_grid_action_title_activate"><![CDATA[Activate]]></string>
+    <string name="_bx_ntfs_grid_action_title_deactivate"><![CDATA[Deactivate]]></string>
+</resources>

+ 51 - 0
modules/boonex/ocean/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Ocean',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/ocean/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'ocean_update_1301_1302',
+
+    'module_dir' => 'boonex/ocean/',
+    'module_uri' => 'ocean',
+
+    'db_prefix' => 'bx_ocean_',
+    'class_prefix' => 'BxOcean',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'BoonEx Ocean',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 26 - 0
modules/boonex/ocean/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxOceanUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function update($aParams)
+    {
+        $aResult = parent::update($aParams);
+        if(!$aResult['result'])
+            return $aResult;
+
+        $oCacheUtilities = BxDolCacheUtilities::getInstance();
+        $oCacheUtilities->clear('css');
+        $oCacheUtilities->clear('template');
+
+        return $aResult;
+    }
+}

+ 20 - 0
modules/boonex/ocean/updates/13.0.1_13.0.2/source/data/template/system/css/editor.less

@@ -0,0 +1,20 @@
+@import '../../../../../../../template/css/editor.less';
+
+.ql-toolbar.ql-snow{
+    border-radius: 0.3rem 0.3rem 0 0 !important;
+}
+.ql-toolbar.ql-snow,
+.ql-container.ql-snow{
+    border-color: #6097b0 !important; 
+    border-width:2px !important;
+}
+
+.bx-form-input-html-quill-empty.ql-container{
+    border-radius: 0.3rem !important;
+    border-top: 2px solid rgb(96, 151, 176) !important;
+}
+
+.ql-editor{
+	min-height: 95px;
+}
+

+ 68 - 0
modules/boonex/ocean/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Ocean Ocean Template
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_TEMPLATE,
+    'name' => 'bx_ocean',
+    'title' => 'Ocean',
+    'note' => 'Design template',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/ocean/',
+    'home_uri' => 'ocean',
+
+    'db_prefix' => 'bx_ocean_',
+    'class_prefix' => 'BxOcean',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'BoonEx Ocean',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'clear_db_cache' => 1
+    ),
+    'enable' => array(
+        'execute_sql' => 1
+    ),
+    'disable' => array(
+        'execute_sql' => 1
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/payment/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Payment',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/payment/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'payment_update_1301_1302',
+
+    'module_dir' => 'boonex/payment/',
+    'module_uri' => 'payment',
+
+    'db_prefix' => 'bx_payment_',
+    'class_prefix' => 'BxPayment',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Payment',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/payment/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxPaymentUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 337 - 0
modules/boonex/payment/updates/13.0.1_13.0.2/source/classes/BxPaymentConfig.php

@@ -0,0 +1,337 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentConfig extends BxBaseModPaymentConfig
+{
+    protected $_bCreditsOnly;
+
+    protected $_iPayAttemptsMax;
+    protected $_iPayAttemptsInterval;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $sBaseUrl = BX_DOL_URL_ROOT . $this->getBaseUri();
+
+        $this->CNF = array_merge($this->CNF, array(
+            // module icon
+            'ICON' => 'credit-card col-gray-dark',
+
+            // database tables
+            'TABLE_COMMISSIONS' => $aModule['db_prefix'] . 'commissions',
+            'TABLE_INVOICES' => $aModule['db_prefix'] . 'invoices',
+
+            // page URIs
+            'URL_JOIN' => 'page.php?i=payment-join',
+            'URL_CARTS' => 'page.php?i=payment-carts',
+            'URL_CART' => 'page.php?i=payment-cart',
+            'URL_CART_CHECKOUT' => $sBaseUrl . 'initialize_checkout/' . BX_PAYMENT_TYPE_SINGLE . '/',
+            'URL_SUBSCRIBE' => $sBaseUrl . 'subscribe/',
+            'URL_SUBSCRIBE_JSON' => $sBaseUrl . 'subscribe_json/',
+            'URL_SUBSCRIPTIONS' => 'page.php?i=payment-sbs-list-my',
+            'URL_HISTORY' => 'page.php?i=payment-history',
+            'URL_ORDERS' => 'page.php?i=payment-orders',
+            'URL_INVOICES' => 'page.php?i=payment-invoices',
+            'URL_DETAILS' => 'page.php?i=payment-details',
+            'URL_RETURN' => 'page.php?i=payment-cart-thank-you',
+            'URL_RETURN_DATA' => $sBaseUrl . 'finalize_checkout/',
+            'URL_NOTIFY' => $sBaseUrl . 'notify/',
+            'URL_CHECKOUT_OFFLINE' => 'page.php?i=payment-checkout-offline',
+
+            'KEY_ARRAY_PRICE_SINGLE' => 'price_single',
+            'KEY_ARRAY_PRICE_RECURRING' => 'price_recurring',
+            'KEY_ARRAY_TRIAL_RECURRING' => 'trial_recurring',
+
+            // some params
+            'PARAM_CMSN_INVOICE_ISSUE_DAY' => 'bx_payment_inv_issue_day', //some day of month
+            'PARAM_CMSN_INVOICE_LIFETIME' => 'bx_payment_inv_lifetime', //in days
+            'PARAM_CMSN_INVOICE_EXPIRATION_NOTIFY' => 'bx_payment_inv_expiraction_notify', //in days, before expiration date
+
+            // objects
+            'OBJECT_FORM_PRELISTS_CURRENCIES' => 'bx_payment_currencies',
+            'OBJECT_PP_OFFLINE' => 'offline', //Offline payment provider
+            'OBJECT_PP_CREDITS' => 'credits', //Credits payment provider
+
+            'MODULE_CREDITS' => 'bx_credits',
+
+            // some language keys
+            'T' => array(
+                'MSG_ITEM_ADDED' => '_bx_payment_msg_item_added',
+                'MSG_ITEM_DELETED' => '_bx_payment_msg_item_deleted',
+                'MSG_SINGLE_SELLER_MODE' => '_bx_payment_msg_single_seller',
+                'ERR_WRONG_DATA' => '_bx_payment_err_wrong_data',
+                'ERR_REQUIRED_LOGIN' => '_bx_payment_err_required_login',
+                'ERR_NOT_ACCEPT_PAYMENTS' => '_bx_payment_err_not_accept_payments',
+                'ERR_SELF_PURCHASE' => '_bx_payment_err_self_purchase',
+                'ERR_INACTIVE_VENDOR' => '_bx_payment_err_inactive_vendor',
+                'ERR_UNKNOWN_VENDOR' => '_bx_payment_err_unknown_vendor',
+
+                'BLOCK_TITLE_CART' => '_bx_payment_page_block_title_cart',
+
+                'POPUP_PROVIDERS_SELECT' => '_bx_payment_popup_title_crd_providers_select', 
+
+                'TXT_CART_PROVIDER' => '_bx_payment_txt_cart_'
+            )
+        ));
+
+        $this->_aHtmlIds = array(
+            'cart' => array(
+                'providers_select' => $this->_sName . '-cart-providers-select-',
+            ),
+            'history' => array(
+                'order_history_view' => $this->_sName . '-order-view-history',
+            ),
+            'subscription' => array(
+                'order_subscription_view' => $this->_sName . '-order-view-subscription',
+                'order_subscription_get_details' => $this->_sName . '-order-get-details-subscription',
+                'order_subscription_change_details' => $this->_sName . '-order-change-details-subscription',
+                'order_subscription_get_billing' => $this->_sName . '-order-get-billing-subscription',
+                'order_subscription_change_billing' => $this->_sName . '-order-change-billing-subscription',
+                'form_subscription_change_billing' => $this->_sName . '-form-change-billing-subscription',
+                'form_subscription_change_details' => $this->_sName . '-form-change-details-subscription',
+            ),
+            'pending' => array(
+                'order_pending_view' => $this->_sName . '-order-view-pending',
+                'order_pending_process' => $this->_sName . '-order-process',
+            ),
+            'processed' => array(
+                'order_processed_view' => $this->_sName . '-order-view-processed',
+                'order_processed_add' => $this->_sName . '-order-add',
+                'order_processed_client_id' => $this->_sName . '-oa-client-id',
+                'order_processed_client' => $this->_sName . '-oa-client',
+                'order_processed_items' => $this->_sName . '-oa-items',	
+            ),
+            'commission' => array(
+                'popup_add' => $this->_sName . '-commission-popup-add',
+                'popup_edit' => $this->_sName . '-commission-popup-edit',
+            ),
+            'invoice' => array(
+                'popup_edit' => $this->_sName . '-invoice-popup-edit',
+            )
+        );
+
+        $this->_aPerPage = array(
+            'orders' => 10,
+            'history' => 10
+        );
+        $this->_aHandlers = array();
+
+        $this->_aJsClasses = array(
+            'cart' => 'BxPaymentCart',
+            'history' => 'BxPaymentOrders',
+            'subscription' => 'BxPaymentSubscriptions',
+            'pending' => 'BxPaymentOrders',
+            'processed' => 'BxPaymentOrders',
+            'chargebee_v3' => 'BxPaymentProviderChargebeeV3',
+            'stripe' => 'BxPaymentProviderStripe',
+            'stripe_v3' => 'BxPaymentProviderStripeV3'
+        );
+
+        $this->_aJsObjects = array(
+            'cart' => 'oPaymentCart',
+            'history' => 'oPaymentOrders',
+            'subscription' => 'oBxPaymentSubscriptions',
+            'pending' => 'oPaymentOrders',
+            'processed' => 'oPaymentOrders',
+            'chargebee_v3' => 'oPaymentProviderChargebeeV3',
+            'stripe' => 'oPaymentProviderStripe',
+            'stripe_v3' => 'oPaymentProviderStripeV3'
+        );
+
+        $this->_bCreditsOnly = false;
+
+        $this->_iPayAttemptsMax = 3;
+        $this->_iPayAttemptsInterval = 86400; //--- in sec
+    }
+
+    public function init(&$oDb)
+    {
+        parent::init($oDb);
+
+        $sPrefix = $this->getPrefix('options');
+
+        $this->_bCreditsOnly = $this->_oDb->getParam($sPrefix . 'credits_only') == 'on';
+    }
+
+    public function isCreditsOnly()
+    {
+        return $this->_bCreditsOnly;
+    }
+
+    public function getPayAttemptsMax()
+    {
+        return $this->_iPayAttemptsMax;
+    }
+
+    public function getPayAttemptsInterval()
+    {
+        return $this->_iPayAttemptsInterval;
+    }
+
+    public function getPrice($sType, $aItem)
+    {
+    	$fPrice = 0;
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_SINGLE')];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_RECURRING')];
+                break;
+        }
+
+        return (float)$fPrice;
+    }
+
+    public function getTrial($sType, $aItem)
+    {
+        $iTrial = 0;
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_RECURRING:
+                $iTrial = $aItem[$this->getKey('KEY_ARRAY_TRIAL_RECURRING')];
+                break;
+        }
+
+        return (int)$iTrial;
+    }
+
+    public function getModuleId($mixedId)
+    {
+        if(is_numeric($mixedId))
+            return (int)$mixedId;
+
+        if(is_string($mixedId)) {
+            $aInfo = $this->_oDb->getModuleByName($mixedId);
+            if(!is_array($aInfo) || empty($aInfo['id']))
+                $aInfo = $this->_oDb->getModuleByUri($mixedId);
+
+            if(is_array($aInfo) && !empty($aInfo['id']))
+                return (int)$aInfo['id'];
+        } 
+
+        return 0;
+    }
+
+    public function a2s($a)
+    {
+        return base64_encode(serialize($a));
+    }
+
+    public function s2a($s)
+    {
+        return unserialize(base64_decode($s));
+    }
+            
+    public function descriptorA2S($a) 
+    {
+    	return implode($this->getDivider('DIVIDER_DESCRIPTOR'), $a);
+    }
+
+    public function descriptorS2A($s) 
+    {
+    	return explode($this->getDivider('DIVIDER_DESCRIPTOR'), $s);
+    }
+
+    public function descriptorsA2S($a) 
+    {
+    	return implode($this->getDivider('DIVIDER_DESCRIPTORS'), $a);
+    }
+
+    /**
+     * Conver items to array with necessary structure.
+     *
+     * @param  string/array $mixed - string with cart items divided with (:) or an array of cart items.
+     * @return array        with items.
+     */
+    public function descriptorsM2A($mixed)
+    {
+        $aResults = array();
+
+        if(is_string($mixed))
+           $aItems = explode($this->getDivider('DIVIDER_DESCRIPTORS'), $mixed);
+        else if(is_array($mixed))
+           $aItems = $mixed;
+        else
+            $aItems = array();
+
+        foreach($aItems as $mixedItem) {
+            $aItem = is_array($mixedItem) ? $mixedItem : $this->descriptorS2A($mixedItem);
+
+            $aResult = array('vendor_id' => $aItem[0], 'module_id' => $aItem[1], 'item_id' => $aItem[2], 'item_count' => $aItem[3]);
+            if(isset($aItem[4]))
+                $aResult['item_addons'] = $aItem[4];
+
+            $aResults[] = $aResult;
+        }
+
+        return $aResults;
+    }
+
+    public function putCustom($mDsc, $aCustom, &$aCustoms)
+    {
+        if(empty($aCustom) || !is_array($aCustom))
+            return;
+
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        $aCustoms[$mDsc] = !empty($aCustoms[$mDsc]) && is_array($aCustoms[$mDsc]) ? array_merge($aCustoms[$mDsc], $aCustom) : $aCustom;
+    }
+
+    public function getCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        return $aCustoms[$mDsc];
+    }
+
+    public function pullCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        $aResult = $aCustoms[$mDsc];
+        unset($aCustoms[$mDsc]);           
+
+        return $aResult;
+    }
+
+    public function http2https($s)
+    {
+    	if(strncmp($s, 'https://', 8) === 0)
+    		return $s;
+
+        return 'https://' . bx_ltrim_str($s, 'http://');
+    }
+
+    public function sortByColumn($sColumn, &$aValues)
+    {
+        return usort($aValues, function($aV1, $aV2) use ($sColumn) {
+            if($aV1[$sColumn] == $aV2[$sColumn])
+                return 0;
+
+            return $aV1[$sColumn] < $aV2[$sColumn] ? -1 : 1;
+        });
+    }
+}
+
+/** @} */

+ 610 - 0
modules/boonex/payment/updates/13.0.1_13.0.2/source/classes/BxPaymentProviderStripeV3.php

@@ -0,0 +1,610 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once('BxPaymentProviderStripeBasic.php');
+
+class BxPaymentProviderStripeV3 extends BxPaymentProviderStripeBasic implements iBxBaseModPaymentProvider
+{
+    protected $_oStripe;
+
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+
+        $this->_aIncludeJs = array(
+            'stripe_v3.js'
+        );
+
+        $this->_oStripe = null;
+    }
+
+    public function actionGetSessionRecurring()
+    {
+        $aClient = $this->_oModule->getProfileInfo();
+
+        $aParams = array(
+            'seller_id' => (int)bx_get('seller_id'),
+            'seller_provider' => bx_process_input(bx_get('seller_provider')),
+            'module_id' => (int)bx_get('module_id'),
+            'item_id' => (int)bx_get('item_id'),
+            'item_count' => (int)bx_get('item_count'),
+            'item_addons' => bx_get('item_addons'),
+            'redirect' => bx_process_input(bx_get('redirect')),
+            'custom' => bx_process_input(bx_get('custom')),
+        );
+
+        $aItems = array($this->_oModule->_oConfig->descriptorA2S(array(
+            'seller_id' => $aParams['seller_id'],
+            'module_id' => $aParams['module_id'],
+            'item_id' => $aParams['item_id'],
+            'item_count' => $aParams['item_count'],
+        )));
+
+        $oCart = $this->_oModule->getObjectCart();
+        $aCartInfo = $oCart->getInfo(BX_PAYMENT_TYPE_RECURRING, $aClient['id'], $aParams['seller_id'], $aItems);
+        if(empty($aCartInfo) || !is_array($aCartInfo))
+            return echoJson(array('msg' => _t('_bx_payment_err_nothing_selected')));
+
+        $aItem = reset($aCartInfo['items']);
+
+        $aSessionParams = array(
+            'cancel_url' => $aItem['url'],
+            'success_url' => bx_append_url_params($this->_oModule->_oConfig->getUrl('URL_SUBSCRIBE_JSON'), array_merge($aParams, array(
+                'session_id' => '{CHECKOUT_SESSION_ID}'
+            )))
+        );
+
+        $sSessionId = $this->_createSession(BX_PAYMENT_TYPE_RECURRING, $aSessionParams, $aClient, $aCartInfo);
+        if($sSessionId === false)
+            return echoJson(array('msg' => _t('_bx_payment_err_cannot_perform')));
+
+        $sJsObject = $this->getJsObject(array(
+            'iModuleId' => $aParams['module_id'],
+            'iSellerId' => $aParams['seller_id'],
+            'iItemId' => $aParams['item_id']
+        ));
+
+        return echoJson(array(
+            'code' => 0, 
+            'session_id' => $sSessionId,
+            'eval' => $sJsObject . '.onSubscribe(oData);'
+        ));
+    }
+
+    public function initializeCheckout($iPendingId, $aCartInfo, $sRedirect = '')
+    {
+        $sSessionId = bx_process_input(bx_get('session_id'));
+
+    	if(empty($aCartInfo['items']) || !is_array($aCartInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_items';
+
+        $aClient = $this->_oModule->getProfileInfo();
+        $aVendor = $this->_oModule->getProfileInfo($aCartInfo['vendor_id']);
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return $this->_sLangsPrefix . 'err_already_processed';
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $mixedResult = $this->_getSession(BX_PAYMENT_TYPE_SINGLE, $sSessionId);
+                if($mixedResult === false || $mixedResult['status'] != 'paid')
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                header("Location: " . $this->getReturnDataUrl($aVendor['id'], array(
+                    'order_id' => $mixedResult['order_id'],
+                    'customer_id' => $mixedResult['customer_id'], 
+                    'pending_id' => $aPending['id'],
+                    'redirect' => $sRedirect
+                )));
+                exit;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $mixedResult = $this->_getSession(BX_PAYMENT_TYPE_RECURRING, $sSessionId);
+                if($mixedResult === false)
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                header("Location: " . $this->getReturnDataUrl($aVendor['id'], array(
+                    'order_id' => $mixedResult['order_id'],
+                    'customer_id' => $mixedResult['customer_id'],
+                    'pending_id' => $aPending['id'],
+                    'redirect' => $sRedirect
+                )));
+                exit;
+        }
+    }
+
+    public function finalizeCheckout(&$aData)
+    {
+    	$sOrderId = bx_process_input($aData['order_id']);
+    	$sCustomerId = bx_process_input($aData['customer_id']);
+        $iPendingId = bx_process_input($aData['pending_id'], BX_DATA_INT);
+        if(empty($iPendingId))
+            return array('code' => 1, 'message' => $this->_sLangsPrefix . 'err_wrong_data');
+
+        $sRedirect = bx_process_input($aData['redirect']);
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return array('code' => 3, 'message' => $this->_sLangsPrefix . 'err_already_processed');
+
+        $aResult = array(
+            'code' => BX_PAYMENT_RESULT_SUCCESS,
+            'message' => '',
+            'pending_id' => $iPendingId,
+            'customer_id' => '',
+            'subscription_id' => '',
+            'client_name' => '',
+            'client_email' => '',
+            'paid' => false,
+            'trial' => false,
+            'redirect' => $sRedirect
+        );
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $oCustomer = $this->_retrieveCustomer(BX_PAYMENT_TYPE_SINGLE, $sCustomerId);
+                $oPaymentIntent = $this->_retrievePaymentIntent($sOrderId);
+                if($oCustomer === false || $oPaymentIntent === false)
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aCustomer = $oCustomer->jsonSerialize();
+                $aPaymentIntent = $oPaymentIntent->jsonSerialize();
+                if(empty($aCustomer) || !is_array($aCustomer) || empty($aPaymentIntent) || !is_array($aPaymentIntent))
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aResult = array_merge($aResult, array(
+                    'message' => $this->_sLangsPrefix . 'strp_msg_charged',
+                    'client_email' => $aCustomer['email'],
+                    'paid' => $aPaymentIntent['status'] == 'succeeded'
+                ));
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $oCustomer = $this->_retrieveCustomer(BX_PAYMENT_TYPE_RECURRING, $sCustomerId);
+                $oSubscription = $this->_retrieveSubscription($sCustomerId, $sOrderId);
+                if($oCustomer === false || $oSubscription === false)
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aCustomer = $oCustomer->jsonSerialize();
+                $aSubscription = $oSubscription->jsonSerialize();
+                if(empty($aCustomer) || !is_array($aCustomer) || empty($aSubscription) || !is_array($aSubscription))
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aResult = array_merge($aResult, array(
+                    'message' => $this->_sLangsPrefix . 'strp_msg_subscribed',
+                    'customer_id' => $sCustomerId,
+                    'subscription_id' => $sOrderId,
+                    'client_email' => $aCustomer['email'],
+                    'paid' => $this->isSubscriptionStatus(BX_PAYMENT_SBS_STATUS_ACTIVE, $aSubscription),
+                    'trial' => $this->isSubscriptionStatus(BX_PAYMENT_SBS_STATUS_TRIAL, $aSubscription)
+                ));
+                break;
+        }
+
+        //--- Update pending transaction ---//
+        $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
+            'order' => $sOrderId,
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message'])
+        ));
+
+        return $aResult;
+    }
+
+    public function getButtonSingle($iClientId, $iVendorId, $aParams = array())
+    {
+        if(!isset($aParams['sAction']))
+            return '';
+
+        return $aParams['sAction'] . parent::getButtonSingle($iClientId, $iVendorId, $aParams);
+    }
+
+    public function overwriteCheckoutParamsSingle($aParams, &$oGrid)
+    {
+        $aClient = $this->_oModule->getProfileInfo();
+
+        $oCart = $this->_oModule->getObjectCart();
+        $aCartInfo = $oCart->getInfo(BX_PAYMENT_TYPE_SINGLE, $aClient['id'], $aParams['seller_id'], $aParams['items']);
+        if(empty($aCartInfo) || !is_array($aCartInfo))
+            return array('msg' => _t('_bx_payment_err_nothing_selected'));
+
+        $aSessionParams = array(
+            'cancel_url' => $oCart->serviceGetCartUrl($aParams['seller_id']),
+            'success_url' => bx_append_url_params($this->_oModule->_oConfig->getUrl('URL_CART_CHECKOUT'), array_merge($aParams, array(
+                'session_id' => '{CHECKOUT_SESSION_ID}'
+            )))
+        );
+
+        $sSessionId = $this->_createSession(BX_PAYMENT_TYPE_SINGLE, $aSessionParams, $aClient, $aCartInfo);
+        if($sSessionId === false)
+            return array('msg' => _t('_bx_payment_err_cannot_perform'));
+
+        return array(
+            'eval' => $this->_oModule->_oConfig->getJsObject($this->_sName) . '.onCartCheckout(oData);', 
+            'session_id' => $sSessionId
+        );
+    }
+
+    public function createTax($sName, $fPercentage, $bInclusive = false)
+    {
+        $oTax = null;
+        $aTax = [
+            'display_name' => $sName,
+            'percentage' => $fPercentage,
+            'inclusive' => $bInclusive,
+        ];
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_create_tax', 0, false, array(
+            'tax_object' => &$oTax, 
+            'tax_params' => &$aTax
+        ));
+
+        try {
+            if(empty($oTax))
+                $oTax = $this->_getStripe()->taxRates->create($aTax);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Create Tax Error: ', $oException);
+        }
+
+        $aResult = $oTax->jsonSerialize();
+        if(empty($aResult) || !is_array($aResult))
+            return false;
+
+        return $aResult['id'];
+    }
+
+    public function retrieveTax($sId)
+    {
+        $oTax = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_tax', 0, false, array(
+            'tax_id' => &$sId,
+            'tax_object' => &$oTax
+        ));
+
+        try {
+            if(empty($oTax))
+                $oTax = $this->_getStripe()->taxRates->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Tax Error: ', $oException);
+        }
+
+        return $oTax;
+    }
+
+    public function getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency)
+    {
+        $sCode = $this->_getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency);
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_get_code_session', 0, false, array(
+            'provider' => $this,
+            'vendor_id' => $iVendorId, 
+            'customer_id' => $iCustomerId,
+            'amount' => $fAmount,
+            'currency' => $sCurrency,
+            'override_result' => &$sCode
+        ));
+
+        return $sCode;
+    }
+
+    public function checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult)
+    {
+        $bCheckResult = $this->_checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult);
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_verify_session', 0, false, array(
+            'provider' => $this,
+            'vendor_id' => $iVendorId, 
+            'customer_id' => $iCustomerId,
+            'result' => $aResult,
+            'override_result' => &$bCheckResult
+        ));
+
+        return $bCheckResult;
+    }
+
+    protected function _getStripe()
+    {
+        if(empty($this->_oStripe))
+            $this->_oStripe = new \Stripe\StripeClient($this->_getSecretKey());
+
+        return $this->_oStripe;
+    }
+            
+    /*
+     * Related Docs: https://stripe.com/docs/api/customers/retrieve
+     */
+    protected function _retrieveCustomer($sType, $sId)
+    {
+        $oCustomer = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_customer', 0, false, array(
+            'type' => $sType,
+            'customer_id' => &$sId,
+            'customer_object' => &$oCustomer
+        ));
+
+        try {
+            if(empty($oCustomer))
+                $oCustomer = $this->_getStripe()->customers->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Customer Error: ', $oException);
+        }
+
+        return $oCustomer;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/checkout/sessions/create
+     */
+    protected function _createSession($sType, $aParams, &$aClient, &$aCartInfo)
+    {
+        $iAmountPrecision = 2;
+        $fAmount = 100 * round((float)$aCartInfo['items_price'], $iAmountPrecision);
+
+        $sMode = '';
+        $aLineItems = array();
+        $aMetaItems = array();
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $sMode = 'payment';
+
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aProductData = array(
+                        'name' => $aItem['title']
+                    );
+                    if(!empty($aItem['description']))
+                        $aProductData['description'] = strmaxtextlen(strip_tags($aItem['description']), 60, '...');
+
+                    $aLineItems[] = array(
+                        'price_data' => array(
+                            'currency' => $aCartInfo['vendor_currency_code'],
+                            'product_data' => $aProductData,
+                            'unit_amount' => 100 * round($this->_oModule->_oConfig->getPrice($sType, $aItem), $iAmountPrecision),
+                        ),
+                        'quantity' => $aItem['quantity'],
+                    );
+
+                    $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aItem['module_id'], $aItem['id']]);
+                }
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $sMode = 'subscription';
+
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aLineItems[] = array(
+                        'price' => $aItem['name'],
+                        'quantity' => $aItem['quantity'],
+                    );
+
+                    $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aItem['module_id'], $aItem['id']]);
+                }
+                break;
+        }
+
+        $oSession = null;
+        $aSession = [
+            'payment_method_types' => ['card'],
+            'customer_email' => !empty($aClient['email']) ? $aClient['email'] : '',
+            'line_items' => $aLineItems,
+            'mode' => $sMode,
+            'success_url' => $aParams['success_url'],
+            'cancel_url' => $aParams['cancel_url'],
+            'metadata' => [
+                'vendor' => $aCartInfo['vendor_id'],
+                'client' => $aClient['id'],
+                'type' => $sType, 
+                'items' => $this->_oModule->_oConfig->descriptorsA2S($aMetaItems),
+                'verification' => $this->getVerificationCodeSession($aCartInfo['vendor_id'], $aClient['id'], $fAmount, $aCartInfo['vendor_currency_code'])
+            ]
+        ];
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_create_session', 0, false, array(
+            'session_object' => &$oSession, 
+            'session_params' => &$aSession
+        ));
+
+        try {
+            if(empty($oSession))
+                $oSession = $this->_getStripe()->checkout->sessions->create($aSession);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Create Session Error: ', $oException);
+        }
+
+        $aResult = $oSession->jsonSerialize();
+        if(empty($aResult) || !is_array($aResult))
+            return false;
+
+        if(!$this->checkVerificationCodeSession($aCartInfo['vendor_id'], $aClient['id'], $aResult))
+            return false;
+
+        return $aResult['id'];
+    }
+
+    protected function _getSession($sType, $sId)
+    {
+        $oSession = $this->_retrieveSession($sId);
+        if($oSession === false)
+            return array();
+
+        $aSession = $oSession->jsonSerialize();
+        if(empty($aSession) || !is_array($aSession))
+            return array();
+
+        $aResult = array(
+            'id' => $aSession['id'],
+            'order_id' => $aSession['payment_intent'],
+            'customer_id' => $aSession['customer'],
+            'status' => $aSession['payment_status']
+        );
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $aResult['order_id'] = $aSession['payment_intent'];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $aResult['order_id'] = $aSession['subscription'];
+                break;
+        }
+
+        return $aResult;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/checkout/sessions/retrieve
+     */
+    protected function _retrieveSession($sId) {
+        $oSession = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_session', 0, false, array(
+            'session_id' => &$sId,
+            'session_object' => &$oSession
+        ));
+
+        try {
+            if(empty($oSession))
+                $oSession = $this->_getStripe()->checkout->sessions->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Session Error: ', $oException);
+        }
+
+        return $oSession;
+    }
+    
+    /*
+     * Related Docs: https://stripe.com/docs/api/payment_intents/retrieve
+     */
+    protected function _retrievePaymentIntent($sId) {
+        $oPaymentIntent = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_payment_intent', 0, false, array(
+            'payment_intent_id' => &$sId,
+            'payment_intent_object' => &$oPaymentIntent
+        ));
+
+        try {
+            if(empty($oPaymentIntent))
+                $oPaymentIntent = $this->_getStripe()->paymentIntents->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Payment Intent Error: ', $oException);
+        }
+
+        return $oPaymentIntent;
+    }
+    
+    /*
+     * Related Docs: https://stripe.com/docs/api/subscriptions/retrieve
+     */
+    protected function _retrieveSubscription($sCustomerId, $sSubscriptionId)
+    {
+        $oSubscription = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_subscription', 0, false, array(
+            'subscription_id' => &$sId,
+            'subscription_object' => &$oSubscription
+        ));
+
+        try {
+            if(empty($oSubscription))
+                $oSubscription = $this->_getStripe()->subscriptions->retrieve($sSubscriptionId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Subscription Error: ', $oException);
+        }
+
+        return $oSubscription;
+    }
+
+    protected function _getButton($sType, $iClientId, $iVendorId, $aParams = array())
+    {
+        list($sJsCode, $sJsMethod) = $this->_getButtonJs($sType, $iClientId, $iVendorId, $aParams);
+
+    	if($sType == BX_PAYMENT_TYPE_SINGLE)
+            return $sJsCode;
+
+        return parent::_getButton($sType, $iClientId, $iVendorId);
+    }
+
+    protected function _getButtonJs($sType, $iClientId, $iVendorId, $aParams = array())
+    {
+        $sClientEmail = '';
+    	if(!empty($iClientId) && ($oClient = BxDolProfile::getInstance($iClientId)) !== false)
+            $sClientEmail = $oClient->getAccountObject()->getEmail();
+
+        $sPublicKey = '';
+    	bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_get_button', 0, $iClientId, array(
+            'type' => &$sType, 
+            'public_key' => &$sPublicKey
+        ));
+
+        $sJsMethod = '';
+        $sJsObject = $this->getJsObject($aParams);
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $sJsMethod = 'void(0)';
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $sJsMethod = $sJsObject . '.subscribe(this)';
+                break;
+        }
+
+        return array($this->_oModule->_oTemplate->getJsCode($this->_sName, array_merge(array(
+            'js_object' => $sJsObject,
+            'sProvider' => $this->_sName,
+            'sPublicKey' => !empty($sPublicKey) ? $sPublicKey : $this->_getPublicKey(),
+            'sVendorName' => '',
+            'sVendorCurrency' => '',
+            'sVendorIcon' => '',
+            'sClientEmail' => $sClientEmail,
+        ), $aParams)), $sJsMethod);
+    }
+
+    protected function _getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency)
+    {
+        return md5(implode('#-#', array(
+            (int)$iVendorId,
+            (int)$iCustomerId,
+            (float)$fAmount,
+            strtoupper($sCurrency)
+        )));
+    }
+
+    protected function _checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult)
+    {
+        return !empty($aResult['metadata']['verification']) && $aResult['metadata']['verification'] == $this->getVerificationCodeSession($iVendorId, $iCustomerId, $aResult['amount_total'], $aResult['currency']);
+    }
+
+    protected function _processException($sMessage, &$oException)
+    {
+        if(method_exists($oException, 'getError')) {
+            $sError = $oException->getError()->message;
+            $aError = $oException->getError()->toArray();
+        }
+        else { 
+            $sError = $oException->getMessage();
+            $aError = array();
+        }
+
+        $this->log($sMessage . $sError);
+        if(!empty($aError))
+            $this->log($aError);
+
+        return false;
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/payment/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_payment',
+    'title' => 'Payment',
+    'note' => 'Payment module.',
+    'version' => '13.0.2',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/payment/',
+    'home_uri' => 'payment',
+
+    'db_prefix' => 'bx_payment_',
+    'class_prefix' => 'BxPayment',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Payment',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+	'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/persons/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Persons',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/persons/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'persons_update_1301_1302',
+
+    'module_dir' => 'boonex/persons/',
+    'module_uri' => 'persons',
+
+    'db_prefix' => 'bx_persons_',
+    'class_prefix' => 'BxPersons',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Persons',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/persons/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxPersonsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 2 - 0
modules/boonex/persons/updates/13.0.1_13.0.2/install/sql/enable.sql

@@ -0,0 +1,2 @@
+-- GRIDS
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_persons_administration' AND `name`='lock_cf';

+ 152 - 0
modules/boonex/persons/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Persons Persons
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_persons',
+    'title' => 'Persons',
+    'note' => 'Basic person profiles functionality.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/persons/',
+    'home_uri' => 'persons',
+
+    'db_prefix' => 'bx_persons_',
+    'class_prefix' => 'BxPersons',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Persons',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+        'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+        'sys_profiles_relations' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_profile_snippet_meta',
+    	'trigger_profile_view_actions',
+    ),
+
+	/**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_persons_pictures'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_persons_icon',
+    	'bx_persons_thumb',
+    	'bx_persons_avatar',
+        'bx_persons_avatar_big',
+    	'bx_persons_picture',
+    	'bx_persons_cover',
+    	'bx_persons_cover_thumb',
+        'bx_persons_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_persons',
+    	'bx_persons_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+    	'process_deleted_profiles' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+	'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'unregister_transcoders' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 565 - 0
modules/boonex/persons/updates/13.0.1_13.0.2/source/install/sql/enable.sql

@@ -0,0 +1,565 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_persons', '_bx_persons', 'bx_persons@modules/boonex/persons/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_persons', '_bx_persons', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_persons_autoapproval', 'on', @iCategId, '_bx_persons_option_autoapproval', 'select', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"get_options_activation";}', '', '', 1),
+('bx_persons_default_acl_level', '3', @iCategId, '_bx_persons_option_default_acl_level', 'select', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"get_memberships";s:6:"params";a:4:{s:11:"purchasable";b:0;s:6:"active";b:1;s:9:"translate";b:1;s:22:"filter_out_auto_levels";b:1;}s:5:"class";s:16:"TemplAclServices";}', '', '', 2),
+('bx_persons_redirect_aadd', 'profile', @iCategId, '_bx_persons_option_redirect_aadd', 'select', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:30:"get_options_redirect_after_add";}', '', '', 3),
+('bx_persons_redirect_aadd_custom_url', '', @iCategId, '_bx_persons_option_redirect_aadd_custom_url', 'digit', '', '', '', 4),
+('bx_persons_num_connections_quick', '6', @iCategId, '_bx_persons_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_persons_per_page_browse', '24', @iCategId, '_bx_persons_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_persons_num_rss', '10', @iCategId, '_bx_persons_option_num_rss', 'digit', '', '', '', 12),
+('bx_persons_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_persons_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_persons_searchable_fields', 'fullname,description', @iCategId, '_bx_persons_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:21:"get_searchable_fields";}', '', '', 20),
+('bx_persons_public_subscriptions', '', @iCategId, '_bx_persons_option_public_subscriptions', 'checkbox', '', '', '', 30),
+('bx_persons_public_subscribed_me', '', @iCategId, '_bx_persons_option_public_subscribed_me', 'checkbox', '', '', '', 31),
+('bx_persons_enable_profile_activation_letter', 'on', @iCategId, '_bx_persons_option_enable_profile_activation_letter', 'checkbox', '', '', '', 32);
+
+-- PAGES
+
+-- PAGE: create profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_create_profile', 'create-persons-profile', '_bx_persons_page_title_sys_create_profile', '_bx_persons_page_title_create_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=create-persons-profile', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_create_profile', 1, 'bx_persons', '_bx_persons_page_block_title_choose_type', 11, 2147483647, 'menu', 'sys_add_profile_vertical', 0, 1, 0, 0),
+('bx_persons_create_profile', 1, 'bx_persons', '_bx_persons_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:13:\"entity_create\";}', 0, 1, 1, 1);
+
+-- PAGE: view profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_profile', 'view-persons-profile', '_bx_persons_page_title_sys_view_profile', '_bx_persons_page_title_view_profile', 'bx_persons', 7, 2147483647, 1, 'page.php?i=view-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_persons_view_profile', 0, 'bx_persons', '_bx_persons_page_block_title_sys_cover_block', '_bx_persons_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 0, 1, 0),
+('bx_persons_view_profile', 0, 'bx_persons', '', '_bx_persons_page_block_title_profile_friends_mutual', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"profile_friends_mutual\";}', 0, 0, 1, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:21:\"profile_subscriptions\";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:21:\"profile_subscribed_me\";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:18:"profile_related_me";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 1),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_friends', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_friends\";}', 0, 1, 1, 2),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:17:"profile_relations";}', 0, 1, 1, 3),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_calendar', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_calendar\";}', 0, 0, 0, 4),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 1),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_membership', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"profile_membership\";}', 0, 0, 1, 2),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_location', 3, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"locations_map\";s:6:\"params\";a:2:{i:0;s:10:\"bx_persons\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 3),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+-- PAGE: view closed profile 
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_profile_closed', 'view-person-profile-closed', '_bx_persons_page_title_sys_view_profile_closed', '_bx_persons_page_title_view_profile', 'bx_persons', 10, 2147483647, 1, 'page.php?i=view-person-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_view_profile_closed', 1, 'bx_persons', '', '_bx_persons_page_block_title_profile_private', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:19:\"private_profile_msg\";}', 0, 1, 1, 0);
+
+-- PAGE: edit profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_edit_profile', 'edit-persons-profile', '_bx_persons_page_title_sys_edit_profile', '_bx_persons_page_title_edit_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=edit-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_edit_profile', 1, 'bx_persons', '_bx_persons_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:11:\"entity_edit\";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_edit_profile_cover', 'edit-persons-cover', '_bx_persons_page_title_sys_edit_profile_cover', '_bx_persons_page_title_edit_profile_cover', 'bx_persons', 5, 2147483647, 1, 'page.php?i=edit-persons-cover', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_edit_profile_cover', 1, 'bx_persons', '_bx_persons_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_edit_cover\";}', 0, 0, 0);
+
+-- PAGE: delete profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_delete_profile', 'delete-persons-profile', '_bx_persons_page_title_sys_delete_profile', '_bx_persons_page_title_delete_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=delete-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_delete_profile', 1, 'bx_persons', '_bx_persons_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:13:\"entity_delete\";}', 0, 0, 0);
+
+-- PAGE: profile info
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_info', 'persons-profile-info', '_bx_persons_page_title_sys_profile_info', '_bx_persons_page_title_profile_info', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-info', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_info', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_info', '_bx_persons_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 1),
+('bx_persons_profile_info', 1, 'bx_persons', '', '_bx_persons_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 2);
+
+-- PAGE: profile friends
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_friends', 'persons-profile-friends', '_bx_persons_page_title_sys_profile_friends', '_bx_persons_page_title_profile_friends', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-friends', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_friends', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_friends', '_bx_persons_page_block_title_profile_friends_link', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:17:\"connections_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1);
+
+-- PAGE: profile friend requests
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_friend_requests', 'persons-friend-requests', '_bx_persons_page_title_sys_friend_requests', '_bx_persons_page_title_friend_requests', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-friend-requests', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_friend_requests', 1, 'bx_persons', '_bx_persons_page_block_title_system_friend_requests', '_bx_persons_page_block_title_friend_requests_link', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:25:\"connections_request_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1);
+
+-- PAGE: profile favorites
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_favorites', 'persons-profile-favorites', '_bx_persons_page_title_sys_profile_favorites', '_bx_persons_page_title_profile_favorites', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-favorites', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_favorites', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_favorites', '_bx_persons_page_block_title_profile_favorites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:15:"browse_favorite";}', 0, 1, 1, 1);
+
+-- PAGE: profile subscriptions
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_subscriptions', 'persons-profile-subscriptions', '_bx_persons_page_title_sys_profile_subscriptions', '_bx_persons_page_title_profile_subscriptions', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-subscriptions', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_subscriptions', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_subscriptions', '_bx_persons_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscriptions_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1),
+('bx_persons_profile_subscriptions', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_subscribed_me', '_bx_persons_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscribed_me_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 2);
+
+-- PAGE: profile relations
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_relations', 'persons-profile-relations', '_bx_persons_page_title_sys_profile_relations', '_bx_persons_page_title_profile_relations', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-relations', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_relations', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_relations', '_bx_persons_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:15:"relations_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 1),
+('bx_persons_profile_relations', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_related_me', '_bx_persons_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:16:"related_me_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 2);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_comments', '_bx_persons_page_title_sys_profile_comments', '_bx_persons_page_title_profile_comments', 'bx_persons', 5, 2147483647, 1, 'persons-profile-comments', '', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_comments', 1, 'bx_persons', '_bx_persons_page_block_title_profile_comments', '_bx_persons_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1);
+
+
+-- PAGE: module home
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_home', '_bx_persons_page_title_sys_recent', '_bx_persons_page_title_recent', 'bx_persons', 5, 2147483647, 1, 'persons-home', 'page.php?i=persons-home', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_persons_home', 1, 'bx_persons', '_bx_persons_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_persons";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0),
+('bx_persons_home', 1, 'bx_persons', '_bx_persons_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1);
+
+-- PAGE: active profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_active', '_bx_persons_page_title_sys_active', '_bx_persons_page_title_active', 'bx_persons', 5, 2147483647, 1, 'persons-active', 'page.php?i=persons-active', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_active', 1, 'bx_persons', '_bx_persons_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"browse_active_profiles";s:6:"params";a:2:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;}}', 0, 1, 0);
+
+-- PAGE: online profiles
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_online', '_bx_persons_page_title_sys_online', '_bx_persons_page_title_online', 'bx_persons', 5, 2147483647, 1, 'persons-online', 'page.php?i=persons-online', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_online', 1, 'bx_persons', '_bx_persons_page_block_title_online_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_online_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_search', '_bx_persons_page_title_sys_entries_search', '_bx_persons_page_title_entries_search', 'bx_persons', 5, 2147483647, 1, 'persons-search', 'page.php?i=persons-search', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:10:"bx_persons";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:10:"bx_persons";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:15:"bx_persons_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:15:"bx_persons_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: module manage own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_manage', '_bx_persons_page_title_sys_manage', '_bx_persons_page_title_manage', 'bx_persons', 5, 2147483647, 1, 'persons-manage', 'page.php?i=persons-manage', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_manage', 1, 'bx_persons', '_bx_persons_page_block_title_system_manage', '_bx_persons_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"manage_tools\";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_administration', '_bx_persons_page_title_sys_manage_administration', '_bx_persons_page_title_manage', 'bx_persons', 5, 192, 1, 'persons-administration', 'page.php?i=persons-administration', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_administration', 1, 'bx_persons', '_bx_persons_page_block_title_system_manage_administration', '_bx_persons_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: add block to homepage
+
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_persons', '' , '_bx_persons_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_persons', '_bx_persons_page_block_title_sys_recommended_entries_view_showcase', '_bx_persons_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+
+-- PAGE: service blocks
+
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_featured_entries_view_showcase', '_bx_persons_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"browse_featured\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_recommended_entries_view_showcase', '_bx_persons_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_active_entries_view_showcase', '_bx_persons_page_block_title_active_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:16:\"showcase_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_active_profiles', '_bx_persons_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:12:\"unit_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_familiar_profiles', '_bx_persons_page_block_title_familiar_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:24:\"browse_familiar_profiles\";s:6:\"params\";a:4:{s:10:\"connection\";s:20:\"sys_profiles_friends\";s:9:\"unit_view\";s:4:\"unit\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5);
+
+-- MENU
+
+-- MENU: add to site menu
+
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_home', '_bx_persons_menu_item_title_entries_home', 'page.php?i=persons-home', '', '', 'user col-blue3', 'bx_persons_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_home', '_bx_persons_menu_item_title_entries_home', 'page.php?i=persons-home', '', '', 'user col-blue3', 'bx_persons_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- SET @iCreateProfileMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_profiles_create' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+-- INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+-- ('sys_profiles_create', 'bx_persons', 'create-person-profile', '_bx_persons_menu_item_title_system_profile_type', '_bx_persons_menu_item_title_profile_type', 'page.php?i=create-persons-profile', '', '', 'user', '', 2147483647, 1, 1, IFNULL(@iCreateProfileMenuOrder, 0) + 1);
+
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_profile_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_profile_links', 'bx_persons', 'create-persons-profile', '_bx_persons_menu_item_title_system_create_profile', '_bx_persons_menu_item_title_create_profile', 'page.php?i=create-persons-profile', '', '', 'user col-blue3', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: view actions
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions', '_bx_persons_menu_title_view_profile_actions', 'bx_persons_view_actions', 'bx_persons', 9, 0, 1, 'BxPersonsMenuViewActions', 'modules/boonex/persons/classes/BxPersonsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions', 'bx_persons', '_bx_persons_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions', 'bx_persons', 'profile-friend-add', '_bx_persons_menu_item_title_system_befriend', '{title_add_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'add\', \'{profile_id}\')', '', 'user-plus', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_actions', 'bx_persons', 'profile-relation-add', '_bx_persons_menu_item_title_system_relation_add', '_bx_persons_menu_item_title_relation_add', 'javascript:void(0)', 'bx_menu_popup(''sys_add_relation'', window, {}, {profile_id: {profile_id}});', '', 'sync', '', 0, 2147483647, '', 1, 0, 15),
+('bx_persons_view_actions', 'bx_persons', 'profile-subscribe-add', '_bx_persons_menu_item_title_system_subscribe', '_bx_persons_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_actions', 'bx_persons', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '_sys_menu_item_title_set_acl_level', 'javascript:void(0)', 'bx_menu_popup(''sys_set_acl_level'', window, {id:{value:''sys_acl_set_{profile_id}'', force:true}, closeOnOuterClick: false, removeOnClose: true, displayMode: ''box'', cssClass: ''''}, {profile_id: {profile_id}});', '', 'certificate', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_actions', 'bx_persons', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '_sys_menu_item_title_set_badges', 'javascript:void(0)', 'bx_menu_popup(''sys_set_badges'', window, {}, {module: ''bx_persons'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 30),
+('bx_persons_view_actions', 'bx_persons', 'profile-actions-more', '_bx_persons_menu_item_title_system_more_actions', '_bx_persons_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_persons_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_persons_view_actions_more', 1, 2147483647, '', 1, 0, 9999);
+
+-- MENU: view actions more
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions_more', '_bx_persons_menu_title_view_profile_actions_more', 'bx_persons_view_actions_more', 'bx_persons', 6, 0, 1, 'BxPersonsMenuViewActions', 'modules/boonex/persons/classes/BxPersonsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions_more', 'bx_persons', '_bx_persons_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions_more', 'bx_persons', 'profile-friend-remove', '_bx_persons_menu_item_title_system_unfriend', '{title_remove_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'remove\', \'{profile_id}\')', '', 'user-times', '', 2147483647, 1, 0, 10),
+('bx_persons_view_actions_more', 'bx_persons', 'profile-relation-remove', '_bx_persons_menu_item_title_system_relation_delete', '_bx_persons_menu_item_title_relation_delete', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_relations\', \'remove\', \'{profile_id}\')', '', 'sync', '', 2147483647, 1, 0, 15),
+('bx_persons_view_actions_more', 'bx_persons', 'profile-subscribe-remove', '_bx_persons_menu_item_title_system_unsubscribe', '_bx_persons_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, 1, 0, 20),
+('bx_persons_view_actions_more', 'bx_persons', 'edit-persons-cover', '_bx_persons_menu_item_title_system_edit_cover', '_bx_persons_menu_item_title_edit_cover', 'page.php?i=edit-persons-cover&id={content_id}', '', '', 'edit', '', 2147483647, 1, 0, 25),
+('bx_persons_view_actions_more', 'bx_persons', 'edit-persons-profile', '_bx_persons_menu_item_title_system_edit_profile', '_bx_persons_menu_item_title_edit_profile', 'page.php?i=edit-persons-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 30),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-profile', '_bx_persons_menu_item_title_system_delete_profile', '_bx_persons_menu_item_title_delete_profile', 'page.php?i=delete-persons-profile&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 40),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-account', '_bx_persons_menu_item_title_system_delete_account', '_bx_persons_menu_item_title_delete_account', 'page.php?i=account-settings-delete&id={account_id}', '', '', 'user-times', '', 128, 1, 0, 50),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-account-content', '_bx_persons_menu_item_title_system_delete_account_content', '_bx_persons_menu_item_title_delete_account_content', 'page.php?i=account-settings-delete&id={account_id}&content=1', '', '', 'trash', '', 128, 1, 0, 60);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions_all', '_sys_menu_title_view_actions', 'bx_persons_view_actions_all', 'bx_persons', 15, 0, 1, 'BxPersonsMenuViewActionsAll', 'modules/boonex/persons/classes/BxPersonsMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions_all', 'bx_persons', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions_all', 'bx_persons', 'profile-friend-add', '_bx_persons_menu_item_title_system_befriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-friend-remove', '_bx_persons_menu_item_title_system_unfriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-relation-add', '_bx_persons_menu_item_title_system_relation_add', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 23),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-relation-remove', '_bx_persons_menu_item_title_system_relation_delete', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 27),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-subscribe-add', '_bx_persons_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-subscribe-remove', '_bx_persons_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 60),
+('bx_persons_view_actions_all', 'bx_persons', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_persons_view_actions_all', 'bx_persons', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 210),
+('bx_persons_view_actions_all', 'bx_persons', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 215),
+('bx_persons_view_actions_all', 'bx_persons', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_persons_view_actions_all', 'bx_persons', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_persons_view_actions_all', 'bx_persons', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_persons_view_actions_all', 'bx_persons', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_persons_view_actions_all', 'bx_persons', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_persons_view_actions_all', 'bx_persons', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_persons&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_persons_view_actions_all', 'bx_persons', 'edit-persons-cover', '_bx_persons_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_persons_view_actions_all', 'bx_persons', 'edit-persons-profile', '_bx_persons_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-profile', '_bx_persons_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-account', '_bx_persons_menu_item_title_system_delete_account', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 430),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-account-content', '_bx_persons_menu_item_title_system_delete_account_content', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 440),
+('bx_persons_view_actions_all', 'bx_persons', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, '', 1, 0, 9999);
+
+-- MENU: meta (counters) menu for view entry
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_meta', '_bx_persons_menu_title_view_profile_meta', 'bx_persons_view_meta', 'bx_persons', 15, 0, 1, 'BxPersonsMenuViewMeta', 'modules/boonex/persons/classes/BxPersonsMenuViewMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_meta', 'bx_persons', '_bx_persons_menu_set_title_view_profile_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_meta', 'bx_persons', 'membership', '_sys_menu_item_title_system_vm_membership', '_sys_menu_item_title_vm_membership', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_meta', 'bx_persons', 'badges', '_sys_menu_item_title_system_vm_badges', '_sys_menu_item_title_vm_badges', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_meta', 'bx_persons', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_meta', 'bx_persons', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_persons_view_meta', 'bx_persons', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50);
+
+-- MENU: module sub-menu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_submenu', '_bx_persons_menu_title_submenu', 'bx_persons_submenu', 'bx_persons', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_submenu', 'bx_persons', '_bx_persons_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_submenu', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_recent', '_bx_persons_menu_item_title_entries_recent', 'page.php?i=persons-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_persons_submenu', 'bx_persons', 'persons-active', '_bx_persons_menu_item_title_system_entries_active', '_bx_persons_menu_item_title_entries_active', 'page.php?i=persons-active', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_persons_submenu', 'bx_persons', 'persons-online', '_bx_persons_menu_item_title_system_entries_online', '_bx_persons_menu_item_title_entries_online', 'page.php?i=persons-online', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_persons_submenu', 'bx_persons', 'persons-search', '_bx_persons_menu_item_title_system_entries_search', '_bx_persons_menu_item_title_entries_search', 'page.php?i=persons-search', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_persons_submenu', 'bx_persons', 'persons-manage', '_bx_persons_menu_item_title_system_entries_manage', '_bx_persons_menu_item_title_entries_manage', 'page.php?i=persons-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: view submenu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_submenu', '_bx_persons_menu_title_view_profile_submenu', 'bx_persons_view_submenu', 'bx_persons', 18, 0, 1, 'BxPersonsMenuView', 'modules/boonex/persons/classes/BxPersonsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_submenu', 'bx_persons', '_bx_persons_menu_set_title_view_profile_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_submenu', 'bx_persons', 'view-persons-profile', '_bx_persons_menu_item_title_system_view_profile_view', '_bx_persons_menu_item_title_view_profile_view', 'page.php?i=view-persons-profile&id={content_id}', '', '', 'user col-blue3', '', '', 0, 2147483647, 1, 0, 1),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-info', '_bx_persons_menu_item_title_system_view_profile_info', '_bx_persons_menu_item_title_view_profile_info', 'page.php?i=persons-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-friends', '_bx_persons_menu_item_title_system_view_profile_friends', '_bx_persons_menu_item_title_view_profile_friends', 'page.php?i=persons-profile-friends&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 3),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-relations', '_bx_persons_menu_item_title_system_view_profile_relations', '_bx_persons_menu_item_title_view_profile_relations', 'page.php?i=persons-profile-relations&profile_id={profile_id}', '', '', 'sync col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-subscriptions', '_bx_persons_menu_item_title_system_view_profile_subscriptions', '_bx_persons_menu_item_title_view_profile_subscriptions', 'page.php?i=persons-profile-subscriptions&profile_id={profile_id}', '', '', 'check col-blue3', '', '', 0, 2147483647, 1, 0, 5),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-comments', '_bx_persons_menu_item_title_system_view_profile_comments', '_bx_persons_menu_item_title_view_profile_comments', 'page.php?i=persons-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 6),
+('bx_persons_view_submenu', 'bx_persons', 'more-auto', '_bx_persons_menu_item_title_system_view_profile_more_auto', '_bx_persons_menu_item_title_view_profile_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_persons_snippet_meta', 'bx_persons', 15, 0, 1, 'BxPersonsMenuSnippetMeta', 'modules/boonex/persons/classes/BxPersonsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_snippet_meta', 'bx_persons', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_persons_snippet_meta', 'bx_persons', 'friends-mutual', '_sys_menu_item_title_system_sm_friends_mutual', '_sys_menu_item_title_sm_friends_mutual', '', '', '', '', '', 2147483647, 0, 0, 1, 0),
+('bx_persons_snippet_meta', 'bx_persons', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 0, 0, 1, 1),
+('bx_persons_snippet_meta', 'bx_persons', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 2),
+('bx_persons_snippet_meta', 'bx_persons', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 3),
+('bx_persons_snippet_meta', 'bx_persons', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 4),
+('bx_persons_snippet_meta', 'bx_persons', 'friends', '_sys_menu_item_title_system_sm_friends', '_sys_menu_item_title_sm_friends', '', '', '', '', '', 2147483647, 1, 0, 1, 5),
+('bx_persons_snippet_meta', 'bx_persons', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, 1, 0, 1, 6),
+('bx_persons_snippet_meta', 'bx_persons', 'membership', '_sys_menu_item_title_system_sm_membership', '_sys_menu_item_title_sm_membership', '', '', '', '', '', 2147483647, 0, 0, 1, 7),
+('bx_persons_snippet_meta', 'bx_persons', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, 1, 0, 1, 8),
+('bx_persons_snippet_meta', 'bx_persons', 'befriend', '_sys_menu_item_title_system_sm_befriend', '_sys_menu_item_title_sm_befriend', '', '', '', '', '', 2147483647, 1, 0, 1, 9),
+('bx_persons_snippet_meta', 'bx_persons', 'unfriend', '_sys_menu_item_title_system_sm_unfriend', '_sys_menu_item_title_sm_unfriend', '', '', '', '', '', 2147483647, 0, 0, 1, 10),
+('bx_persons_snippet_meta', 'bx_persons', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, 1, 0, 1, 11),
+('bx_persons_snippet_meta', 'bx_persons', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, 0, 0, 1, 12);
+
+-- MENU: notifications menu in account popup
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', 'bx_persons', 'notifications-friend-requests', '_bx_persons_menu_item_title_system_friends', '_bx_persons_menu_item_title_friends', 'page.php?i=persons-profile-friends&profile_id={member_id}', '', '', 'users col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1),
+('sys_account_notifications', 'bx_persons', 'notifications-relation-requests', '_bx_persons_menu_item_title_system_relations', '_bx_persons_menu_item_title_relations', 'page.php?i=persons-profile-relations&profile_id={member_id}', '', '', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:22:"sys_profiles_relations";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: profile stats
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_persons', 'profile-stats-friend-requests', '_bx_persons_menu_item_title_system_friend_requests', '_bx_persons_menu_item_title_friend_requests', 'page.php?i=persons-profile-friends&profile_id={member_id}', '', '', 'users col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 1),
+('sys_profile_stats', 'bx_persons', 'profile-stats-manage-profiles', '_bx_persons_menu_item_title_system_manage_my_profiles', '_bx_persons_menu_item_title_manage_my_profiles', 'page.php?i=persons-manage', '', '_self', 'users col-blue3', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 2),
+('sys_profile_stats', 'bx_persons', 'profile-stats-favorite-persons', '_bx_persons_menu_item_title_system_favorites', '_bx_persons_menu_item_title_favorites', 'page.php?i=persons-profile-favorites&profile_id={member_id}', '', '', 'star col-blue3', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:38:"get_menu_addon_favorites_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 3),
+('sys_profile_stats', 'bx_persons', 'profile-stats-subscriptions', '_bx_persons_menu_item_title_system_subscriptions', '_bx_persons_menu_item_title_subscriptions', 'page.php?i=persons-profile-subscriptions&profile_id={member_id}#subscriptions', '', '_self', 'rss col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 4),
+('sys_profile_stats', 'bx_persons', 'profile-stats-subscribed-me', '_bx_persons_menu_item_title_system_subscribed_me', '_bx_persons_menu_item_title_subscribed_me', 'page.php?i=persons-profile-subscriptions&profile_id={member_id}#subscribers', '', '_self', 'rss col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 5),
+('sys_profile_stats', 'bx_persons', 'profile-stats-relations', '_bx_persons_menu_item_title_system_relations', '_bx_persons_menu_item_title_relations', 'page.php?i=persons-profile-relations&profile_id={member_id}#relations', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 6),
+('sys_profile_stats', 'bx_persons', 'profile-stats-related-me', '_bx_persons_menu_item_title_system_related_me', '_bx_persons_menu_item_title_related_me', 'page.php?i=persons-profile-relations&profile_id={member_id}#related-me', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 7);
+
+-- MENU: profile followings
+SET @iFollowingsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_profile_followings' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `collapsed`, `active`, `copyable`, `order`) VALUES 
+('sys_profile_followings', 'bx_persons', 'persons', '_bx_persons_menu_item_title_system_followings', '_bx_persons_menu_item_title_followings', 'javascript:void(0)', '', '_self', 'users col-blue3', '', '', 2147483647, 0, 1, 0, @iFollowingsMenuOrder + 1);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_menu_manage_tools', '_bx_persons_menu_title_manage_tools', 'bx_persons_menu_manage_tools', 'bx_persons', 6, 0, 1, 'BxPersonsMenuManageTools', 'modules/boonex/persons/classes/BxPersonsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_menu_manage_tools', 'bx_persons', '_bx_persons_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_menu_manage_tools', 'bx_persons', 'clear-reports', '_bx_persons_menu_item_title_system_clear_reports', '_bx_persons_menu_item_title_clear_reports', 'javascript:void(0)', 'javascript:{js_object}.onClickClearReports({content_id});', '_self', 'eraser', '', 2147483647, 1, 0, 1),
+('bx_persons_menu_manage_tools', 'bx_persons', 'manage-cf', '_bx_persons_menu_item_title_system_manage_cf', '_bx_persons_menu_item_title_manage_cf', 'javascript:void(0)', 'javascript:{js_object}.onClickManageCf({content_id});', '_self', 'filter', '', 2147483647, 1, 0, 6),
+('bx_persons_menu_manage_tools', 'bx_persons', 'delete', '_bx_persons_menu_item_title_system_delete', '_bx_persons_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 98),
+('bx_persons_menu_manage_tools', 'bx_persons', 'delete-with-content', '_bx_persons_menu_item_title_system_delete_with_content', '_bx_persons_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 99);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_persons', 'persons-administration', '_bx_persons_menu_item_title_system_admt_persons', '_bx_persons_menu_item_title_admt_persons', 'page.php?i=persons-administration', '', '_self', 'user', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'create entry', NULL, '_bx_persons_acl_action_create_profile', '', 1, 1);
+SET @iIdActionProfileCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'delete entry', NULL, '_bx_persons_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'view entry', NULL, '_bx_persons_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'edit any entry', NULL, '_bx_persons_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'delete any entry', NULL, '_bx_persons_acl_action_delete_any_profile', '', 1, 3);
+SET @iIdActionProfileDeleteAny = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile create
+(@iAccount, @iIdActionProfileCreate),
+(@iStandard, @iIdActionProfileCreate),
+(@iUnconfirmed, @iIdActionProfileCreate),
+(@iPending, @iIdActionProfileCreate),
+(@iModerator, @iIdActionProfileCreate),
+(@iAdministrator, @iIdActionProfileCreate),
+(@iPremium, @iIdActionProfileCreate),
+
+-- profile delete
+(@iAccount, @iIdActionProfileDelete),
+(@iStandard, @iIdActionProfileDelete),
+(@iUnconfirmed, @iIdActionProfileDelete),
+(@iPending, @iIdActionProfileDelete),
+(@iModerator, @iIdActionProfileDelete),
+(@iAdministrator, @iIdActionProfileDelete),
+(@iPremium, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- any profile delete
+(@iAdministrator, @iIdActionProfileDeleteAny);
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons', 'bx_persons', 'bx_persons_meta_keywords', 'bx_persons_meta_locations', 'bx_persons_meta_mentions', '', '');
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_persons', '_bx_persons', @iSearchOrder + 1, 'BxPersonsSearchResult', 'modules/boonex/persons/classes/BxPersonsSearchResult.php'),
+('bx_persons_cmts', '_bx_persons_cmts', @iSearchOrder + 2, 'BxPersonsCmtsSearchResult', 'modules/boonex/persons/classes/BxPersonsCmtsSearchResult.php');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_persons', 'bx_persons', '_bx_persons', 'page.php?i=persons-home', 'user col-blue3', 'SELECT COUNT(*) FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_persons_growth', '_bx_persons_chart_growth', 'bx_persons_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_persons_growth_speed', '_bx_persons_chart_growth_speed', 'bx_persons_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRIDS: administration
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_administration', 'Sql', 'SELECT `td`.*, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status`, `tp`.`id` as `profile_id` FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_persons'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_persons_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'fullname,email', '', 'like', 'reports', '', 192, 'BxPersonsGridAdministration', 'modules/boonex/persons/classes/BxPersonsGridAdministration.php'),
+('bx_persons_common', 'Sql', 'SELECT `td`.*, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status` FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_persons'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_persons_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'fullname', '', 'like', '', '', 2147483647, 'BxPersonsGridCommon', 'modules/boonex/persons/classes/BxPersonsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_persons_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_persons_administration', 'switcher', '_bx_persons_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_persons_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_persons_administration', 'fullname', '_bx_persons_grid_column_title_adm_fullname', '25%', 0, '', '', 4),
+('bx_persons_administration', 'last_online', '_bx_persons_grid_column_title_adm_last_online', '20%', 1, '25', '', 5),
+('bx_persons_administration', 'account', '_bx_persons_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_persons_administration', 'actions', '', '20%', 0, '', '', 7),
+('bx_persons_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_persons_common', 'fullname', '_bx_persons_grid_column_title_adm_fullname', '48%', 0, '', '', 2),
+('bx_persons_common', 'last_online', '_bx_persons_grid_column_title_adm_last_online', '30%', 1, '25', '', 3),
+('bx_persons_common', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_persons_administration', 'bulk', 'set_acl_level', '_bx_persons_grid_action_title_adm_set_acl_level', '', 0, 0, 1),
+('bx_persons_administration', 'bulk', 'delete', '_bx_persons_grid_action_title_adm_delete', '', 0, 1, 2),
+('bx_persons_administration', 'bulk', 'delete_with_content', '_bx_persons_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_persons_administration', 'bulk', 'clear_reports', '_bx_persons_grid_action_title_adm_clear_reports', '', 0, 1, 4),
+('bx_persons_administration', 'single', 'set_acl_level', '_bx_persons_grid_action_title_adm_set_acl_level', 'certificate', 1, 0, 1),
+('bx_persons_administration', 'single', 'settings', '_bx_persons_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_persons_administration', 'single', 'audit_content', '_bx_persons_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_persons_administration', 'single', 'audit_profile', '_bx_persons_grid_action_title_adm_audit_profile', 'search-location', 1, 0, 4),
+
+('bx_persons_common', 'bulk', 'delete', '_bx_persons_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_persons_common', 'bulk', 'delete_with_content', '_bx_persons_grid_action_title_adm_delete_with_content', '', 0, 1, 2),
+('bx_persons_common', 'single', 'settings', '_bx_persons_grid_action_title_adm_more_actions', 'cog', 1, 0, 1);
+
+-- LIVE UPDATES
+INSERT INTO `sys_objects_live_updates`(`name`, `frequency`, `service_call`, `active`) VALUES
+('bx_persons_friend_requests', 1, 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:40:"get_live_updates_unconfirmed_connections";s:6:"params";a:5:{i:0;s:10:"bx_persons";i:1;s:20:"sys_profiles_friends";i:2;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:7:"account";}i:3;a:2:{s:11:"menu_object";s:25:"sys_account_notifications";s:9:"menu_item";s:29:"notifications-friend-requests";}i:4;s:7:"{count}";}s:5:"class";s:23:"TemplServiceConnections";}', 1);
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_persons', 'BxPersonsAlertsResponse', 'modules/boonex/persons/classes/BxPersonsAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('sys_profiles_friends', 'connection_added', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_persons_pictures', 'file_deleted', @iHandler),
+('bx_persons', 'timeline_view', @iHandler),
+('bx_persons', 'timeline_post', @iHandler),
+('bx_persons', 'timeline_delete', @iHandler),
+('bx_persons', 'timeline_comment', @iHandler),
+('bx_persons', 'timeline_vote', @iHandler),
+('bx_persons', 'timeline_score', @iHandler),
+('bx_persons', 'timeline_report', @iHandler),
+('bx_persons', 'timeline_repost', @iHandler),
+('bx_persons', 'timeline_pin', @iHandler),
+('bx_persons', 'timeline_promote', @iHandler);
+
+-- PRIVACY 
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_allow_view_to', 'bx_persons', 'view', '_bx_persons_form_profile_input_allow_view_to', '3', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacy', 'modules/boonex/persons/classes/BxPersonsPrivacy.php'),
+('bx_persons_allow_post_to', 'bx_persons', 'post', '_bx_persons_form_profile_input_allow_post_to', '5', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacyPost', 'modules/boonex/persons/classes/BxPersonsPrivacyPost.php'),
+('bx_persons_allow_contact_to', 'bx_persons', 'contact', '_bx_persons_form_profile_input_allow_contact_to', '3', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacyContact', 'modules/boonex/persons/classes/BxPersonsPrivacyContact.php');
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_persons', '_bx_persons_email_friend_request', 'bx_persons_friend_request', '_bx_persons_email_friend_request_subject', '_bx_persons_email_friend_request_body');
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_cover_crop', 1, 'BxPersonsUploaderCoverCrop', 'modules/boonex/persons/classes/BxPersonsUploaderCoverCrop.php'),
+('bx_persons_picture_crop', 1, 'BxPersonsUploaderPictureCrop', 'modules/boonex/persons/classes/BxPersonsUploaderPictureCrop.php');

+ 51 - 0
modules/boonex/photos/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Photos',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/photos/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'photos_update_1301_1302',
+
+    'module_dir' => 'boonex/photos/',
+    'module_uri' => 'photos',
+
+    'db_prefix' => 'bx_photos_',
+    'class_prefix' => 'BxPhotos',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Photos',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/photos/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxPhotosUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 136 - 0
modules/boonex/photos/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Photos Photos
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_photos',
+    'title' => 'Photos',
+    'note' => 'Basic photo posting module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/photos/',
+    'home_uri' => 'photos',
+
+    'db_prefix' => 'bx_photos_',
+    'class_prefix' => 'BxPhotos',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Photos',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_photos_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_photos_preview',
+        'bx_photos_gallery',
+        'bx_photos_cover'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_photos',
+    	'bx_photos_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 1 - 0
modules/boonex/photos/updates/13.0.1_13.0.2/source/template/entry-text.html

@@ -0,0 +1 @@
+<div class="bx-base-profile-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-vanilla-html prose dark:prose-invert">__entry_text__</div>

+ 51 - 0
modules/boonex/polls/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Polls',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/polls/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'polls_update_1301_1302',
+
+    'module_dir' => 'boonex/polls/',
+    'module_uri' => 'polls',
+
+    'db_prefix' => 'bx_polls_',
+    'class_prefix' => 'BxPolls',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Polls',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/polls/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxPollsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 136 - 0
modules/boonex/polls/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Polls Polls
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_polls',
+    'title' => 'Polls',
+    'note' => 'Basic poll module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/polls/',
+    'home_uri' => 'polls',
+
+    'db_prefix' => 'bx_polls_',
+    'class_prefix' => 'BxPolls',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Polls',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_polls_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_polls_preview',
+        'bx_polls_gallery',
+        'bx_polls_cover'
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_polls',
+    	'bx_polls_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 18 - 0
modules/boonex/polls/updates/13.0.1_13.0.2/source/template/entry-text-subentries.html

@@ -0,0 +1,18 @@
+<div class="bx-polls-entity-actions">__menu__</div>
+<div class="bx-polls-entity-entity-content bx-content-padding-block">
+    <div class="bx-content-description-before">__content_description_before__</div>
+    <div class="bx-content-description">
+        <div class="bx-pull-combined-entity-content bx-base-text-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-vanilla-html prose dark:prose-invert">
+            __entry_text__
+        </div>
+        <bx_if:show_image>
+            <div class="bx-base-text-entity-image bx-def-margin-top bx-def-font-align-center">
+                <img class="bx-def-border-radius-block" src="__entry_image__" />
+            </div>
+        </bx_if:show_image>
+        <bx_if:show_subentries>
+            <div class="bx-poll-entity-subentries bx-def-margin-top">__entry_subentries__</div>
+        </bx_if:show_subentries>
+    </div>
+    <div class="bx-content-description-after">__content_description_after__</div>
+</div>

+ 6 - 0
modules/boonex/polls/updates/13.0.1_13.0.2/source/template/entry-text.html

@@ -0,0 +1,6 @@
+<div class="bx-base-text-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-vanilla-html prose dark:prose-invert">__entry_text__</div>
+<bx_if:show_image>
+    <div class="bx-base-text-entity-image bx-def-margin-top bx-def-font-align-center">
+        <img class="bx-def-border-radius-block" src="__entry_image__" />
+    </div>
+</bx_if:show_image>

+ 51 - 0
modules/boonex/posts/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Posts',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/posts/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'posts_update_1301_1302',
+
+    'module_dir' => 'boonex/posts/',
+    'module_uri' => 'posts',
+
+    'db_prefix' => 'bx_posts_',
+    'class_prefix' => 'BxPosts',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Posts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/posts/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxPostsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 153 - 0
modules/boonex/posts/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,153 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Posts Posts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_posts',
+    'title' => 'Posts',
+    'note' => 'Basic blogging module.',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/posts/',
+    'home_uri' => 'posts',
+
+    'db_prefix' => 'bx_posts_',
+    'class_prefix' => 'BxPosts',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Posts',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_posts_covers',
+        'bx_posts_photos',
+        'bx_posts_videos',
+        'bx_posts_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_posts_preview',
+        'bx_posts_gallery',
+        'bx_posts_cover',
+
+        'bx_posts_preview_photos',
+        'bx_posts_gallery_photos',
+        'bx_posts_view_photos',
+
+        'bx_posts_videos_poster',
+        'bx_posts_videos_poster_preview',
+        'bx_posts_videos_mp4',
+        'bx_posts_videos_mp4_hd',
+        
+        'bx_posts_sounds_mp3',
+
+        'bx_posts_preview_files',
+        'bx_posts_gallery_files'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_posts',
+    	'bx_posts_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 701 - 0
modules/boonex/posts/updates/13.0.1_13.0.2/source/install/sql/install.sql

@@ -0,0 +1,701 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_posts_posts` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `published` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_comments` tinyint(4) NOT NULL DEFAULT '1',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_posts_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_files` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_photos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLES: LINKS
+CREATE TABLE IF NOT EXISTS `bx_posts_links` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `media_id` int(11) NOT NULL DEFAULT '0',
+  `url` varchar(255) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `text` text NOT NULL,
+  `added` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_links2content` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `content_id` int(11) NOT NULL DEFAULT '0',
+  `link_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `link` (`link_id`, `content_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_videos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_sounds` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_sounds_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_posts_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  `cmt_cf` int(11) NOT NULL default '1',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_posts_votes` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_reactions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_posts_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_posts_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_posts_meta_mentions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+CREATE TABLE `bx_posts_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_posts_reports` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_posts_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_posts_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_posts_scores` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: polls
+CREATE TABLE IF NOT EXISTS `bx_posts_polls` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author_id` int(11) NOT NULL default '0',
+  `content_id` int(11) NOT NULL default '0',
+  `text` text NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `content_id` (`content_id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_polls_answers` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `poll_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `poll_id` (`poll_id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_polls_answers_votes` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_polls_answers_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- STORAGES & TRANSCODERS
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_posts_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_videos', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_posts_videos', 'allow-deny', 'avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_videos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_sounds', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_sounds', 'allow-deny', 'mp3,m4a,m4b,wma,wav,3gp', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_sounds_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_sounds_resized', 'allow-deny', 'mp3,m4a,m4b,wma,wav,3gp', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_files', 'deny-allow', '', 'action,apk,app,bat,bin,cmd,com,command,cpl,csh,exe,gadget,inf,ins,inx,ipa,isu,job,jse,ksh,lnk,msc,msi,msp,mst,osx,out,paf,pif,prg,ps1,reg,rgs,run,sct,shb,shs,u3p,vb,vbe,vbs,vbscript,workflow,ws,wsf', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`, `override_class_name`, `override_class_file`) VALUES 
+('bx_posts_preview', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_cover', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_posts_preview_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_view_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_posts_videos_poster', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_poster_preview', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_mp4', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_mp4_hd', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_posts_sounds_mp3', 'bx_posts_sounds_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_sounds";}', 'no', '0', '0', '0', 'BxDolTranscoderAudio', ''),
+
+('bx_posts_preview_files', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_posts_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery_files', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_posts_files";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_posts_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_posts_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_posts_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_gallery_photos', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_posts_view_photos', 'Resize',  'a:2:{s:1:"w";s:4:"2000";s:1:"h";s:4:"2000";}', '0'),
+
+('bx_posts_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_posts_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_posts_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_posts_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_posts_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_posts_sounds_mp3', 'Mp3', 'a:0:{}', 0),
+
+('bx_posts_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_gallery_files', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
+
+
+-- FORMS: entry (post)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_posts', 'bx_posts', '_bx_posts_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_posts_posts', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxPostsFormEntry', 'modules/boonex/posts/classes/BxPostsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_posts', 'bx_posts_entry_add', 'bx_posts', 0, '_bx_posts_form_entry_display_add'),
+('bx_posts', 'bx_posts_entry_delete', 'bx_posts', 0, '_bx_posts_form_entry_display_delete'),
+('bx_posts', 'bx_posts_entry_edit', 'bx_posts', 0, '_bx_posts_form_entry_display_edit'),
+('bx_posts', 'bx_posts_entry_view', 'bx_posts', 1, '_bx_posts_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_posts', 'bx_posts', 'cf', '1', '#!sys_content_filter', 0, 'select', '_sys_form_entry_input_sys_cf', '_sys_form_entry_input_cf', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_posts', 'bx_posts', 'allow_view_to', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_allow_view_to', '_bx_posts_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_posts_form_entry_input_sys_delete_confirm', '_bx_posts_form_entry_input_delete_confirm', '_bx_posts_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'do_publish', '_bx_posts_form_entry_input_do_publish', '', 0, 'submit', '_bx_posts_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'do_submit', '_bx_posts_form_entry_input_do_submit', '', 0, 'submit', '_bx_posts_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'covers', 'a:1:{i:0;s:14:"bx_posts_html5";}', 'a:2:{s:15:"bx_posts_simple";s:26:"_sys_uploader_simple_title";s:14:"bx_posts_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_covers', '_bx_posts_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'pictures', 'a:1:{i:0;s:21:"bx_posts_photos_html5";}', 'a:2:{s:22:"bx_posts_photos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_posts_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_pictures', '_bx_posts_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'videos', 'a:2:{i:0;s:21:"bx_posts_videos_html5";i:1;s:28:"bx_posts_videos_record_video";}', 'a:3:{s:22:"bx_posts_videos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_posts_videos_html5";s:25:"_sys_uploader_html5_title";s:28:"bx_posts_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_videos', '_bx_posts_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'link', '', '', 0, 'custom', '_bx_posts_form_post_input_sys_link', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'sounds', 'a:1:{i:0;s:21:"bx_posts_sounds_html5";}', 'a:2:{s:22:"bx_posts_sounds_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_posts_sounds_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_sounds', '_bx_posts_form_entry_input_sounds', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'files', 'a:1:{i:0;s:20:"bx_posts_files_html5";}', 'a:2:{s:21:"bx_posts_files_simple";s:26:"_sys_uploader_simple_title";s:20:"bx_posts_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_files', '_bx_posts_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'polls', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'text', '', '', 0, 'textarea', '_bx_posts_form_entry_input_sys_text', '_bx_posts_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_posts', 'bx_posts', 'title', '', '', 0, 'text', '_bx_posts_form_entry_input_sys_title', '_bx_posts_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'cat', '', '#!bx_posts_cats', 0, 'select', '_bx_posts_form_entry_input_sys_cat', '_bx_posts_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_posts_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'multicat', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_multicat', '_bx_posts_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_posts_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'added', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_added', '_bx_posts_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'changed', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_changed', '_bx_posts_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'published', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_published', '_bx_posts_form_entry_input_date_published', '_bx_posts_form_entry_input_date_published_info', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
+('bx_posts', 'bx_posts', 'attachments', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'allow_comments', '1', '', 1, 'switcher', '_bx_posts_form_entry_input_sys_allow_comments', '_bx_posts_form_entry_input_allow_comments', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
+
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_posts_entry_add', 'delete_confirm', 2147483647, 0, 1),
+('bx_posts_entry_add', 'title', 2147483647, 1, 2),
+('bx_posts_entry_add', 'cat', 2147483647, 1, 3),
+('bx_posts_entry_add', 'text', 2147483647, 1, 4),
+('bx_posts_entry_add', 'attachments', 2147483647, 1, 5),
+('bx_posts_entry_add', 'link', 2147483647, 1, 6),
+('bx_posts_entry_add', 'pictures', 2147483647, 1, 7),
+('bx_posts_entry_add', 'videos', 2147483647, 1, 8),
+('bx_posts_entry_add', 'sounds', 2147483647, 1, 9),
+('bx_posts_entry_add', 'files', 2147483647, 1, 10),
+('bx_posts_entry_add', 'polls', 2147483647, 1, 11),
+('bx_posts_entry_add', 'covers', 2147483647, 1, 12),
+('bx_posts_entry_add', 'allow_view_to', 2147483647, 1, 13),
+('bx_posts_entry_add', 'cf', 2147483647, 1, 14),
+('bx_posts_entry_add', 'location', 2147483647, 1, 15),
+('bx_posts_entry_add', 'published', 192, 0, 16),
+('bx_posts_entry_add', 'allow_comments', 192, 1, 17),
+('bx_posts_entry_add', 'do_publish', 2147483647, 1, 18),
+
+('bx_posts_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_posts_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_posts_entry_edit', 'do_publish', 2147483647, 0, 1),
+('bx_posts_entry_edit', 'delete_confirm', 2147483647, 0, 2),
+('bx_posts_entry_edit', 'title', 2147483647, 1, 3),
+('bx_posts_entry_edit', 'cat', 2147483647, 1, 4),
+('bx_posts_entry_edit', 'text', 2147483647, 1, 5),
+('bx_posts_entry_edit', 'attachments', 2147483647, 1, 6),
+('bx_posts_entry_edit', 'link', 2147483647, 1, 7),
+('bx_posts_entry_edit', 'pictures', 2147483647, 1, 8),
+('bx_posts_entry_edit', 'videos', 2147483647, 1, 9),
+('bx_posts_entry_edit', 'sounds', 2147483647, 1, 10),
+('bx_posts_entry_edit', 'files', 2147483647, 1, 11),
+('bx_posts_entry_edit', 'polls', 2147483647, 1, 12),
+('bx_posts_entry_edit', 'covers', 2147483647, 1, 13),
+('bx_posts_entry_edit', 'allow_view_to', 2147483647, 1, 14),
+('bx_posts_entry_edit', 'cf', 2147483647, 1, 15),
+('bx_posts_entry_edit', 'location', 2147483647, 1, 16),
+('bx_posts_entry_edit', 'allow_comments', 192, 1, 17),
+('bx_posts_entry_edit', 'published', 192, 0, 18),
+('bx_posts_entry_edit', 'do_submit', 2147483647, 1, 19),
+
+('bx_posts_entry_view', 'cat', 2147483647, 1, 1),
+('bx_posts_entry_view', 'added', 2147483647, 1, 2),
+('bx_posts_entry_view', 'changed', 2147483647, 1, 3),
+('bx_posts_entry_view', 'published', 192, 1, 4);
+
+-- FORMS: poll
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_posts_poll', 'bx_posts', '_bx_posts_form_poll', '', '', 'do_submit', 'bx_posts_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:28:"BxPostsFormPollCheckerHelper";}', 0, 1, 'BxPostsFormPoll', 'modules/boonex/posts/classes/BxPostsFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_posts_poll_add', 'bx_posts', 'bx_posts_poll', '_bx_posts_form_poll_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_posts_poll', 'bx_posts', 'text', '', '', 0, 'text', '_bx_posts_form_poll_input_sys_text', '_bx_posts_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_posts_poll', 'bx_posts', 'answers', '', '', 0, 'custom', '_bx_posts_form_poll_input_sys_answers', '_bx_posts_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_posts_form_poll_input_answers_err', '', '', 1, 0),
+('bx_posts_poll', 'bx_posts', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_poll', 'bx_posts', 'do_submit', '_bx_posts_form_poll_input_do_submit', '', 0, 'submit', '_bx_posts_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_poll', 'bx_posts', 'do_cancel', '_bx_posts_form_poll_input_do_cancel', '', 0, 'button', '_bx_posts_form_poll_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_posts_poll_add', 'text', 2147483647, 1, 1),
+('bx_posts_poll_add', 'answers', 2147483647, 1, 2),
+('bx_posts_poll_add', 'controls', 2147483647, 1, 3),
+('bx_posts_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_posts_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+-- Forms -> Attach link
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_posts_attach_link', 'bx_posts', '_bx_posts_form_attach_link', '', '', 'do_submit', 'bx_posts_links', 'id', '', '', '', 0, 1, '', '');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_posts_attach_link_add', 'bx_posts', 'bx_posts_attach_link', '_bx_posts_form_attach_link_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_posts_attach_link', 'bx_posts', 'content_id', '0', '', 0, 'hidden', '_bx_posts_form_attach_link_input_sys_content_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'url', '', '', 0, 'text', '_bx_posts_form_attach_link_input_sys_url', '_bx_posts_form_attach_link_input_url', '', 0, 0, 0, '', '', '', 'Preg', 'a:1:{s:4:"preg";s:0:"";}', '_bx_posts_form_attach_link_input_url_err', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'do_submit', '_bx_posts_form_attach_link_input_do_submit', '', 0, 'submit', '_bx_posts_form_attach_link_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'do_cancel', '_bx_posts_form_attach_link_input_do_cancel', '', 0, 'button', '_bx_posts_form_attach_link_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_posts_attach_link_add', 'content_id', 2147483647, 1, 1),
+('bx_posts_attach_link_add', 'url', 2147483647, 1, 2),
+('bx_posts_attach_link_add', 'controls', 2147483647, 1, 3),
+('bx_posts_attach_link_add', 'do_submit', 2147483647, 1, 4),
+('bx_posts_attach_link_add', 'do_cancel', 2147483647, 1, 5);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_posts_cats', '_bx_posts_pre_lists_cats', 'bx_posts', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_posts_cats', '', 0, '_sys_please_select', ''),
+('bx_posts_cats', '1', 1, '_bx_posts_cat_Animals_Pets', ''),
+('bx_posts_cats', '2', 2, '_bx_posts_cat_Architecture', ''),
+('bx_posts_cats', '3', 3, '_bx_posts_cat_Art', ''),
+('bx_posts_cats', '4', 4, '_bx_posts_cat_Cars_Motorcycles', ''),
+('bx_posts_cats', '5', 5, '_bx_posts_cat_Celebrities', ''),
+('bx_posts_cats', '6', 6, '_bx_posts_cat_Design', ''),
+('bx_posts_cats', '7', 7, '_bx_posts_cat_DIY_Crafts', ''),
+('bx_posts_cats', '8', 8, '_bx_posts_cat_Education', ''),
+('bx_posts_cats', '9', 9, '_bx_posts_cat_Film_Music_Books', ''),
+('bx_posts_cats', '10', 10, '_bx_posts_cat_Food_Drink', ''),
+('bx_posts_cats', '11', 11, '_bx_posts_cat_Gardening', ''),
+('bx_posts_cats', '12', 12, '_bx_posts_cat_Geek', ''),
+('bx_posts_cats', '13', 13, '_bx_posts_cat_Hair_Beauty', ''),
+('bx_posts_cats', '14', 14, '_bx_posts_cat_Health_Fitness', ''),
+('bx_posts_cats', '15', 15, '_bx_posts_cat_History', ''),
+('bx_posts_cats', '16', 16, '_bx_posts_cat_Holidays_Events', ''),
+('bx_posts_cats', '17', 17, '_bx_posts_cat_Home_Decor', ''),
+('bx_posts_cats', '18', 18, '_bx_posts_cat_Humor', ''),
+('bx_posts_cats', '19', 19, '_bx_posts_cat_Illustrations_Posters', ''),
+('bx_posts_cats', '20', 20, '_bx_posts_cat_Kids_Parenting', ''),
+('bx_posts_cats', '21', 21, '_bx_posts_cat_Mens_Fashion', ''),
+('bx_posts_cats', '22', 22, '_bx_posts_cat_Outdoors', ''),
+('bx_posts_cats', '23', 23, '_bx_posts_cat_Photography', ''),
+('bx_posts_cats', '24', 24, '_bx_posts_cat_Products', ''),
+('bx_posts_cats', '25', 25, '_bx_posts_cat_Quotes', ''),
+('bx_posts_cats', '26', 26, '_bx_posts_cat_Science_Nature', ''),
+('bx_posts_cats', '27', 27, '_bx_posts_cat_Sports', ''),
+('bx_posts_cats', '28', 28, '_bx_posts_cat_Tattoos', ''),
+('bx_posts_cats', '29', 29, '_bx_posts_cat_Technology', ''),
+('bx_posts_cats', '30', 30, '_bx_posts_cat_Travel', ''),
+('bx_posts_cats', '31', 31, '_bx_posts_cat_Weddings', ''),
+('bx_posts_cats', '32', 32, '_bx_posts_cat_Womens_Fashion', '');
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_posts', 'bx_posts', 'bx_posts_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_posts_posts', 'id', 'author', 'title', 'comments', '', ''),
+('bx_posts_notes', 'bx_posts', 'bx_posts_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_posts_posts', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_posts', 'bx_posts_votes', 'bx_posts_votes_track', '604800', '1', '1', '0', '1', 'bx_posts_posts', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_posts_reactions', 'bx_posts_reactions', 'bx_posts_reactions_track', '604800', '1', '1', '1', '1', 'bx_posts_posts', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_posts_poll_answers', 'bx_posts_polls_answers_votes', 'bx_posts_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_posts_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxPostsVotePollAnswers', 'modules/boonex/posts/classes/BxPostsVotePollAnswers.php');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts', 'bx_posts_scores', 'bx_posts_scores_track', '604800', '0', 'bx_posts_posts', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts', 'bx_posts_reports', 'bx_posts_reports_track', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_notes', 'bx_posts_posts', 'id', 'author', 'reports', '', '');
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts_views_track', '86400', '1', 'bx_posts_posts', 'id', 'author', 'views', '', '');
+
+-- FAVORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts_favorites_track', 'bx_posts_favorites_lists', '1', '1', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_posts', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts', '1', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_posts', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_posts', '_bx_posts', 'bx_posts', 'added', 'edited', 'deleted', '', ''),
+('bx_posts_cmts', '_bx_posts_cmts', 'bx_posts', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_posts', 'bx_posts_administration', 'id', '', ''),
+('bx_posts', 'bx_posts_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_posts', 'bx_posts', 'bx_posts', '_bx_posts_search_extended', 1, '', ''),
+('bx_posts_cmts', 'bx_posts_cmts', 'bx_posts', '_bx_posts_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_posts', '_bx_posts', '_bx_posts', 'bx_posts@modules/boonex/posts/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_posts', 'content', '{url_studio}module.php?name=bx_posts', '', 'bx_posts@modules/boonex/posts/|std-icon.svg', '_bx_posts', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 51 - 0
modules/boonex/protean/updates/13.0.1_13.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Protean',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/protean/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'protean_update_1301_1302',
+
+    'module_dir' => 'boonex/protean/',
+    'module_uri' => 'protean',
+
+    'db_prefix' => 'bx_protean_',
+    'class_prefix' => 'BxProtean',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Protean Template',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 26 - 0
modules/boonex/protean/updates/13.0.1_13.0.2/install/installer.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxProteanUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function update($aParams)
+    {
+        $aResult = parent::update($aParams);
+        if(!$aResult['result'])
+                return $aResult;
+
+        $oCacheUtilities = BxDolCacheUtilities::getInstance();
+        $oCacheUtilities->clear('css');
+        $oCacheUtilities->clear('template');
+
+        return $aResult;
+    }
+}

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor