diff --git a/ansico-some-plugin-v1.0.0.16.zip b/ansico-some-plugin-v1.0.0.16.zip deleted file mode 100644 index dcc736c..0000000 Binary files a/ansico-some-plugin-v1.0.0.16.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.0.0.26.zip b/ansico-some-plugin-v1.0.0.26.zip deleted file mode 100644 index 54a872a..0000000 Binary files a/ansico-some-plugin-v1.0.0.26.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.0.0.27.zip b/ansico-some-plugin-v1.0.0.27.zip deleted file mode 100644 index 07f82b3..0000000 Binary files a/ansico-some-plugin-v1.0.0.27.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.1.0.19.zip b/ansico-some-plugin-v1.1.0.19.zip deleted file mode 100644 index a26247c..0000000 Binary files a/ansico-some-plugin-v1.1.0.19.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.1.0.2 (1).zip b/ansico-some-plugin-v1.1.0.2 (1).zip deleted file mode 100644 index 53e209e..0000000 Binary files a/ansico-some-plugin-v1.1.0.2 (1).zip and /dev/null differ diff --git a/ansico-some-plugin-v1.1.0.zip b/ansico-some-plugin-v1.1.0.zip deleted file mode 100644 index 9fbca22..0000000 Binary files a/ansico-some-plugin-v1.1.0.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.6.1.zip b/ansico-some-plugin-v1.6.1.zip deleted file mode 100644 index 657194b..0000000 Binary files a/ansico-some-plugin-v1.6.1.zip and /dev/null differ diff --git a/ansico-some-plugin-v1.6.42.zip b/ansico-some-plugin-v1.6.42.zip deleted file mode 100644 index 3af7482..0000000 Binary files a/ansico-some-plugin-v1.6.42.zip and /dev/null differ diff --git a/ansico-some-plugin.zip b/ansico-some-plugin.zip deleted file mode 100644 index e86c9a4..0000000 Binary files a/ansico-some-plugin.zip and /dev/null differ diff --git a/ansico-some-plugin/admin-script.js b/ansico-some-plugin/admin-script.js index 01b7814..2669b7d 100644 --- a/ansico-some-plugin/admin-script.js +++ b/ansico-some-plugin/admin-script.js @@ -1,19 +1,600 @@ jQuery(document).ready(function($){ - var mediaUploader; - $('#ansico-upload-button').click(function(e) { - e.preventDefault(); - if (mediaUploader) { mediaUploader.open(); return; } - mediaUploader = wp.media({ title: 'Choose Avatar', button: { text: 'Set as Profile Picture' }, multiple: false }); - mediaUploader.on('select', function() { - var attachment = mediaUploader.state().get('selection').first().toJSON(); - $('#ansico-avatar-url').val(attachment.url); - $('#ansico-avatar-preview').attr('src', attachment.url).show(); + var frame; + + function openAvatarFrame(e){ + if (e) { + e.preventDefault(); + } + if(frame){ frame.open(); return; } + frame = wp.media({ title: 'Profilbillede', button: { text: 'Brug' }, multiple: false }); + frame.on('select', function(){ + var att = frame.state().get('selection').first().toJSON(); + $('#ansico-avatar-url').val(att.url); + $('#ansico-avatar-preview').attr('src', att.url).show(); + $('.ansico-avatar-trigger').addClass('has-image'); + $('.ansico-avatar-trigger .ansico-avatar-placeholder').remove(); }); - mediaUploader.open(); - }); - $('#ansico-remove-button').click(function(e){ + frame.open(); + } + + $('#ansico-upload-button').on('click', openAvatarFrame); + + $('#ansico-remove-button').on('click', function(e){ e.preventDefault(); $('#ansico-avatar-url').val(''); $('#ansico-avatar-preview').hide().attr('src', ''); + $('.ansico-avatar-trigger').removeClass('has-image'); + if (!$('.ansico-avatar-trigger .ansico-avatar-placeholder').length) { + $('.ansico-avatar-trigger').append('Upload'); + } }); -}); \ No newline at end of file + + function normalizeText(text) { + return $.trim(String(text || '').replace(/\s+/g, ' ')).toLowerCase(); + } + + function textMatches(text, patterns) { + var normalized = normalizeText(text); + for (var i = 0; i < patterns.length; i++) { + if (normalized.indexOf(patterns[i]) !== -1) { + return true; + } + } + return false; + } + + function enhanceAvatarUi() { + var $preview = $('#ansico-avatar-preview'); + var $upload = $('#ansico-upload-button'); + var $remove = $('#ansico-remove-button'); + if (!$preview.length || !$upload.length) { + return; + } + + var $cell = $preview.closest('td'); + $cell.addClass('ansico-avatar-cell'); + $upload.addClass('ansico-avatar-hidden-button'); + + if (!$cell.find('.ansico-avatar-trigger').length) { + var $trigger = $(''); + $preview.before($trigger); + $trigger.append($preview); + if (!$preview.attr('src')) { + $preview.hide(); + $trigger.append('Upload'); + } else { + $trigger.addClass('has-image'); + } + } + + $cell.on('click', '.ansico-avatar-trigger', openAvatarFrame); + $remove.addClass('ansico-avatar-remove-button'); + } + + enhanceAvatarUi(); + + if ( ! window.ansicoAdminSettings || ! window.ansicoAdminSettings.cleanUpProfileSettings ) { + return; + } + + var $form = $('#your-profile'); + if ( ! $form.length ) { + return; + } + + var labels = window.ansicoAdminSettings.labels || {}; + var initialSerializedState = ''; + var panelLabels = { + profile: labels.profile || 'Profile', + federation: labels.federation || 'Federation', + other: labels.otherSettings || 'Other settings' + }; + + var profileHeadingPatterns = ['name', 'navn', 'contact info', 'kontaktinformation', 'account management', 'kontohåndtering', 'social profiles', 'profilbillede', 'ansico avatar']; + var federationHeadingPatterns = ['activitypub', 'moderation', 'moderering', 'federation', 'føderation']; + var otherHeadingPatterns = ['application passwords', 'applikationsadgangskoder']; + + function bucketForHeading(text) { + if ( textMatches(text, otherHeadingPatterns) ) { + return 'other'; + } + if ( textMatches(text, profileHeadingPatterns) ) { + return 'profile'; + } + if ( textMatches(text, federationHeadingPatterns) ) { + return 'federation'; + } + return 'other'; + } + + function getSectionNodes($heading) { + var $nodes = $heading; + var $next = $heading.next(); + while ( $next.length && ! $next.is('h2, h3') ) { + $nodes = $nodes.add($next); + $next = $next.next(); + } + return $nodes; + } + + function createSectionBucket($nodes) { + return { + headingText: $nodes.first().text() || '', + nodes: $nodes + }; + } + + function collectSections($container) { + var results = []; + $container.children('h2, h3').each(function(){ + results.push(createSectionBucket(getSectionNodes($(this)))); + }); + return results; + } + + function extractSectionByMatcher(sections, matcherFn) { + var extracted = []; + for (var i = sections.length - 1; i >= 0; i--) { + if (matcherFn(sections[i])) { + extracted.unshift(sections.splice(i, 1)[0]); + } + } + return extracted; + } + + function appendSections($panel, sections) { + $.each(sections, function(_, section){ + $panel.append(section.nodes); + }); + } + + // Rename heading in-place for the Ansico avatar section. + $form.find('h2, h3').each(function(){ + var $heading = $(this); + if ( normalizeText($heading.text()) === 'ansico avatar' ) { + $heading.text('Profilbillede'); + } + }); + + // Separate biography into its own section. + var $bioRow = $(); + $form.find('tr').each(function(){ + var headingText = normalizeText($(this).find('th').first().text()); + if ( headingText.indexOf('biographical info') !== -1 || headingText.indexOf('biografisk info') !== -1 ) { + $bioRow = $(this); + return false; + } + }); + + var $bioSection = $(); + if ( $bioRow.length ) { + var bioTitle = $.trim($bioRow.find('th').first().text()) || 'Biografisk info'; + $bioSection = $('
'); + $bioSection.append($('

').text(bioTitle)); + var $bioTable = $(''); + $bioTable.append($bioRow); + $bioSection.append($bioTable); + + var $sourceTable = $bioRow.closest('table'); + if ( $sourceTable.find('tr').length === 0 ) { + var $prevHeading = $sourceTable.prevAll('h2, h3').first(); + $sourceTable.remove(); + if ( $prevHeading.length ) { + $prevHeading.remove(); + } + } + } + + var $submits = $form.find('p.submit, .submit').filter(function(){ return $(this).find(':submit').length || $(this).is('p.submit'); }).detach(); + var sections = collectSections($form); + + if ( ! sections.length && ! $bioSection.length ) { + if ( $submits.length ) { + $form.append($submits); + } + return; + } + + var $tabsNav = $('
'); + var $panelsWrap = $('
'); + var panels = { + profile: $('
'), + federation: $('
'), + other: $('
') + }; + + $.each(panelLabels, function(key, label){ + var target = 'ansico-profile-tab-' + (key === 'other' ? 'other' : key); + var $button = $(''); + $button.text(label).attr('data-panel', target); + $tabsNav.append($button); + }); + + var profileSections = extractSectionByMatcher(sections, function(section){ + return bucketForHeading(section.headingText) === 'profile'; + }); + var federationSections = extractSectionByMatcher(sections, function(section){ + return bucketForHeading(section.headingText) === 'federation'; + }); + var otherSections = sections; + + // Pull sections with ActivityPub-ish field names into Federation even if heading text is unexpected. + var fallbackFromProfile = extractSectionByMatcher(profileSections, function(section){ + return section.nodes.find('[name*="activitypub"], [id*="activitypub"], [class*="activitypub"], [name*="moderation"], [id*="moderation"], [class*="moderation"]').length > 0 || textMatches(section.headingText, federationHeadingPatterns); + }); + federationSections = federationSections.concat(fallbackFromProfile); + + var socialFromOther = extractSectionByMatcher(otherSections, function(section){ + return textMatches(section.headingText, ['social profiles']) || section.nodes.find('[name^="ansico_social_"], [id^="ansico_social_"]').length > 0; + }); + profileSections = profileSections.concat(socialFromOther); + + var applicationPasswordSections = extractSectionByMatcher(profileSections, function(section){ + return textMatches(section.headingText, otherHeadingPatterns) || section.nodes.find('[name*="application_password"], [id*="application-password"], .application-passwords').length > 0; + }); + otherSections = applicationPasswordSections.concat(otherSections); + + function findAndExtractRows($sectionNodes, patterns) { + var rows = $(); + $sectionNodes.filter('table').add($sectionNodes.find('table')).each(function(){ + $(this).find('tr').each(function(){ + var rowLabel = normalizeText($(this).find('th').first().text()); + if ( textMatches(rowLabel, patterns) ) { + rows = rows.add($(this)); + } + }); + }); + return rows; + } + + function buildSingleTableSection(title, $rows) { + if ( !$rows.length ) { + return null; + } + var $wrap = $('
'); + $wrap.append($('

').text(title)); + var $table = $(''); + $table.append($rows); + $wrap.append($table); + return createSectionBucket($wrap); + } + + function findAllRows($sectionNodes) { + var rows = $(); + $sectionNodes.filter('table').add($sectionNodes.find('table')).each(function(){ + rows = rows.add($(this).find('tr')); + }); + return rows; + } + + function pruneEmptySectionList(sectionList) { + return $.grep(sectionList, function(section){ + var $tables = section.nodes.filter('table').add(section.nodes.find('table')); + if ( ! $tables.length ) { + return true; + } + return $tables.find('tr').length > 0; + }); + } + + // Reorder profile sections into a more social-profile-like flow. + var orderedProfile = []; + var avatarSections = extractSectionByMatcher(profileSections, function(section){ return textMatches(section.headingText, ['profilbillede', 'ansico avatar']); }); + var nameSections = extractSectionByMatcher(profileSections, function(section){ return textMatches(section.headingText, ['name', 'navn']); }); + var contactSections = extractSectionByMatcher(profileSections, function(section){ return textMatches(section.headingText, ['contact info', 'kontaktinformation']); }); + var socialSections = extractSectionByMatcher(profileSections, function(section){ return textMatches(section.headingText, ['social profiles']); }); + var accountSections = extractSectionByMatcher(profileSections, function(section){ return textMatches(section.headingText, ['account management', 'kontohåndtering']); }); + + var socialRows = $(); + $.each(socialSections, function(_, section){ + socialRows = socialRows.add(findAllRows(section.nodes)); + }); + + var websiteRows = $(); + $.each(contactSections, function(_, section){ + var $rows = findAndExtractRows(section.nodes, ['website', 'websted', 'site url']); + if ( $rows.length ) { + websiteRows = websiteRows.add($rows); + } + }); + + if ( contactSections.length ) { + var $contactTable = contactSections[0].nodes.filter('table').add(contactSections[0].nodes.find('table')).first(); + if ( !$contactTable.length ) { + $contactTable = $(''); + contactSections[0].nodes = contactSections[0].nodes.add($contactTable); + } + if ( socialRows.length ) { + $contactTable.append('Social profiles'); + $contactTable.append(socialRows); + } + if ( websiteRows.length ) { + $contactTable.append('Website'); + $contactTable.append(websiteRows); + } + } else if ( socialRows.length || websiteRows.length ) { + var $contactWrap = $('
'); + $contactWrap.append($('

').text('Kontaktinformationer')); + var $contactTableOnly = $(''); + if ( socialRows.length ) { + $contactTableOnly.append('Social profiles'); + $contactTableOnly.append(socialRows); + } + if ( websiteRows.length ) { + $contactTableOnly.append('Website'); + $contactTableOnly.append(websiteRows); + } + $contactWrap.append($contactTableOnly); + contactSections.push(createSectionBucket($contactWrap)); + } + + // Move ActivityPub header image into the profile hero card instead of Federation. + var headerRows = $(); + $.each(federationSections, function(_, section){ + section.nodes.filter('table').add(section.nodes.find('table')).each(function(){ + $(this).find('tr').each(function(){ + var $row = $(this); + var rowLabel = normalizeText($row.find('th').first().text()); + var hasHeaderFields = $row.find('[name*="header"], [id*="header"], [class*="header"], [name*="banner"], [id*="banner"], [class*="banner"]').length > 0; + if ( textMatches(rowLabel, ['header image', 'headerbillede', 'cover image', 'banner image']) || hasHeaderFields ) { + headerRows = headerRows.add($row); + } + }); + }); + }); + + profileSections = pruneEmptySectionList(profileSections); + federationSections = pruneEmptySectionList(federationSections); + + orderedProfile = orderedProfile.concat(avatarSections, nameSections, contactSections); + if ( $bioSection.length ) { + orderedProfile.push(createSectionBucket($bioSection)); + $bioSection = $(); + } + orderedProfile = orderedProfile.concat(accountSections, profileSections); + + appendSections(panels.profile, orderedProfile); + appendSections(panels.federation, federationSections); + appendSections(panels.other, otherSections); + + // If any ActivityPub/Moderation heading still ended up elsewhere, move it explicitly. + function moveMatchingHeadings($panel, patterns, $targetPanel) { + $panel.children('h2, h3').each(function(){ + var $heading = $(this); + if ( textMatches($heading.text(), patterns) ) { + $targetPanel.append(getSectionNodes($heading)); + } + }); + } + moveMatchingHeadings(panels.profile, federationHeadingPatterns, panels.federation); + moveMatchingHeadings(panels.other, federationHeadingPatterns, panels.federation); + moveMatchingHeadings(panels.profile, otherHeadingPatterns, panels.other); + moveMatchingHeadings(panels.federation, otherHeadingPatterns, panels.other); + moveMatchingHeadings(panels.other, ['social profiles'], panels.profile); + + // Decorate section cards. + panels.profile.children('h2, h3').each(function(){ + var $heading = $(this); + var $section = $('
'); + var $nodes = getSectionNodes($heading); + $nodes.wrapAll($section); + }); + panels.federation.children('h2, h3').each(function(){ + var $heading = $(this); + var $section = $('
'); + var $nodes = getSectionNodes($heading); + $nodes.wrapAll($section); + }); + panels.other.children('h2, h3').each(function(){ + var $heading = $(this); + var $section = $('
'); + var $nodes = getSectionNodes($heading); + $nodes.wrapAll($section); + }); + + panels.profile.find('.ansico-profile-card').first().addClass('ansico-profile-card-avatar'); + + function compactNameFields() { + panels.profile.find('.ansico-profile-card').each(function(){ + var $card = $(this); + var headingText = $card.children('h2, h3').first().text(); + if ( ! textMatches(headingText, ['name', 'navn']) ) { + return; + } + var $table = $card.find('table.form-table').first(); + if ( ! $table.length ) { + return; + } + var $firstRow = $(); + var $lastRow = $(); + $table.find('tr').each(function(){ + var rowLabel = normalizeText($(this).find('th').first().text()); + if ( !$firstRow.length && textMatches(rowLabel, ['first name', 'fornavn']) ) { + $firstRow = $(this); + } else if ( !$lastRow.length && textMatches(rowLabel, ['last name', 'efternavn']) ) { + $lastRow = $(this); + } + }); + if ( $firstRow.length && $lastRow.length && ! $card.find('.ansico-profile-inline-grid').length ) { + var $grid = $('
'); + $.each([$firstRow, $lastRow], function(_, $row){ + var $field = $('
'); + $field.append($('').html($row.find('th').first().html())); + var $control = $('
'); + $control.append($row.find('td').contents()); + $field.append($control); + $grid.append($field); + $row.remove(); + }); + $table.before($grid); + if ( !$table.find('tr').length ) { + $table.remove(); + } + } + }); + } + + function integrateHeroHeaderRow() { + var $heroCard = panels.profile.find('.ansico-profile-card').filter(function(){ + return textMatches($(this).children('h2, h3').first().text(), ['profilbillede', 'profile picture', 'ansico avatar']); + }).first(); + if ( !$heroCard.length ) { + return; + } + $heroCard.addClass('ansico-profile-hero-card'); + var $heroTable = $heroCard.find('table.form-table').first(); + if ( !$heroTable.length ) { + $heroTable = $(''); + $heroCard.append($heroTable); + } + if ( headerRows.length ) { + var $coverTable = $(''); + headerRows.each(function(){ + $(this).addClass('ansico-profile-cover-row'); + }); + $coverTable.append(headerRows); + $heroCard.find('h2, h3').first().after($coverTable); + $heroCard.addClass('has-cover'); + } + $heroTable.find('tr').each(function(){ + var rowLabel = normalizeText($(this).find('th').first().text()); + if ( textMatches(rowLabel, ['profilbillede', 'profile picture', 'avatar']) ) { + $(this).addClass('ansico-profile-avatar-row'); + } + }); + panels.federation.find('.ansico-profile-card').each(function(){ + if ( ! $(this).find('tr').length ) { + $(this).remove(); + } + }); + } + + function enhanceHeaderImageUi() { + var $coverRow = panels.profile.find('.ansico-profile-cover-row').first(); + if ( !$coverRow.length || $coverRow.hasClass('ansico-cover-ui-ready') ) { + return; + } + $coverRow.addClass('ansico-cover-ui-ready'); + + var $cell = $coverRow.find('td').first(); + if ( !$cell.length ) { + return; + } + + var $buttons = $cell.find('button, .button, input[type="button"], input[type="submit"]'); + var $selectButton = $buttons.filter(function(){ + return !/remove|delete|fjerne|slet/.test(normalizeText($(this).text() || $(this).val())); + }).first(); + var $removeButton = $buttons.filter(function(){ + return /remove|delete|fjerne|slet/.test(normalizeText($(this).text() || $(this).val())); + }).first(); + + var $img = $cell.find('img').first(); + var $trigger = $(''); + if ( $img.length ) { + $trigger.append($img); + $trigger.addClass('has-image'); + } else { + $trigger.append('Choose a header image'); + } + + $cell.prepend($trigger); + if ( $selectButton.length ) { + $selectButton.addClass('ansico-header-hidden-button'); + $trigger.on('click', function(e){ + e.preventDefault(); + $selectButton.trigger('click'); + }); + } + if ( $removeButton.length ) { + $removeButton.addClass('ansico-header-remove-button'); + } + + var $actions = $('
'); + if ( $selectButton.length ) { + $actions.append($selectButton); + } + if ( $removeButton.length ) { + $actions.append($removeButton); + } + if ( $actions.children().length ) { + $cell.append($actions); + } + + var observer = new MutationObserver(function(){ + var $latestImg = $cell.find('img').not($trigger.find('img')).first(); + if ( $latestImg.length ) { + $trigger.empty().append($latestImg).addClass('has-image'); + } else if ( !$trigger.find('img').length ) { + $trigger.removeClass('has-image').html('Choose a header image'); + } + }); + observer.observe($cell.get(0), { childList: true, subtree: true }); + + if ( $removeButton.length ) { + $removeButton.on('click', function(){ + setTimeout(function(){ + if ( !$trigger.find('img').length ) { + $trigger.removeClass('has-image').html('Choose a header image'); + } + }, 50); + }); + } + } + + $panelsWrap.append(panels.profile, panels.federation, panels.other); + + var $firstHeading = $form.children('h2, h3').first(); + if ( $firstHeading.length ) { + $firstHeading.before($tabsNav, $panelsWrap); + } else { + $form.prepend($tabsNav, $panelsWrap); + } + + if ( $submits.length ) { + var $submitWrap = $('
'); + $submitWrap.append($submits); + $form.append($submitWrap); + } + + function activateTab(panelId) { + $tabsNav.find('.ansico-profile-tab-button').each(function(){ + var active = $(this).attr('data-panel') === panelId; + $(this).toggleClass('is-active', active).attr('aria-selected', active ? 'true' : 'false'); + }); + $panelsWrap.find('.ansico-profile-tab-panel').each(function(){ + $(this).toggleClass('is-active', this.id === panelId); + }); + } + + $tabsNav.on('click', '.ansico-profile-tab-button', function(){ + activateTab($(this).attr('data-panel')); + }); + + + function refreshInitialState() { + initialSerializedState = $form.serialize(); + } + + function setupUnsavedChangesGuard() { + $(window).off('beforeunload.edit-profile'); + $(window).off('beforeunload.ansicoProfileCleanup'); + refreshInitialState(); + $(window).on('beforeunload.ansicoProfileCleanup', function(){ + if ( $form.serialize() !== initialSerializedState ) { + return labels.leaveWarning || 'Vil du forlade webstedet? Ændringer, du har foretaget, gemmes muligvis ikke.'; + } + }); + $form.on('submit', function(){ + refreshInitialState(); + $(window).off('beforeunload.ansicoProfileCleanup'); + }); + } + + compactNameFields(); + integrateHeroHeaderRow(); + enhanceHeaderImageUi(); + activateTab('ansico-profile-tab-profile'); + enhanceAvatarUi(); + setupUnsavedChangesGuard(); +}); diff --git a/ansico-some-plugin/ansico-some-plugin.php b/ansico-some-plugin/ansico-some-plugin.php index 9bb33cb..0747a7f 100644 --- a/ansico-some-plugin/ansico-some-plugin.php +++ b/ansico-some-plugin/ansico-some-plugin.php @@ -1,176 +1,1850 @@ ID, 'ansico_avatar_url', true ); - ?> -

Ansico Avatar

- - - - - -
- - - - -

Upload a custom profile picture. This will override Gravatar. If empty, Gravatar or standard logo will be used.

-
- user_id ) ) { $user_id = $id_or_email->user_id; } - elseif ( is_string( $id_or_email ) ) { $user = get_user_by( 'email', $id_or_email ); if ( $user ) { $user_id = $user->ID; } } - - if ( $user_id ) { - $custom_avatar = get_user_meta( $user_id, 'ansico_avatar_url', true ); - if ( ! empty( $custom_avatar ) ) { return $custom_avatar; } - } - return $url; -} - -add_action( 'init', 'ansico_some_register_blocks' ); -function ansico_some_register_blocks() { - wp_register_script( - 'ansico-some-blocks-script', - plugins_url( 'block.js', __FILE__ ), - array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-data', 'wp-components' ), - '1.0.0' - ); - - wp_register_style( - 'ansico-some-blocks-style', - plugins_url( 'style.css', __FILE__ ), - array(), - '1.0.0' - ); - - register_block_type( 'ansico/some-author', array( - 'editor_script' => 'ansico-some-blocks-script', - 'editor_style' => 'ansico-some-blocks-style', - 'style' => 'ansico-some-blocks-style', - 'render_callback' => 'ansico_some_render_author_block' - ) ); - - register_block_type( 'ansico/some-comment', array( - 'editor_script' => 'ansico-some-blocks-script', - 'editor_style' => 'ansico-some-blocks-style', - 'style' => 'ansico-some-blocks-style', - 'render_callback' => 'ansico_some_render_comment_block' - ) ); -} - -function ansico_some_render_author_block( $attributes, $content, $block ) { - $post_id = get_the_ID(); - $author_id = get_post_field( 'post_author', $post_id ) ?: get_current_user_id(); - $name = get_the_author_meta( 'display_name', $author_id ); - $bio = get_the_author_meta( 'description', $author_id ); - $avatar_url = get_avatar_url( $author_id, array( 'size' => 100 ) ); - - ob_start(); - ?> -
'ansico-compact-author' ) ); ?>> -
- Avatar -
-

-
- -
-
-
- 50 ) ); - - $domain = ''; - if ( ! empty( $url ) ) { - $domain = parse_url( $url, PHP_URL_HOST ); - $domain = str_replace( 'www.', '', $domain ); - } - - $time_display = $time; - if ( ! empty( $time ) ) { - $timestamp = strtotime( $time ); - if ( $timestamp ) { - $date_format = get_option( 'date_format' ); - $time_format = get_option( 'time_format' ); - $formatted_time = wp_date( $time_format, $timestamp ); - $formatted_date = wp_date( $date_format, $timestamp ); - $time_display = $formatted_time . ' · ' . $formatted_date; +add_filter( 'block_categories_all', 'ansico_register_block_category', 10, 2 ); +function ansico_register_block_category( $categories, $post ) { + foreach ( $categories as $category ) { + if ( isset( $category['slug'] ) && 'ansico' === $category['slug'] ) { + return $categories; } } - $source_label = __( 'Source:', 'ansico-some-plugin' ); - if ( $source_label === 'Source:' ) { - $locale = get_locale(); - if ( strpos( $locale, 'da' ) === 0 ) { $source_label = 'Kilde:'; } - elseif ( strpos( $locale, 'sv' ) === 0 ) { $source_label = 'Källa:'; } - elseif ( strpos( $locale, 'no' ) === 0 || strpos( $locale, 'nb' ) === 0 || strpos( $locale, 'nn' ) === 0 ) { $source_label = 'Kilde:'; } - elseif ( strpos( $locale, 'de' ) === 0 ) { $source_label = 'Quelle:'; } + array_unshift( + $categories, + array( + 'slug' => 'ansico', + 'title' => __( 'Ansico Blocks', 'ansico-some-plugin' ), + 'icon' => null, + ) + ); + + return $categories; +} + + +function ansico_get_micropost_max_chars() { + $value = get_option( 'ansico_micropost_max_chars', 500 ); + $value = intval( $value ); + return $value > 0 ? $value : 500; +} + +add_action( 'admin_menu', 'ansico_register_settings_page' ); +function ansico_register_settings_page() { + add_options_page( + 'Ansico SoMe Plugin', + 'Ansico SoMe Plugin', + 'manage_options', + 'ansico-some-plugin-settings', + 'ansico_render_settings_page' + ); +} + +add_action( 'admin_init', 'ansico_register_settings' ); +function ansico_register_settings() { + register_setting( + 'ansico_some_plugin_settings', + 'ansico_micropost_max_chars', + array( + 'type' => 'integer', + 'sanitize_callback' => 'ansico_sanitize_micropost_max_chars', + 'default' => 500, + ) + ); + + register_setting( + 'ansico_some_plugin_settings', + 'ansico_clean_up_profile_settings', + array( + 'type' => 'boolean', + 'sanitize_callback' => 'ansico_sanitize_checkbox_setting', + 'default' => false, + ) + ); + + add_settings_section( + 'ansico_some_plugin_main', + __( 'Micropost settings', 'ansico-some-plugin' ), + function() { + echo '

' . esc_html__( 'Settings for Ansico SoMe Plugin.', 'ansico-some-plugin' ) . '

'; + }, + 'ansico-some-plugin-settings' + ); + + add_settings_field( + 'ansico_micropost_max_chars', + __( 'Maximum characters in Micropost Form', 'ansico-some-plugin' ), + 'ansico_render_micropost_max_chars_field', + 'ansico-some-plugin-settings', + 'ansico_some_plugin_main' + ); + + add_settings_field( + 'ansico_clean_up_profile_settings', + __( 'Clean up profile settings', 'ansico-some-plugin' ), + 'ansico_render_clean_up_profile_settings_field', + 'ansico-some-plugin-settings', + 'ansico_some_plugin_main' + ); +} + +function ansico_sanitize_checkbox_setting( $value ) { + return ! empty( $value ) ? '1' : ''; +} + +function ansico_sanitize_micropost_max_chars( $value ) { + $value = intval( $value ); + if ( $value < 1 ) { + $value = 500; + } + return $value; +} + +function ansico_render_micropost_max_chars_field() { + $value = ansico_get_micropost_max_chars(); + echo ''; + echo '

' . esc_html__( 'Default is 500 characters.', 'ansico-some-plugin' ) . '

'; +} + +function ansico_render_clean_up_profile_settings_field() { + $enabled = ! empty( get_option( 'ansico_clean_up_profile_settings', '' ) ); + echo ''; +} + +function ansico_render_settings_page() { + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + ?> +
+

+
+ +
+
+ is_main_query() && $query->is_author() ) { + $types = $query->get('post_type'); + if (empty($types) || $types === 'post') { + $query->set( 'post_type', array( 'post', 'micropost' ) ); + } elseif (is_array($types) && !in_array('micropost', $types)) { + $types[] = 'micropost'; + $query->set('post_type', $types); + } + } +} + + +/* ========================================================================== + 1.6. FORCE COMMENTS OPEN FOR MICROPOSTS + ========================================================================== */ +add_filter( 'comments_open', 'ansico_force_micropost_comments_open', 10, 2 ); +function ansico_force_micropost_comments_open( $open, $post_id ) { + if ( get_post_type( $post_id ) === 'micropost' ) { + return true; + } + return $open; +} + + +/* ========================================================================== + 1.7. FORMAT MICROPOST COMMENTS (Mastodon & Embeds) + ========================================================================== */ +add_filter( 'comment_text', 'ansico_format_comment_text', 10, 2 ); +function ansico_format_comment_text( $text, $comment = null ) { + if ( ! is_object( $comment ) || get_post_type( $comment->comment_post_ID ) !== 'micropost' ) { + return $text; } - ob_start(); + return ansico_get_formatted_comment_html( $comment, true ); +} + +function ansico_apply_micropost_text_formatting( $text ) { + $text = (string) $text; + + $text = preg_replace('/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/i', '$1', $text); + $text = preg_replace('/(?@$1@$2', $text); + $text = preg_replace_callback('/(?<=^|\s|>|>)#([\p{L}\p{N}_]+)/u', function($m) { + $link = get_term_link($m[1], 'micropost_tag'); + if ( is_wp_error($link) ) { + $link = home_url('/micropost-tag/' . sanitize_title($m[1]) . '/'); + } + return '#' . esc_html($m[1]) . ''; + }, $text); + $text = make_clickable($text); + $text = preg_replace('/\*\*(.+?)\*\*/s', '$1', $text); + $text = preg_replace('/\*([^\*]+)\*/s', '$1', $text); + $text = preg_replace('/`([^`]+)`/s', '$1', $text); + $text = preg_replace('/^>\s+(.*)/m', '
$1
', $text); + + return $text; +} + +function ansico_get_formatted_comment_html( $comment, $already_filtered = false ) { + if ( ! is_object( $comment ) ) { + return ''; + } + + $raw_text = isset( $comment->comment_content ) ? (string) $comment->comment_content : ''; + if ( $raw_text === '' ) { + return ''; + } + + preg_match( '/(https?:\/\/[^\s()<>{}\[\]]+)/i', $raw_text, $url_matches ); + $first_url = ! empty( $url_matches[1] ) ? $url_matches[1] : ''; + + $text = esc_html( $raw_text ); + + $text = ansico_apply_micropost_text_formatting( $text ); + $text = wpautop( $text ); + + if ( $first_url ) { + $embed_data = ansico_fetch_metadata_internal( $first_url ); + if ( $embed_data && ! empty( $embed_data['title'] ) ) { + $img_html = ! empty( $embed_data['image'] ) ? '' : ''; + $text .= '
' . $img_html . '
' . esc_html( $embed_data['domain'] ) . '

' . esc_html( $embed_data['title'] ) . '

'; + } + } + + return ansico_prepare_comment_display_html( $text ); +} + +function ansico_prepare_comment_display_html( $html ) { + $html = (string) $html; + if ( $html === '' ) { + return ''; + } + + // Normaliser WordPress-kommentar HTML uden at skabe ekstra luft omkring embeds. + $html = shortcode_unautop( $html ); + + // Fjern tomme afsnit og linjeskift rundt om embed-kort. + $patterns = array( + '#

\s*(

]*>)#i', + '#(
)\s*

#i', + '#

\s*(]*>\s*]*class="ansico-tweet-embed-image"[^>]*>\s*)\s*

#i', + '#

\s*(]*class="ansico-tweet-embed-image"[^>]*>)\s*

#i', + '#

\s*(]*>.*?)\s*

#is', + '#

\s*

#i', + ); + $replacements = array('$1', '$1', '$1', '$1', '$1', ''); + $html = preg_replace( $patterns, $replacements, $html ); + + return trim( $html ); +} + +/* ========================================================================== + 1.8. CUSTOM COMMENT MARKUP (Design uden "siger" og med ny opstilling) + ========================================================================== */ + +function ansico_custom_comment_markup($comment, $args, $depth) { + $GLOBALS['comment'] = $comment; + $avatar = get_avatar($comment, 40, '', '', array('class' => 'ansico-tweet-avatar')); + $author_link = get_comment_author_link($comment); + $author_url = ''; + if ( is_object( $comment ) && ! empty( $comment->user_id ) ) { + $author_url = get_author_posts_url( (int) $comment->user_id ); + } elseif ( is_object( $comment ) && ! empty( $comment->comment_author_url ) ) { + $author_url = $comment->comment_author_url; + } + $avatar_html = $author_url ? '' . $avatar . '' : $avatar; + $time_display = get_comment_date( get_option('date_format'), $comment ) . ' · ' . get_comment_time( get_option('time_format'), false, false, $comment ); + $like_button = ansico_render_like_button( 'comment', $comment->comment_ID ); ?> -
'ansico-some-tweet' ) ); ?>> - Avatar -
-
- - -
-
- -