diff --git a/class_post_it_colors.php b/class_post_it_colors.php
new file mode 100644
index 0000000..1ca30e7
--- /dev/null
+++ b/class_post_it_colors.php
@@ -0,0 +1,71 @@
+get_post_it_color($post_id);
+ }
+ function generate_post_it_colors() {
+ // Überprüfe, ob die Farben bereits in der wp_options gespeichert sind
+ $colors = get_option('post_it_colors');
+
+ // Wenn noch keine Farben vorhanden sind, generiere 12 Farben
+ if (!$colors) {
+ $colors = [];
+ for ($i = 0; $i < 12; $i++) {
+ $colors[] = $this->generate_contrast_color();
+ }
+ // Speichere die generierten Farben in wp_options
+ update_option('post_it_colors', $colors);
+ }
+
+ return $colors;
+ }
+
+ function generate_contrast_color() {
+ // Helligkeit der Farben für gute Lesbarkeit mit schwarzer Schrift
+ $min_brightness = 130;
+
+ do {
+ // Generiere eine zufällige Farbe
+ $color = sprintf('#%02X%02X%02X', mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
+ // Berechne die Helligkeit der Farbe
+ $brightness = $this->calculate_brightness($color);
+ } while ($brightness < $min_brightness);
+
+ return $color;
+ }
+
+ function calculate_brightness($hex) {
+ // Entferne das "#" Zeichen, wenn vorhanden
+ $hex = str_replace('#', '', $hex);
+
+ // Wandle HEX in RGB um
+ $r = hexdec(substr($hex, 0, 2));
+ $g = hexdec(substr($hex, 2, 2));
+ $b = hexdec(substr($hex, 4, 2));
+
+ // Berechne die Helligkeit (simplifiziert)
+ return ($r * 299 + $g * 587 + $b * 114) / 1000;
+ }
+
+ function get_post_it_color($post_id) {
+ // Überprüfe, ob die Farbe bereits als Meta-Information gespeichert ist
+ $color = get_post_meta($post_id, '_post_it_color', true);
+
+ if (!$color) {
+ // Hol die Liste der 12 Farben
+ $colors = $this->generate_post_it_colors();
+
+ // Wähle eine zufällige Farbe aus
+ $color = $colors[array_rand($colors)];
+
+ // Speichere die Farbe als Post-Meta
+ update_post_meta($post_id, '_post_it_color', $color);
+ }
+
+ return $color;
+ }
+
+}
diff --git a/css/colors.css b/css/colors.css
new file mode 100644
index 0000000..e8ab7be
--- /dev/null
+++ b/css/colors.css
@@ -0,0 +1,17 @@
+:root{
+ --textcolor: var(--theme-palette-color-3);
+ --background: var(--theme-palette-color-7);
+ --buttoncolor: var(--theme-palette-color-1);
+ --buttontext: var(--theme-palette-color-6);
+ --inverse: var(--theme-palette-color-4);
+ --akcent: var(--theme-palette-color-2);
+ --akcent2: var(--theme-palette-color-5);
+ --background1: var(--theme-palette-color-6);
+ --background2: var(--theme-palette-color-8);
+ --modal-background: rgba(0,0,0,0.4);
+ --bordercolor: var(--theme-palette-color-2);
+ --bordercolor2: var(--theme-palette-color-9);
+ --gray: #d3d3d3;
+
+}
+
diff --git a/css/group-builder.css b/css/group-builder.css
new file mode 100644
index 0000000..81b1da8
--- /dev/null
+++ b/css/group-builder.css
@@ -0,0 +1,573 @@
+.single-group_post .page-title {
+ background-image: linear-gradient(90deg, rgba(255, 255, 255, 0.76) 10%, rgba(162, 162, 162, 0) 80%);
+ padding-left: 10px;
+ margin-left: -10px;
+}
+.entry-card.card-content.group_post, .entry-card.card-content.pinwall_post {
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-rows: minmax(20px,1fr);
+}
+
+.attendees {
+ margin-top: 0px;
+ border-top: 4px solid #ddd;
+
+}
+.attendees-wrapper {
+ position: relative;
+}
+.single-group_post .attendees-wrapper {
+ position: relative;
+ z-index: 50;
+ max-width: 500px;
+ margin: -75px auto 20px;
+}
+@media screen and (max-width: 1200px) {
+ .single-group_post .attendees-wrapper {
+ position: relative;
+ z-index: 50;
+ margin-top: -22px;
+ margin-bottom: -52px;
+ }
+}
+.attendees-wrapper p{
+ color: var(--inverse);
+}
+.attendees-label {
+ color: var(--inverse);
+ text-align: center;
+}
+.group_post .attendees-wrapper {
+ margin-top: 10px;
+}
+
+
+.pinwall_post .attendees-label {
+ text-align: right;
+}
+.assoziated-groups {
+ list-style: none;
+}
+.assoziated-group-link a span {
+ background-color: var(--buttoncolor);
+ color: var(--inverse);
+ border-radius: 50%;
+ font-size: 32px;
+ height: fit-content;
+ width: fit-content;
+ padding: 2px;
+ margin-right: 7px;
+ margin-top: -5px;
+ margin-left: -3px;
+}
+.assoziated-group-link a:hover span {
+ border-radius: 50%;
+ font-size: 33px;
+ height: fit-content;
+ width: fit-content;
+ padding: 3px;
+ margin-top: -7px;
+ box-shadow: 2px 2px 5px 3px rgba(0,0,0,0.3);
+}
+
+.assoziated-groups a{
+ background-color: var(--buttoncolor);
+ color: var(--inverse);
+ border: none;
+ border-radius: 10px;
+ padding: 5px 10px;
+ cursor: pointer;
+ padding-left:0;
+
+}
+.assoziated-groups a:hover{
+ background-color: var(--inverse);
+ color: var(--buttoncolor)
+}
+.avatar-list {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+ min-height: 50px;
+}
+.pinwall_post .avatar-list {
+ justify-content: right;
+}
+.avatar-wrapper {
+ display: inline-block;
+ margin-right: 5px;
+ position: relative;
+}
+
+.avatar-wrapper img {
+ border-radius: 50%;
+ width: 50px;
+ height: 50px;
+}
+.avatar-wrapper img:hover {
+ border: 2px solid var(--buttoncolor);
+ scale: 1.3;
+}
+
+.avatar-wrapper:hover::after {
+ content: attr(title);
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: var(--background1, #dddddd);
+ color: var(--textcolor, #000000);
+ padding: 5px;
+ border-radius: 3px;
+ font-size: 12px;
+ white-space: nowrap;
+}
+.single-group_post .avatar-list a {
+ display: inline-block;
+ opacity: 0;
+ transform: translateY(-100px);
+ animation: dropIn 0.5s forwards;
+}
+
+.single-group_post .avatar-list a:nth-child(1) {
+ animation-delay: 0.2s;
+}
+
+.single-group_post .avatar-list a:nth-child(2) {
+ animation-delay: 0.4s;
+}
+
+.single-group_post .avatar-list a:nth-child(3) {
+ animation-delay: 0.6s;
+}
+
+@keyframes dropIn {
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.show-interest,
+.create-group,
+.leave-group {
+ padding: 5px 10px;
+ background-color: var(--background1);
+ color: var(--inverse);
+ border: none;
+ border-radius: 3px;
+ cursor: pointer;
+}
+
+.show-interest:hover,
+.create-group:hover,
+.leave-group:hover {
+ /*background-color: var(--buttoncolor);*/
+}
+
+
+/** Group Form **/
+.edit-group, .toggle-join-option, .generate-invite-link {
+ margin-top: 10px;
+ padding: 5px 10px;
+ background-color: var(--gray);
+ color: var(--inverse);
+ border: none;
+ cursor: pointer;
+}
+
+.edit-group:hover, .toggle-join-option:hover, .generate-invite-link:hover {
+ background-color: var(--akcent);
+}
+
+/* Modal Styles */
+.modal {
+ display: none;
+ position: fixed;
+ z-index: 99;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ background-color: var(--modal-background);
+}
+
+.modal-content {
+ background-color: var(--background1);
+ margin: 15% auto;
+ padding: 20px;
+ border: var(--buttoncolor);
+ width: 80%;
+ max-width: 780px;
+ box-shadow: 3px 3px 5px rgba(0,0,0,0.3);
+ border-radius: 5px;
+}
+
+.modal-close {
+ color: var(--textcolor);
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.modal-close:hover,
+.modal-close:focus {
+ color: var(--akcent);
+ text-decoration: none;
+ cursor: pointer;
+}
+
+/* Form Styles */
+.edit-group-form,
+.edit-comment-form {
+ margin-top: 20px;
+}
+
+.edit-group-form input[type="text"],
+.edit-group-form textarea,
+.edit-comment-form textarea {
+ width: 100%;
+ padding: 8px;
+ margin-bottom: 10px;
+}
+
+.edit-group-form input[type="submit"],
+.edit-comment-form button[type="submit"] {
+ background-color: var(--buttoncolor);
+ color: var(--inverse);
+ padding: 10px 15px;
+ border: none;
+ cursor: pointer;
+}
+
+.edit-group-form input[type="submit"]:hover,
+.edit-comment-form button[type="submit"]:hover {
+ background-color: var(--akcent);
+}
+
+/* Button Styles */
+.edit-group,
+.toggle-join-option,
+.generate-invite-link,
+.edit-comment {
+ margin-top: 10px;
+ padding: 5px 10px;
+ background-color: var(--buttoncolor);
+ color: var(--inverse);
+ border: none;
+ cursor: pointer;
+}
+
+.edit-group:hover,
+.toggle-join-option:hover,
+.generate-invite-link:hover,
+.edit-comment:hover {
+ background-color: var(--akcent);
+}
+.edit-button-wrapper {
+ display: inline;
+ justify-content: right;
+ position: relative;
+}
+.edit-button-wrapper button{
+ /*position: absolute;
+ top:20px*/
+}
+/* Invite Link Styles */
+#invite-link-modal input[type="text"] {
+ width: 100%;
+ padding: 8px;
+ margin-bottom: 10px;
+}
+
+.copy-link {
+ background-color: var(--buttoncolor);
+ color: var(--background2);
+ padding: 5px 10px;
+ border: none;
+ cursor: pointer;
+}
+
+.copy-link:hover {
+ background-color: var(--akcent);
+}
+
+/** Editor styles **/
+.edit-thumbnail div.image-wrap {
+ max-width: 100%!important;
+ max-height: 200px;
+ overflow: hidden;
+ width: 100%;
+}
+.edit-thumbnail div.image-wrap img{
+ max-width: 100%!important;
+ max-height: unset!important;
+ width: 100%;
+}
+
+/** Action Buttons **/
+
+.group-builder-button-container {
+ overflow: hidden;
+ border-radius: 25px;
+ transition: width 0.3s ease;
+ width: 45px; /* Anfangsbreite */
+ text-align: center;
+ display: flex;
+ justify-content: left;
+ position: relative;
+
+}
+.group-builder-create-button-container {
+ position: absolute;
+ top: 2px;
+}
+.group-builder-create-button-container button {
+ background-color: var(--buttoncolor);
+}
+.group-builder-button-container:hover {
+ width: auto; /* Breite bei Hover */
+ position: absolute;
+}
+.group-builder-button-container button {
+ padding: 8px 11px;
+ border: none;
+ background-color: var(--gray);
+ color: var(--inverse);
+ border-radius: 25px;
+ cursor: pointer;
+ white-space: nowrap;
+ align-items: center;
+ justify-content: center;
+}
+.group-builder-button-container button svg {
+ top: 9px;
+ position: absolute;
+}
+.group-builder-button-container button span {
+ margin-left: 30px;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+.group-builder-button-container:hover button span {
+ opacity: 1;
+}
+.group-builder-join-button-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+}
+.group-builder-join-button-container button{
+ grid-column: 2;
+ background-color: var(--buttoncolor);
+ color: var(--background2);
+ padding: 5px 20px 7px;
+ border-radius: 3px;
+}
+
+.group-builder-join-button-container button:hover {
+ background-color: var(--akcent);
+}
+div.clearfix {
+ clear: both;
+ width: 100%;
+ display: block;
+}
+
+/** Toggle-join design für die Beitrittsoption von Gruppen **/
+.toggle-join-option {
+ padding: 5px 10px;
+ background-color: var(--buttoncolor);
+ color: var(--inverse);
+ border: none;
+ cursor: pointer;
+ border-radius: 3px;
+}
+
+.toggle-join-option:hover::after {
+ content: attr(title);
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: var(--buttoncolor, #dddddd);
+ color: var(--inverse, #000000);
+ padding: 5px 20px;
+ border-radius: 3px;
+ max-width: 300px;
+ font-size: 15px;
+ /*white-space: nowrap;*/
+}
+.copy-invite-link-wrapper, .leave-btn-wrapper {
+ display: grid;
+ grid-template-columns: auto 200px;
+ border: 1px solid var(--akcent);
+ border-radius: 3px;
+ padding: 5px;
+}
+.leave-btn-wrapper {
+ margin-top: 10px;
+ border-color: var(--gray);
+}
+.leave-btn-wrapper span {
+ padding: 5px;
+}
+.leave-btn-wrapper button:hover {
+ background-color: var(--akcent);
+ color: var(--background2);
+}
+.copy-invite-link-label {
+ padding: 5px;
+}
+
+
+
+/** Adminbar **/
+
+.custom-modal, .custom-mega-menu {
+ z-index: 99!important;
+}
+.custom-modal-close, .custom-mega-menu-close {
+ color: var(--textcolor)!important;
+}
+.custom-modal-close:hover, .custom-modal-close:focus,
+.custom-mega-menu-close:hover, .custom-mega-menu-close:focus {
+ color: var(--buttoncolor)!important;
+}
+.custom-modal-content, .custom-mega-menu-content {
+ background-color: var(--background)!important;
+ color: var(--textcolor)!important;
+ border: 3px solid var(--textcolor) !important;
+}
+.custom-modal-content > div, .custom-mega-menu-content > div {
+ overflow: auto;
+ max-height: calc(100vh - 50px);
+}
+#wpadminbar #wp-admin-bar-my-account.with-avatar #wp-admin-bar-user-actions > li {
+ margin-left: 20px;
+}
+#wp-admin-bar-root-default .custom a.ab-item {
+ color: var(--akcent);
+}
+/*schrift in der mobilen adminbar sichtbar machen */
+@media screen and (max-width: 782px) {
+ #wpadminbar .ab-label {
+ border: 0;
+ clip: unset;
+ clip-path: unset;
+ height: unset;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 200px;
+ word-wrap: normal !important;
+ }
+
+}
+/** Formularfelder in modals**/
+.custom-modal .acf-field[data-name="group_title"] input {
+ font-size: 30px;
+ font-weight: bold;
+}
+.custom-modal .acf-field[data-name="group_exerpt"] textarea {
+ font-size: 20px;
+ font-weight: bold;
+ height: 80px;
+}
+.custom-modal .acf-fields > .acf-field {
+ border-top: 0;
+}
+.custom-modal .acf-label{
+ font-size: 12px!important;
+ color: #444;
+}
+.custom-modal .acf-label label{
+ font-size: 16px!important;
+ color: #444;
+}
+/** Comments **/
+
+.single-group_post article > .ct-comments {
+ margin-top: 30px;
+ padding-top:0px;
+}
+.ct-comments-title, #reply-title {
+ display: none;
+}
+.ct-comment-inner {
+ padding-block: 10px;
+ position: relative;
+}
+.ct-comment-inner .cld-prevent{
+ color: var(--buttoncolor);
+}
+.ct-comment-meta{
+ background: rgba(22, 127, 168, 0.15);
+ border-radius: 25px 0 0 0;
+
+}
+.cld-like-dislike-wrap {
+ position: absolute;
+ left: 15px;
+ top: 61px;
+}
+.cld-count-wrap {
+ margin-left: 5px;
+ font-weight: bold;
+}
+
+
+/** FEP Notificationbar **/
+#fep-notification-bar {
+ background-color: var(--akcent);
+ border-radius: 5px;
+ border: 1px solid var(--inverse);
+ box-sizing: border-box;
+ color: var(--inverse);
+ font-size: 15px;
+ font-weight: bold;
+ padding: 12px;
+ position: relative;
+ text-align: center;
+ width: 100%;
+ z-index: 999999;
+}
+#fep-notification-bar a {
+ color: var(--buttontext)!important;
+ text-decoration: underline;
+}
+#fep-notification-bar button{
+ margin-top: -10px;
+}
+
+/** HEADER MENU **/
+a.ct-menu-link {
+ background-position: center center;
+}
+#offcanvas a.ct-menu-link {
+ /*background-position: center left!important;*/
+}
+@media screen and (max-width: 782px) {
+ li.menu-item:hover, li.menu-item:hover:active {
+ background-color: var(--menu-indicator-hover-color, var(--theme-palette-color-2))
+ }
+}
+
+/** Realtime Comment Notification Button **/
+
+#realtime-comment-notification {
+ width: 100%;
+ display: grid;
+ background-color: var(--buttontext);
+ color: var(--background2);
+ padding: 5px;
+ border-radius: 3px;
+ border: 1px solid var(--buttoncolor);
+ animation:slide 3s ease-in-out infinite alternate;
+ background-image: linear-gradient(-60deg, var(--background2) 50%, var(--akcent));
+
+}
diff --git a/group-builder.php b/group-builder.php
index 9db5e1c..e4ab276 100644
--- a/group-builder.php
+++ b/group-builder.php
@@ -7,12 +7,14 @@
*/
if (!defined('ABSPATH')) exit;
+require_once 'class_post_it_colors.php';
/**
* Plugin-Klasse zur Verwaltung der Interessenbekundung und Gruppenerstellung
*/
class GroupBuilder {
private static $instance = null;
+ private static $adminbar;
/**
* Gibt eine Instanz der Klasse zurück
@@ -31,23 +33,268 @@ public static function get_instance() {
private function __construct() {
$this->setup_actions();
}
+ /**
+ * Aktualisiert den Zeitstempel der letzten Änderung
+ *
+ * @param int $post_id ID des Beitrags
+ */
+ private function update_change_timestamp($post_id) {
+ update_post_meta($post_id, '_avatar_list_updated', time());
+ }
+
/**
* Initialisiert die Action Hooks für das Plugins
*/
private function setup_actions() {
- add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
+
+ add_action('admin_bar_menu', array($this, 'set_adminbar'),10000);
+ add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'),800);
+
+
+ // AJAX-Aktionen
add_action('wp_ajax_show_interest', array($this, 'ajax_show_interest'));
add_action('wp_ajax_create_group', array($this, 'ajax_create_group'));
- add_filter('the_content', array($this, 'display_interest_button'));
+ add_action('wp_ajax_leave_group', array($this, 'ajax_leave_group'));
+ add_action('wp_ajax_get_avatar_list', array($this, 'ajax_get_avatar_list'));
+ add_action('wp_ajax_withdraw_interest', array($this, 'ajax_withdraw_interest'));
+ add_action('wp_ajax_join_group', array($this, 'ajax_join_group'));
+ add_action('wp_ajax_toggle_join_option', array($this, 'ajax_toggle_join_option'));
+ add_action('wp_ajax_generate_invite_link', array($this, 'ajax_generate_invite_link'));
+
+ // Kommentar-Aktionen
+ add_action('pre_get_comments', array($this, 'restrict_group_comments'));
+ add_filter('comment_form_defaults', array($this, 'customize_comment_form'));
+ add_filter('comments_template', array($this, 'customize_comments_template'));
+
+ add_shortcode('group_members', array($this, 'group_members_shortcode'));
+ add_shortcode('group_edit_form', array($this, 'group_edit_form_shortcode'));
+
+ // Integration in das Blocksy-Theme
+ add_action('blocksy:loop:card:end' , array($this, 'get_avatar_list'));
+ add_action('blocksy:comments:before' , array($this, 'get_pinnwall_post_avatar_list'));
+ add_action('blocksy:header:after' , array($this, 'get_group_post_avatar_list'));
+ add_action('blocksy:single:content:top' , array($this, 'join_group_button'));
+ add_action('blocksy:single:content:top' , array($this, 'group_goal'));
+ add_action('blocksy:comments:top' , array($this, 'comments_header'));
+
+
+ #add_action('blocksy:header:after' , array($this, 'invite_link_copy_button'));
+
+ // Add Heartbeat API support
+ add_filter('heartbeat_received', array($this, 'heartbeat_received'), 10, 2);
+ add_filter('heartbeat_nopriv_received', array($this, 'heartbeat_received'), 10, 2);
+
+
+ // Integration in Ultimate Member
+ add_filter( 'um_profile_tabs', array( $this, 'ultimate_member_integration_tab' ), 1000 );
+ add_filter( 'um_user_profile_tabs', array( $this, 'ultimate_member_integration_tab' ), 1000 );
+ add_action('um_profile_content_group-builder', array( $this, 'ultimate_member_integration_content' ) );
+ add_filter( 'um_profile_query_make_posts', [$this,'ultimate_member_integration_profile_query_make_posts'], 10, 1 );
+
+
+ // Tägliche Bereinigung der Daten
+ if (!wp_next_scheduled('group_builder_cleanup')) {
+ wp_schedule_event(time(), 'daily', 'group_builder_cleanup');
+ }
+ add_action('group_builder_cleanup', array($this, 'cleanup_orphaned_data'));
+ }
+
+ public function heartbeat_received($response, $data) {
+ if (empty($data['group_builder_request'])) {
+ return $response;
+ }
+
+ $updated_lists = array();
+
+ foreach ($data['group_builder_request'] as $request) {
+ $post_id = intval($request['post_id']);
+ $client_timestamp = intval($request['timestamp']);
+
+ $server_timestamp = get_post_meta($post_id, '_avatar_list_updated', true);
+
+ if (!$server_timestamp) {
+ $server_timestamp = time();
+ update_post_meta($post_id, '_avatar_list_updated', $server_timestamp);
+ }
+
+ if ($client_timestamp < $server_timestamp) {
+ $avatar_list = $this->get_avatar_list($post_id);
+ if ($avatar_list !== null) {
+ $updated_lists[] = array(
+ 'post_id' => $post_id,
+ 'updated' => true,
+ 'avatar_list' => $avatar_list,
+ 'timestamp' => $server_timestamp
+ );
+ }
+ } else {
+ $updated_lists[] = array(
+ 'post_id' => $post_id,
+ 'updated' => false
+ );
+ }
+ }
+
+ $response['group_builder_response'] = $updated_lists;
+
+ return $response;
+ }
+
+ /**
+ * Integriert das Plugin Custom WP Adminbar von Joachim Happel
+ * @see https://github.com/johappel/custom_wp_adminbar
+ * @param $customized_wordpress_adminbar Custom_AdminBar Class
+ * stellt eine angepasste Adminbar auch für Abonnenten bereit und stellt eine Modal-Fenster Funktionalität zur Verfügung.
+ */
+ public function set_adminbar(){
+ if(is_admin()){
+ return;
+ }
+ global $customized_wordpress_adminbar;
+
+ $user = wp_get_current_user();
+ $adminbar = $customized_wordpress_adminbar;;
+ $adminbar->remove('search');
+ $adminbar->remove('logout');
+ $adminbar->remove('user-info');
+
+ $adminbar->edit('my-account',null,'/user/');
+ $adminbar->add('top-secondary','','#', ' ');
+ $adminbar->add('user-actions','Profil ansehen','/user/', 'dashicons-admin-users');
+ $adminbar->add('user-actions','Profil bearbeiten','/user?um_action=edit', 'dashicons-edit');
+ $adminbar->add('user-actions','Meine Gruppen','/user/wpadmin/?profiletab=group-builder', 'dashicons-admin-groups');
+ $adminbar->add('user-actions','Nachricht schreiben','/account/fep-um/', 'dashicons-email-alt');
+
+ $adminbar->add('user-actions','Konto Einstellungen','/account/', 'dashicons-admin-settings');
+ $adminbar->add('user-actions','Abmelden',wp_logout_url(), 'dashicons-exit');
+ $parent ='';
+ $parent_home = $adminbar->add('',get_bloginfo('name'),home_url(), 'dashicons-admin-home');
+ if(is_user_logged_in()){
+ $adminbar->add($parent_home,'Leute', '/netwerk/');
+ $adminbar->add($parent_home,'Gruppen', '/group_post/');
+ $adminbar->add('','Pinwand Karte','/pinwand-karte-erstellen/', 'dashicons-plus');
+ }
+ if(is_singular('pinwall_post') && is_user_logged_in()){
+ if(current_user_can('edit_post', get_the_ID())){
+ $adminbar->addModal('', 'Bearbeiten', 'edit_pinwall_post', 'dashicons-edit');
+ $adminbar->addModalContent('edit_pinwall_post',
+ '
Pinwand Karte bearbeiten '.do_shortcode('[acfe_form name="edit_pinwall_post"]').'',
+ 'full');
+ }
+ }
+
+ if(is_singular('group_post')){
+ #echo do_shortcode('[acfe_form name="edit_group"]');
+ $parent ='';
+ $group_settings_content = '
+
Gruppe konfigurieren '.
+ //do_shortcode('[acfe_form name="edit_group"]').
+ '';
+ $group_tools_content = '';
+ if(group_builder_user_can(get_the_ID(), 'edit')){
+ $adminbar->addMegaMenu($parent, 'Gruppe konfigurieren', 'group-edit-modal', 'dashicons-edit');
+ $adminbar->addMegaMenu($parent, 'Lernwerkzeuge konfigurieren', 'group_tools', 'dashicons-admin-generic');
+ #$adminbar->addMegaMenuContent('group_settings',$group_settings_content);
+ $adminbar->addMegaMenuContent('group_tools','
Lernwerkzeuge konfigurieren ');
+ }
+ $this->display_modal_frame();
+ }
+ $adminbar->add_modal_and_mega_menu_html();
+
+
}
+
+
/**
* Lädt die benötigten Skripte und Stile
*/
public function enqueue_scripts() {
wp_enqueue_script('group-builder-js', plugin_dir_url(__FILE__) . 'js/group-builder.js', array('jquery'), '1.0', true);
- wp_enqueue_style('group-builder-css', plugin_dir_url(__FILE__) . 'css/group-builder.css');
+ wp_enqueue_style('group-builder-css', plugin_dir_url(__FILE__) . 'css/colors.css');
+ wp_enqueue_style('group-builder-colors-css', plugin_dir_url(__FILE__) . 'css/group-builder.css');
wp_localize_script('group-builder-js', 'group_builder_ajax', array('ajax_url' => admin_url('admin-ajax.php')));
+ //Lade Dashicons https://developer.wordpress.org/resource/dashicons ins Frontend
+ wp_enqueue_style('dashicons');
+ wp_enqueue_script('heartbeat');
+
+
+ }
+ /**
+ * AJAX-Funktion zum Anzeigen des Interesses an einem Beitrag
+ */
+ public function ajax_leave_group() {
+ $post_id = $group_id= isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ if(get_post_type($post_id) !== 'group_post'){
+ wp_send_json_error('Ungültige Anfrage');
+ }
+ $user_id = get_current_user_id();
+
+
+ if (!$post_id || !$user_id) {
+ wp_send_json_error('Ungültige Anfrage');
+ }
+
+
+ $members = get_post_meta($group_id, '_group_members', true);
+ if (!is_array($members)) {
+ $members = array();
+ }
+
+ $key = array_search($user_id, $members);
+ if ($key !== false) {
+ unset($members[$key]);
+ update_post_meta($group_id, '_group_members', array_values($members));
+
+ // Aktualisiere den Zeitstempel nach erfolgreichem Verlassen der Gruppe
+ $this->update_change_timestamp($post_id);
+
+ wp_send_json_success(array('post_id' => $post_id));
+ } else {
+ wp_send_json_error('Benutzer nicht in der Gruppe');
+ }
+ }
+ /**
+ * AJAX-Funktion zum Aktualisieren
+ * der Gruppen, Interessenten, Mitglieder und Aktionsschalter
+ */
+ public function ajax_get_avatar_list() {
+ $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ $client_timestamp = isset($_POST['timestamp']) ? intval($_POST['timestamp']) : 0;
+
+ if (!$post_id) {
+ wp_send_json_error(array('message' => 'Ungültige Anfrage: Keine post_id angegeben'));
+ return;
+ }
+
+ $post_type = get_post_type($post_id);
+ if($post_type !== 'group_post' && $post_type !== 'pinwall_post') {
+ wp_send_json_error(array('message' => 'Ungültiger Post-Typ: ' . $post_type));
+ return;
+ }
+
+ $server_timestamp = get_post_meta($post_id, '_avatar_list_updated', true);
+
+ if (!$server_timestamp) {
+ $server_timestamp = time();
+ update_post_meta($post_id, '_avatar_list_updated', $server_timestamp);
+ }
+
+ $avatar_list = $this->get_avatar_list($post_id);
+ if ($avatar_list === null) {
+ wp_send_json_error(array('message' => 'Fehler beim Abrufen der Avatar-Liste für Post-ID: ' . $post_id));
+ return;
+ }
+
+ $updated = $client_timestamp < $server_timestamp;
+
+ wp_send_json_success(array(
+ 'updated' => $updated,
+ 'avatar_list' => $updated ? $avatar_list : '',
+ 'timestamp' => $server_timestamp
+ ));
}
+
+
/**
* AJAX-Funktion zum Anzeigen des Interesses an einem Beitrag
*/
@@ -63,6 +310,7 @@ public function ajax_show_interest() {
$success = $this->add_user_interest($post_id, $user_id);
if ($success) {
+ $this->update_change_timestamp($post_id);
$avatar_list = $this->get_avatar_list($post_id);
wp_send_json_success($avatar_list);
} else {
@@ -82,28 +330,95 @@ public function ajax_create_group() {
$group_id = $this->create_group($post_id);
if ($group_id) {
+ $this->update_change_timestamp($post_id);
wp_send_json_success(array('group_id' => $group_id));
} else {
wp_send_json_error('Fehler beim Erstellen der Gruppe');
}
}
/**
- * Fügt den Interessen-Button und die Avatar-Liste zum Beitrag hinzu
- *
- * @param string $content Ursprünglicher Beitragstext
- * @return string Modifizierter Beitragstext
+ * AJAX-Funktion zum Verlassen einer Gruppe
*/
- public function display_interest_button($content) {
- if (get_post_type() === 'pinwall_post') {
- $post_id = get_the_ID();
- $avatar_list = $this->get_avatar_list($post_id);
- $interest_button = '+ ';
- $group_button = 'Gruppe gründen ';
+ public function ajax_withdraw_interest() {
+ $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ $user_id = get_current_user_id();
+
+ if (!$post_id || !$user_id) {
+ wp_send_json_error('Ungültige Anfrage');
+ }
+
+ $interested_users = get_post_meta($post_id, '_interested_users', true);
+ if (!is_array($interested_users)) {
+ $interested_users = array();
+ }
+
+ $key = array_search($user_id, $interested_users);
+ if ($key !== false) {
+ unset($interested_users[$key]);
+ update_post_meta($post_id, '_interested_users', array_values($interested_users));
+ // Aktualisiere den Zeitstempel nach erfolgreichem Verlassen der Gruppe
+ $this->update_change_timestamp($post_id);
+
+ wp_send_json_success(array('post_id' => $post_id));
+ } else {
+ wp_send_json_error('Benutzer war nicht interessiert');
+ }
+ }
+ /**
+ * AJAX-Funktion zum Beitreten einer Gruppe
+ */
+ public function ajax_join_group() {
+ $group_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
+ if ($group_id===0) {
+ $group_id = isset($_POST['group_id']) ? intval($_POST['group_id']) : 0;
+ }
+ $user_id = get_current_user_id();
+
+ if (!$group_id || !$user_id || get_post_type($group_id) !== 'group_post') {
+ wp_send_json_error('Ungültige Anfrage');
+ }
+
+ $members = get_post_meta($group_id, '_group_members', true);
+ if (!is_array($members)) {
+ $members = array();
+ }
+
+ if (!in_array($user_id, $members)) {
+ if ($this->check_group_limit($group_id)) {
+ $members[] = $user_id;
+ update_post_meta($group_id, '_group_members', $members);
+ $this->update_change_timestamp($group_id);
- $content .= $interest_button . $avatar_list . $group_button;
+ // Finde den zugehörigen pinwall_post
+ $args = array(
+ 'post_type' => 'pinwall_post',
+ 'meta_query' => array(
+ array(
+ 'key' => '_associated_group',
+ 'value' => $group_id,
+ ),
+ ),
+ );
+ $query = new WP_Query($args);
+
+ if ($query->have_posts()) {
+ $query->the_post();
+ $post_id = get_the_ID();
+ //@todo: check if this update is really necessary
+ $this->update_change_timestamp($post_id);
+ wp_reset_postdata();
+ wp_send_json_success(array('post_id' => $post_id));
+ } else {
+ wp_send_json_error('Zugehöriger pinwall_post nicht gefunden');
+ }
+ } else {
+ wp_send_json_error('Benutzer ist bereits Mitglied der Gruppe');
+ }
+ } else {
+ wp_send_json_error('Die Gruppe hat die maximale Anzahl an Mitgliedern erreicht');
}
- return $content;
}
+
/**
* Fügt das Nutzerinteresse zum Beitrag hinzu
*
@@ -112,8 +427,16 @@ public function display_interest_button($content) {
* @return bool Erfolg oder Misserfolg
*/
private function add_user_interest($post_id, $user_id) {
- // Implementierung der Logik zum Hinzufügen des Nutzerinteresses
- // Rückgabe: true bei Erfolg, false bei Fehler
+ $interested_users = get_post_meta($post_id, '_interested_users', true);
+ if (!is_array($interested_users)) {
+ $interested_users = array();
+ }
+ if (!in_array($user_id, $interested_users)) {
+ $interested_users[] = $user_id;
+ update_post_meta($post_id, '_interested_users', $interested_users);
+ return true;
+ }
+ return false;
}
/**
* Erstellt eine Gruppe zum Beitrag
@@ -122,34 +445,662 @@ private function add_user_interest($post_id, $user_id) {
* @return int ID der erstellten Gruppe
*/
private function create_group($post_id) {
- // Implementierung der Logik zur Gruppenerstellung
+ $interested_users = get_post_meta($post_id, '_interested_users', true);
+ if (!is_array($interested_users) || count($interested_users) < 2) {
+ return false;
+ }
+
$group_id = wp_insert_post(array(
'post_type' => 'group_post',
'post_title' => 'Interessengruppe zum Beitrag ' . get_the_title($post_id),
- // Weitere Felder...
+ 'post_status' => 'publish',
));
if ($group_id) {
- // Interessierte der Gruppe zuordnen
- // Link zum Pinwand-Beitrag aktualisieren
+ update_post_meta($group_id, '_group_members', $interested_users);
+ add_post_meta($post_id, '_associated_group', $group_id);
+ delete_post_meta($post_id, '_interested_users');
+ return $group_id;
+ }
+
+ return false;
+ }
+ /**
+ * Shortcode für die Anzeige der Avatar-Liste
+ *
+ * @param array $atts Attribute des Shortcodes
+ * @return string HTML-Code der Avatar-Liste
+ */
+ public function group_members_shortcode($atts) {
+ $atts = shortcode_atts(array(
+ 'post_id' => get_the_ID(),
+ ), $atts, 'group_members');
+
+ return $this->get_avatar_list($atts['post_id']);
+ }
+ public function get_group_post_avatar_list(){
+ if(is_singular(['group_post'])){
+ $this->get_avatar_list();
+ }
+ }
+ public function join_group_button(){
+ if(is_singular(['group_post']) && group_builder_user_can(get_the_ID(), 'join')){
+ echo '
+
+ Gruppe beitreten
+
+
';
+ }
+ }
+
+ public function get_pinnwall_post_avatar_list(){
+ if(is_singular(['pinwall_post'])){
+ $this->get_avatar_list();
+ }
+ }
+
+ public function group_goal(){
+ if(is_singular(['group_post'])){
+ $goal = get_post_meta(get_the_ID(), 'group_exerpt', true);
+ if($goal){
+ echo 'Unser Ziel: '.$goal.'
Herausforderungen und Schwerkunkte: ';
+
+ }
}
+ }
- return $group_id;
+ public function comments_header(){
+ if(is_singular(['group_post'])){
+ ?>
+
+
+
+ ...';
+ public function get_avatar_list($post_id = null) {
+
+ $do_print_output = false;
+ $has_groups = false;
+ $output = '';
+
+ $post_type = get_post_type($post_id);
+ if($post_type !== 'group_post' && $post_type !== 'pinwall_post') {
+ return null;
+ }
+ if($post_type === 'group_post'){
+ $group_id = $post_id;
+ $members = get_post_meta($post_id, '_group_members', true);
+
+ } else {
+ $assoziated_group_ids = get_post_meta($post_id, '_associated_group');
+ $group_section = '';
+ if(is_array($assoziated_group_ids) && !empty($assoziated_group_ids)){
+ $has_groups = true;
+ $group_section .= '';
+ } else {
+ $assoziated_group_ids = false;
+ }
+
+ $members = get_post_meta($post_id, '_interested_users', true);
+
+ }
+ if (!$post_id) {
+ $post_id = get_the_ID();
+ $do_print_output = true;
+ $output = '
';
+ }
+ if ($assoziated_group_ids) {
+ $output .= $group_section;
+ }
+ $output .= '
';
+
+ if($post_type === 'group_post'){
+ //$output .= '
Mitglieder
';
+ } else {
+ if ($has_groups) {
+ $output .= '
Interesse an weiterer Gruppe?
';
+ } else {
+ $output .= '
Interessenten
';
+ }
+ }
+
+ list($buttons, $create_button)= $this->get_action_buttons($post_id, $post_id,$has_groups);
+ $output .= '
';
+ $output .= $create_button;
+ $output .= '
'; //attendees-wrapper
+
+
+
+ if($do_print_output){
+ $output .= '
';
+ echo $output;
+ return false;
+ }
+ return $output;
+ }
+ /**
+ * Gibt die Aktionsschaltflächen für den Beitrag zurück
+ *
+ * @param int $post_id ID des Beitrags
+ * @param int $group_id ID der Gruppe
+ * @param bool $has_groups Gibt an, ob der Beitrag mit Gruppen assoziiert ist
+ * @return string HTML-Code der Aktionsschaltflächen
+ */
+ private function get_action_buttons($post_id, $group_id = null, $has_groups = false) {
+
+ $join_svg = ' ';
+ $leave_svg = ' ';
+
+ $current_user_id = get_current_user_id();
+ if (!$current_user_id) {
+ return '';
+ }
+ $create_button = '';
+ $button_template = '
+
+ %s
+ %s
+
+
';
+
+ $button2_template = '
+
+ %s
+
+
';
+ $buttons = '';
+
+ if (get_post_type($post_id) === 'pinwall_post') {
+ $interested_users = get_post_meta($post_id, '_interested_users', true);
+ if (!is_array($interested_users)) {
+ $interested_users = array();
+ }
+
+ if (in_array($current_user_id, $interested_users)) {
+ $buttons .= sprintf($button_template, 'withdraw-interest', $post_id,$leave_svg, 'Mein Interesse zurückziehen');
+
+ if (count($interested_users) >= 2) {
+ $create_button = sprintf($button2_template, 'create-group', $post_id, 'Gruppe gründen');
+ }
+ } else {
+ $buttons .= sprintf($button_template, 'show-interest', $post_id,$join_svg, 'Interesse zeigen');
+ }
+ } elseif ($group_id) {
+ $members = get_post_meta($group_id, '_group_members', true);
+ if (!is_array($members)) {
+ $members = array();
+ }
+ if(get_option('group_builder_avatar_actions')) {
+
+ if (in_array($current_user_id, $members)) {
+ $buttons .= sprintf($button_template, 'leave-group', $group_id,$leave_svg, 'Gruppe verlassen');
+ } else {
+ $buttons .= sprintf($button_template, 'join-group', $group_id,$join_svg, 'Gruppe beitreten');
+ }
+ }
+ if(!in_array($current_user_id, $members) && count($members) < get_option('group_builder_max_members',4)){
+ $buttons .= sprintf($button_template, 'join-group', $group_id,$join_svg, 'Gruppe beitreten');
+ }
+ }
+
+ return [$buttons, $create_button];
+ }
+ /**
+ * Überprüft, ob die Gruppe die maximale Anzahl an Mitgliedern erreicht hat
+ *
+ * @param int $group_id ID der Gruppe
+ * @return bool true, wenn die Gruppe die maximale Anzahl an Mitgliedern erreicht hat, sonst false
+ */
+ private function check_group_limit($group_id) {
+ $members = get_post_meta($group_id, '_group_members', true);
+ $max_members = apply_filters('group_builder_max_members', 10); // Standardmäßig 10, kann mit einem Filter angepasst werden
+ return count($members) < $max_members;
+ }
+
+ /**
+ * Bereinigt verwaiste Daten
+ */
+ public function cleanup_orphaned_data() {
+
+ /**
+ * Löscht _interested_users in den Metadaten der pinwall_post Beiträge, für die es keine existierenden Nutzer gibt
+ */
+ $args = array(
+ 'post_type' => 'pinwall_post',
+ 'meta_query' => array(
+ array(
+ 'key' => '_interested_users',
+ 'compare' => 'EXISTS',
+ ),
+ ),
+ );
+ $query = new WP_Query($args);
+
+ if ($query->have_posts()) {
+ while ($query->have_posts()) {
+ $query->the_post();
+ $post_id = get_the_ID();
+ $interested_users = get_post_meta($post_id, '_interested_users', true);
+ if (empty($interested_users)) {
+ delete_post_meta($post_id, '_interested_users');
+ }
+ }
+ }
+
+ /**
+ * Überprüft ob, die Metadaten für assozierten Gruppen (_associated_group) in den pinwall_post Beiträge
+ * und löscht die Metadaten, wenn die Gruppe nicht mehr existiert
+ */
+ $args = array(
+ 'post_type' => 'pinwall_post',
+ 'meta_query' => array(
+ array(
+ 'key' => '_associated_group',
+ 'compare' => 'EXISTS',
+ ),
+ ),
+ );
+ $query = new WP_Query($args);
+
+ if ($query->have_posts()) {
+ while ($query->have_posts()) {
+ $query->the_post();
+ $post_id = get_the_ID();
+ $group_id = get_post_meta($post_id, '_associated_group', true);
+ if (!get_post($group_id)) {
+ delete_post_meta($post_id, '_associated_group');
+ }
+ }
+ }
+
+ wp_reset_postdata();
+ }
+ /**
+ * Shortcode für das bearbeitungsformular der Group_Post
+ */
+ public function group_edit_form_shortcode($atts) {
+ // Überprüfen Sie, ob der Benutzer berechtigt ist, die Gruppe zu bearbeiten
+ $group_id = get_the_ID();
+ $current_user_id = get_current_user_id();
+ $group_members = $this->get_group_members($group_id);
+
+ if (!in_array($current_user_id, $group_members)) {
+ return 'Sie sind nicht berechtigt, diese Gruppe zu bearbeiten.';
+ }
+
+ // Rendern Sie das ACF-Formular
+ ob_start();
+ acfe_form('edit_group');
+ return ob_get_clean();
+ }
+
+ /**
+ * AJAX-Funktion zum Bearbeiten eines Gruppenkommentars
+ */
+ public function restrict_group_comments($query) {
+ if (!is_admin() && $query->is_comment_feed) {
+ $post_id = $query->query_vars['post_id'];
+ $post_type = get_post_type($post_id);
+
+ if ($post_type === 'group_post') {
+ $current_user_id = get_current_user_id();
+ $group_members = $this->get_group_members($post_id);
+
+ if (!in_array($current_user_id, $group_members)) {
+ $query->set('post__in', array(0)); // Keine Kommentare anzeigen
+ }
+ }
+ }
+ }
+ public function customize_comments_template($comment_template) {
+ if (get_post_type() === 'group_post') {
+ global $post;
+ $current_user_id = get_current_user_id();
+ $group_members = $this->get_group_members($post->ID);
+ if (!in_array($current_user_id, $group_members)) {
+ $comment_template = 'Nur Mitglieder dieser Gruppe können Kommentare sehen.
';
+ }
+ }
+ return $comment_template;
+ }
+
+ /**
+ * Passt das Kommentarformular an
+ */
+ public function customize_comment_form($defaults) {
+ global $post;
+ $defaults['title_reply_before'] = 'Kommentare erwünscht. ';
+ $defaults['title_reply']='';
+ $defaults['logged_in_as'] = '';
+
+ if (get_post_type($post) === 'group_post') {
+ $current_user_id = get_current_user_id();
+ $group_members = $this->get_group_members($post->ID);
+ $defaults['label_submit'] = 'Beitrag abschicken';
+ $defaults['logged_in_as'] = '';
+ $defaults['title_reply'] = 'Beitrag schreiben
';
+ $defaults['comment_field'] = str_replace('Kommentar','Beitrag',$defaults['comment_field']);
+ if (!in_array($current_user_id, $group_members)) {
+ $defaults['title_reply_before'] = 'Nur Mitglieder dieser Gruppe können hier Beiträge hinterlassen.
';
+ $defaults['title_reply'] = ' -- ';
+ $defaults['logged_in_as'] = '';
+ $defaults['comment_field'] = '';
+ $defaults['submit_button'] = '';
+ }
+ }
+
+ return $defaults;
+ }
+
+ private function get_icon($name) {
+ return '';
}
+
+
+ /**
+ * Zeigt das Modal-Fenster für die Gruppenbearbeitung an
+ * Hinweis: Wir nutzen die Klassen-Definitionen von meinem custom_wp_adminbar Plugin
+ */
+ public function display_modal_frame() {
+ if (is_singular('group_post') && group_builder_user_can(get_the_ID(), 'edit')) {
+ ?>
+
+
+
+ ×
+
Gruppe konfigurieren
+ invite_link_copy_button(); ?>
+
+
+
+
+
+
+
+
+ ×
+
Pinwand Karte bearbeiten
+
+
+
+ get_invite_link();
+ }else{
+ $new_status_text = 'Beitritt zur Gruppe freigeben: Jeder kann beitreten';
+ $new_status = 'unlock';
+ $status = 'lock';
+ $link = '';
+ }
+ update_post_meta($group_id, '_join_option', $new_join_option);
+ wp_send_json_success(array(
+ 'new_status' => $new_status,
+ 'new_status_text' => $new_status_text,
+ 'status_icon' => $this->get_icon($status),
+ 'link' => $link
+
+ ));
+ }
+
+ /**
+ * AJAX-Funktion zur Rückgabe des Einladungslinks
+ */
+ public function ajax_generate_invite_link() {
+ $invite_url = $this->get_invite_link();
+ wp_send_json_success(array('invite_link' =>$invite_url));
+ }
+
+ /**
+ * Gibt den Einladungslink zur Gruppe zurück
+ * @return string|null //url to the invite link
+ */
+ public function get_invite_link($group_id = null)
+ {
+ if(!$group_id){
+ $group_id = get_the_ID();
+ }
+ if(!$group_id){
+ return 'Fehler: Gruppen-ID nicht gefunden';
+ }
+
+ $hash = get_post_meta($group_id, '_invite_hash', true);
+ // speichere neuen Hash für Einladungslink, wenn noch keiner existiert
+ if (empty($hash)) {
+ $hash = md5(uniqid(rand(), true));
+ update_post_meta($group_id, '_invite_hash', $hash);
+ }
+
+ return get_permalink($group_id) . '?invite=' . $hash;
+ }
+
+
+ /**
+ * Gibt den HTML-Code für den Einladungslink zurück
+ * @return string
+ */
+ public function invite_link_copy_button(){
+ if(!is_singular('group_post')){
+ return;
+ }
+ if(!is_user_logged_in()){
+ return;
+ }
+ $group_id = get_the_ID();
+ $join_option = get_post_meta($group_id, '_join_option', true);
+
+ if($join_option){
+ $link = $this->get_invite_link($group_id);
+ echo '';
+ echo 'Weitere Mitglieder einladen: Einladungslink kopieren
';
+ echo ' ';
+ echo '
';
+ }
+
+ echo $this->leave_button($group_id);
+ }
+ private function leave_button($group_id){
+ return 'Deine Mitarbeit in der Gruppe beenden: Gruppe verlassen
';
+ }
+ public function get_invite_link_html($group_id = null){
+ if(!$group_id){
+ $group_id = get_the_ID();
+ }
+ $status = get_post_meta($group_id, '_join_option', true);
+ if($status === 'invite_only') {
+ $status_text = 'Jeder kann der Gruppe beitreten. Klicke auf das Schloss, um den Beitritt zur Gruppe zu sperren';
+ $status_icon = $this->get_icon('unlock');
+ $link = '';
+ $html = '
+ ' . $status_icon . '
+
+ ';
+ }else{
+ $status_text = 'Der Beitritt zur Gruppe ist gesperrt. Nur Mitglieder mit Einladungslink können beitreten. Klicke auf das Schloss, um den Beitritt zur Gruppe freizugeben';
+ $status_icon = $this->get_icon('lock');
+ $link = $this->get_invite_link();
+ $html = '
+ ' . $status_icon . '
+ Einladungslink kopieren
+
+ ';
+ }
+ return $html;
+
+ }
+
+ /**
+ * Überprüft, ob der Benutzer über einen Einladungslink beigetreten ist
+ */
+ public function check_invite() {
+ if (isset($_GET['invite'])) {
+ $group_id = get_the_ID();
+ $hash = $_GET['invite'];
+ if ($this->check_invite_hash($group_id, $hash)) {
+ $current_user_id = get_current_user_id();
+ $members = get_post_meta($group_id, '_group_members', true);
+ if (!is_array($members)) {
+ $members = array();
+ }
+ if (!in_array($current_user_id, $members)) {
+ $members[] = $current_user_id;
+ update_post_meta($group_id, '_group_members', $members);
+ $this->update_change_timestamp($group_id);
+ }
+ //redirect to the group page
+ wp_redirect(get_permalink($group_id));
+ }
+ }
+
+ }
+
+
+
+ // Überprüfe den Einladungslink
+ private function check_invite_hash($group_id, $hash) {
+ $invite_hash = get_post_meta($group_id, '_invite_hash', true);
+ return $invite_hash === $hash;
+ }
+
+ // Implementierung der Integration mit Ultimate Member
+
+ /**
+ * Post_types für Ultimate Member hinzufügen
+ */
+ public function ultimate_member_integration_profile_query_make_posts($args) {
+ $args['post_type'] = 'pinwall_post';
+ return $args;
+ }
+
+ /**
+ * Fügt den Gruppen-Tab zu Ultimate Member hinzu
+ */
+ function ultimate_member_integration_tab( $tabs ) {
+
+ $tabs['group-builder'] = array(
+ 'name' => 'Gruppen',
+ 'icon' => 'um-icon-android-people',
+ 'custom' => true,
+ );
+ $custom_tab = UM()->options()->get( 'profile_tab_' . 'group-builder' );
+ if ( '' === $custom_tab ) {
+ UM()->options()->update( 'profile_tab_' . 'group-builder', true );
+ }
+
+ return $tabs;
+
+ }
+
+ /**
+ * Gibt die Liste von Group_Posts zurück, bei denen der User Mitglied ist
+ */
+ public function ultimate_member_integration_content()
+ {
+ $current_user_id = get_current_user_id();
+ $args = array(
+ 'post_type' => 'group_post',
+ 'meta_query' => array(
+ array(
+ 'key' => '_group_members',
+ 'value' => $current_user_id,
+ 'compare' => 'LIKE'
+ )
+ )
+ );
+ $groups = get_posts($args);
+ echo 'Mitglied in folgenden Gruppen ';
+ echo '';
+ foreach ($groups as $group) {
+ // @todo: Hier können weitere infos zu den Gruppen-Beiträge angezeigt werden
+ echo '' . $group->post_title . ' ';
+ }
+ echo ' ';
+ }
+
}
-// Initialisierung des Plugins
-function group_builder_init() {
- GroupBuilder::get_instance();
+function group_builder_user_can($group_id, $action = 'edit') {
+ $current_user_id = get_current_user_id();
+ $group_members = get_post_meta($group_id, '_group_members', true);
+
+ if ($action === 'join') {
+
+ if (is_array($group_members) && in_array($current_user_id, $group_members)) {
+ return false;
+ }
+ $join_option = get_post_meta($group_id, '_join_option', true);
+ $hash = get_post_meta($group_id, '_invite_hash', true);
+ return !$join_option || (isset( $_GET['invite']) && $hash === $_GET['invite']);
+ }
+
+ if (!is_array($group_members)) {
+ return false;
+ }
+
+ if ($action === 'edit' || $action === 'invite') {
+ return in_array($current_user_id, $group_members);
+ }
+
+
+
+ return false;
}
-add_action('plugins_loaded', 'group_builder_init');
+// Initialisierung des Plugins
+add_action('plugins_loaded', ['GroupBuilder', 'get_instance']);
diff --git a/images/gruppe.png b/images/gruppe.png
new file mode 100644
index 0000000..e6a72ab
Binary files /dev/null and b/images/gruppe.png differ
diff --git a/images/markt.png b/images/markt.png
new file mode 100644
index 0000000..f1eb5b0
Binary files /dev/null and b/images/markt.png differ
diff --git a/images/netzwerk.png b/images/netzwerk.png
new file mode 100644
index 0000000..3b9c54a
Binary files /dev/null and b/images/netzwerk.png differ
diff --git a/images/pinnwand.png b/images/pinnwand.png
new file mode 100644
index 0000000..230da0f
Binary files /dev/null and b/images/pinnwand.png differ
diff --git a/js/group-builder.js b/js/group-builder.js
new file mode 100644
index 0000000..51de96e
--- /dev/null
+++ b/js/group-builder.js
@@ -0,0 +1,241 @@
+jQuery(document).ready(function($) {
+ const avatarLists = {};
+
+ function getPostIdFromElement($element) {
+ let postId = $element.data('post-id');
+ if (!postId) {
+ const $childWithPostId = $element.find('[data-post-id]').first();
+ if ($childWithPostId.length) {
+ postId = $childWithPostId.data('post-id');
+ } else {
+ const $parentWithPostId = $element.closest('[data-post-id]');
+ if ($parentWithPostId.length) {
+ postId = $parentWithPostId.data('post-id');
+ }
+ }
+ }
+ return postId;
+ }
+
+ function initializeAvatarList($element) {
+ const postId = getPostIdFromElement($element);
+ if (!postId) {
+ console.error('Konnte keine gültige postId für das Element finden:', $element);
+ return;
+ }
+ if (!avatarLists[postId]) {
+ avatarLists[postId] = {
+ timestamp: 0
+ };
+ loadAvatarList(postId);
+ }
+ }
+
+ function loadAvatarList(postId) {
+ $.ajax({
+ url: group_builder_ajax.ajax_url,
+ type: 'POST',
+ data: {
+ action: 'get_avatar_list',
+ post_id: postId,
+ timestamp: avatarLists[postId].timestamp
+ },
+ success: function(response) {
+ if (response.success) {
+ if (response.data.updated) {
+ $('.attendees[data-post-id="' + postId + '"]').html(response.data.avatar_list);
+ avatarLists[postId].timestamp = response.data.timestamp;
+ }
+ console.log('Avatar-Liste aktualisiert für Post-ID:', postId, 'Neuer Timestamp:', avatarLists[postId].timestamp);
+ } else {
+ console.error('Fehler beim Laden der Avatar-Liste:', response.data ? response.data.message : 'Unbekannter Fehler');
+ }
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ console.error('AJAX-Fehler beim Laden der Avatar-Liste:', textStatus, errorThrown);
+ }
+ });
+ }
+
+ // Initialisiere alle vorhandenen Avatar-Listen
+ $('.attendees').each(function() {
+ initializeAvatarList($(this));
+ });
+
+ // Heartbeat-Sender
+ $(document).on('heartbeat-send', function(e, data) {
+ data.group_builder_request = Object.keys(avatarLists).map(postId => ({
+ post_id: postId,
+ timestamp: avatarLists[postId].timestamp
+ }));
+ console.log('Heartbeat-Anfrage gesendet:', data.group_builder_request);
+ });
+
+ // Heartbeat-Empfänger
+ $(document).on('heartbeat-tick', function(e, data) {
+ if (data.group_builder_response) {
+ data.group_builder_response.forEach(function(item) {
+ if (item.updated) {
+ $('.attendees[data-post-id="' + item.post_id + '"]').html(item.avatar_list);
+ avatarLists[item.post_id].timestamp = item.timestamp;
+ console.log('Avatar-Liste aktualisiert für Post-ID:', item.post_id, 'Neuer Timestamp:', item.timestamp);
+ }
+ });
+ }
+ });
+
+ // Event-Handler für die Buttons
+ $(document).on('click', '.show-interest, .withdraw-interest, .create-group, .join-group, .leave-group', function(e) {
+ e.preventDefault();
+ const $button = $(this);
+ const postId = getPostIdFromElement($button);
+ if (!postId) {
+ console.error('Konnte keine gültige postId für den Button finden:', $button);
+ return;
+ }
+ const action = $button.attr('class').split(' ')[0].replace('-', '_');
+ const data = {
+ action: action,
+ post_id: postId
+ };
+ if (action === 'join_group' || action === 'leave_group') {
+ data.group_id = $button.data('group-id');
+ }
+
+ $.ajax({
+ url: group_builder_ajax.ajax_url,
+ type: 'POST',
+ data: data,
+ success: function(response) {
+ if (response.success) {
+ console.log('Aktion erfolgreich:', action, 'für Post ID:', postId);
+ //loadAvatarList(postId); // Lade die Liste sofort neu
+ location.reload();
+ } else {
+ console.error('Fehler bei der Aktion:', action, 'für Post ID:', postId, response.data.message);
+ }
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ console.error('AJAX-Fehler bei der Aktion:', action, 'für Post ID:', postId, textStatus, errorThrown);
+ }
+ });
+ });
+
+ // Weitere Event-Handler und Funktionen...
+// Frontend-Formular Modal
+ // für die Bearbeitung von Gruppen und Pinnwandeinträge
+ $(document).on('click', '.edit-group', function(e) {
+ e.preventDefault();
+ const groupId = $(this).data('group-id');
+ openModal('#group-edit-modal');
+ });
+
+ // Beitrittsoption umschalten
+ $(document).on('click', '.toggle-join-option', function(e) {
+ e.preventDefault();
+ const groupId = $(this).data('group-id');
+ const toggle = $(this);
+ console.info(groupId,'toggle-join-option');
+ $.ajax({
+ url: group_builder_ajax.ajax_url,
+ type: 'POST',
+ data: {
+ action: 'toggle_join_option',
+ group_id: groupId
+ },
+ success: function(response) {
+ console.log(response);
+ if (response.success) {
+ // Aktualisiere UI
+ toggle.text(response.data.new_status);
+ } else {
+ console.error('Fehler beim Umschalten der Beitrittsoption:', response.data.message);
+ }
+ }
+ });
+ });
+
+ /**
+ * Funktion zum Kopieren des Einladungstextes in die Zwischenablage
+ * @param {string} element_id ID des Textfeldes, dessen Inhalt kopiert werden soll
+ */
+ function copy_to_clipboard(element_id) {
+ // Das Textfeld auswählen
+ var textfeld = document.getElementById(element_id);
+
+ // Den Inhalt des Textfeldes auswählen
+ textfeld.select();
+ textfeld.setSelectionRange(0, 99999); // Für mobile Geräte
+
+ // Den Text in die Zwischenablage kopieren
+ navigator.clipboard.writeText(textfeld.value)
+ .then(() => {
+ alert("Einladungslink wurde in die Zwischenablage kopiert!");
+ })
+ .catch(err => {
+ console.error('Fehler beim Kopieren: ', err);
+ });
+ }
+ // Einladungslink kopieren
+ $(document).on('click', '.copy-invite-link', function(e) {
+ e.preventDefault();
+ copy_to_clipboard('invite-link');
+ });
+
+ // Einladungslink generieren
+ $(document).on('click', '.generate-invite-link', function(e) {
+ e.preventDefault();
+ const groupId = $(this).data('group-id');
+
+ $.ajax({
+ url: group_builder_ajax.ajax_url,
+ type: 'POST',
+ data: {
+ action: 'generate_invite_link',
+ group_id: groupId
+ },
+ success: function(response) {
+ if (response.success) {
+ // Zeige den generierten Link in einem Modal an
+ $('#invite-link-modal .modal-content').html(`
+ Hier ist der Einladungslink für diese Gruppe:
+
+ Link kopieren
+ `);
+ openModal('#invite-link-modal');
+ } else {
+ console.error('Fehler beim Generieren des Einladungslinks:', response.data.message);
+ }
+ }
+ });
+ });
+
+ $('.ct-comments-title').html('Beiträge');
+
+ // Todo: Image Pfade für die Menüpunkte anpassen aus dem Pluginpfad ./images/ holen
+ jQuery("a.ct-menu-link:contains('Startseite')")
+ .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/markt.png')")
+ .css('background-size','50px')
+ .css('background-repeat', 'no-repeat')
+ .css('background-position', 'center center')
+ .css('padding-top','70px');
+ jQuery("a.ct-menu-link:contains('Pinwand')")
+ .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/pinnwand.png')")
+ .css('background-size','50px')
+ .css('background-repeat', 'no-repeat')
+ .css('background-position', 'center center')
+ .css('padding-top','70px');
+ jQuery("a.ct-menu-link:contains('Gruppen')")
+ .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/gruppe.png')")
+ .css('background-size','50px')
+ .css('background-repeat', 'no-repeat')
+ .css('background-position', 'center center')
+ .css('padding-top','70px');
+ jQuery("a.ct-menu-link:contains('Mitglieder')")
+ .css('background-image',"url('https://lernende-community.local/wp-content/uploads/2024/08/netzwerk.png')")
+ .css('background-size','50px')
+ .css('background-repeat', 'no-repeat')
+ .css('background-position', 'center center')
+ .css('padding-top','70px');
+
+});
Diskurs und Ergebnisse:
+ +