-
Posts
110 -
Joined
-
Last visited
-
Days Won
1
Everything posted by Leftfield
-
@BrendonKozthanks mate! I have to try it. Brilliant! @bernhard Yes, for me, it is a fun little thing but very useful. Here's screenshot attached.
-
Hi @All, I made the page with only admin access so I can check in frontend visually (a chart) and links - what pages are most linked from blog pages and where I forgot to use this opportunity. This is important for SEO and removes manual labor. If you have any suggestions, feel free to shoot. Simple explanation: I got template=post and want to see stats with inner links to the homepage and service pages. Thanks @poljpocketfor helping me out! <?php namespace ProcessWire; // Calculate Internal Link Counts and Linked Pages $pages = wire('pages'); // Get all relevant pages directly in one query $relevantPages = $pages->find("template=post|service|home"); $blogPosts = $relevantPages->find("template=post"); $mainPages = $relevantPages->find("template=home|service"); // Function to check if a post DOES NOT link to ANY PUBLISHED service OR home page /** @var PageArray $mainPagesLinks */ $mainPagesLinks = $wire->wire(new PageArray()); foreach ($mainPages as $mainPage) { // this will remove duplicates by default $mainPagesLinks->append($mainPage->links("template=post")); } // Calculate Internal Link Counts and Linked Pages $linkCounts = []; $linkedPages = []; foreach ($relevantPages as $page) { $linkCounts[$page->id] = 0; $linkedPages[$page->id] = []; if ($page) { $items = $page->links(); if ($items->count()) { foreach ($items as $item) { if ($item->template != 'admin') { $linkCounts[$page->id]++; $linkedPages[$page->id][] = $item; } } } } } arsort($linkCounts); // Prepare data for the circle chart $chartLabels = []; $chartValues = []; foreach ($linkCounts as $pageId => $count) { if ($count > 0) { $page = $pages->get($pageId); $chartLabels[] = $page->title; $chartValues[] = $count; } } ?> <div class="container py-5 mb-5 links"> <div class="row py-5"> <div class="col-12 col-md-4 offset-md-4 pb-5"> <canvas id="linkCountChart" width="200" height="200"></canvas> </div> <div class="col-12 col-md-8 offset-md-2"> <div class="accordion" id="internalLinksAccordion"> <?php foreach ($linkCounts as $pageId => $count): ?> <?php if ($count > 0): ?> <?php $page = $pages->get($pageId); ?> <div class="accordion-item"> <h2 class="accordion-header" id="heading<?= $page->id ?>"> <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse<?= $page->id ?>" aria-expanded="false" aria-controls="collapse<?= $page->id ?>"> <?= $page->title ?> (<?= $count ?>) </button> </h2> <div id="collapse<?= $page->id ?>" class="accordion-collapse collapse" aria-labelledby="heading<?= $page->id ?>" data-bs-parent="#internalLinksAccordion"> <div class="accordion-body"> <?php if (!empty($linkedPages[$page->id])): ?> <ul> <?php foreach ($linkedPages[$page->id] as $linkedPage): ?> <?php if ($linkedPage->template != 'service'): ?> <li><a href="<?= $linkedPage->url ?>"><?= $linkedPage->title ?></a></li> <?php endif; ?> <?php endforeach; ?> </ul> <?php else: ?> <p>No internal links found for this page.</p> <?php endif; ?> </div> </div> </div> <?php endif; ?> <?php endforeach; ?> </div> <h3 class="pt-5">Posts without Links to Service and Home Pages</h3> <table class="table"> <thead> <tr> <th>Post Title</th> <th>Edit Link</th> </tr> </thead> <tbody> <?php // echo results foreach ($blogPosts as $post) { if (!$mainPagesLinks->has($post)) { echo "<tr>"; echo "<td><a href=\"{$post->url}\">{$post->title}</a></td>"; echo "<td><a href=\"{$post->editUrl}\">Edit</a></td>"; echo "</tr>"; } } ?> </tbody> </table> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> document.addEventListener('DOMContentLoaded', function () { // Chart data is now defined within the JavaScript scope const chartData = { labels: <?= json_encode($chartLabels); ?>, datasets: [{ data: <?= json_encode($chartValues); ?>, backgroundColor: [ 'rgba(255, 99, 132, 0.8)', 'rgba(54, 162, 235, 0.8)', 'rgba(255, 206, 86, 0.8)', // Add more colors as needed ], }] }; const ctx = document.getElementById('linkCountChart').getContext('2d'); const linkCountChart = new Chart(ctx, { type: 'doughnut', data: chartData, options: { plugins: { legend: { display: true, position: 'bottom', }, } } }); }); </script>
-
List post pages without any link to service or home pages
Leftfield replied to Leftfield's topic in General Support
Working like a charm. Thanks @poljpocket!!!! PS: I will post my code now on the other thread so everyone can grab -
List post pages without any link to service or home pages
Leftfield replied to Leftfield's topic in General Support
I want to list all pages from template=post that don't link to template=home|service. -
List post pages without any link to service or home pages
Leftfield replied to Leftfield's topic in General Support
Hey :). Thanks for helping me!!! Nope. I got the links the same way. Made pie chart, list of all links with number of links pointed to them. But for some reason I can't get pages which do not link other pages (with different template). -
module TextformatterImgDataUri - Embed small images as data URLs
Leftfield replied to BitPoet's topic in Modules/Plugins
Oh man, and I've put it in the field description :D. I was born just a few hundred kilometers from the Tesla's house. It seems like I am Jang for his Jing. -
module TextformatterImgDataUri - Embed small images as data URLs
Leftfield replied to BitPoet's topic in Modules/Plugins
@BitPoetthanks for helping me out!!! All I can get is (normal). Just pasting part of the code: 2024-05-15 09:27:23 leftfield http://localhost/test/ Running TextformatterImgDataUri 2024-05-15 09:27:23 leftfield http://localhost/test/ Running TextformatterImgDataUri 2024-05-15 09:27:23 leftfield http://localhost/test/ Running TextformatterImgDataUri 2024-05-15 09:27:23 leftfield http://localhost/test/ Running TextformatterImgDataUri 2024-05-15 09:27:23 leftfield http://localhost/test/ Running TextformatterImgDataUri -
Hi @All I am checking if the post pages have no links to the service or home pages. If they don't, list them. All I can get is a list of all the post pages with links. I've tried to rewrite this function like 100 times but no luck. What am I doing wrong? // Get all relevant pages directly in one query $relevantPages = $pages->find("template=post|service|home"); $blogPosts = $relevantPages->find("template=post"); $mainPages = $relevantPages->find("template=home|service"); // Function to check if a post DOES NOT link to ANY service OR home page function postHasNoLinksToMainPages($postPage, $mainPages) { $mainPagesIds = $mainPages->explode('id'); foreach ($postPage->links() as $link) { if (in_array($link->id, $mainPagesIds)) { return false; // Found a link to a main page, so return false immediately } } return true; // No links to PUBLISHED main pages found, so return true } // echo results foreach ($blogPosts as $post) { if (postHasNoLinksToMainPages($post, $mainPages)) { echo "<tr>"; echo "<td><a href=\"{$post->url}\">{$post->title}</a></td>"; echo "<td><a href=\"{$post->editUrl}\">Edit</a></td>"; echo "</tr>"; } }
-
module TextformatterImgDataUri - Embed small images as data URLs
Leftfield replied to BitPoet's topic in Modules/Plugins
Hey, @BitPoet I'm excited about this module (and I really need it!). I appreciate your help in advance. I might be stupid as a rock, but at least I'm consistent. I have tried on Windows and Linux (in both cases, php_fileinfo.dll is on). I placed it in the image field, like in the screenshot, but nothing happened. I've cleared the cache, etc. The debug mode is ON, and no error is logged. -
Upon saving the page, update the field on another template (SOLVED)
Leftfield replied to Leftfield's topic in General Support
No, mate. PW (as you all know way better than me) doesn't have the option to change the default fields published and modified. Published is constant, and Modified is changing on every page save. It doesn't suit me, so I made my date field to set a date when publishing/changing so it reflects on the sitemap and tells search engines the page has been changed on that date. Not on every save. -
Upon saving the page, update the field on another template (SOLVED)
Leftfield replied to Leftfield's topic in General Support
@wbmnfktrthanks mate!!! I count beers I owe you.... So for anyone looking at this here is the solution: $wire->addHookAfter("Pages::published(template=post)", function (HookEvent $event) { $pages = $event->object; $page = $event->arguments(0); $blog = wire('pages')->get('template=blog'); $blog->date_modified = $page->date_modified; $blog->save(); // wire()->log->save("debug", "page was published"); }); -
Ehey, aloha everyone! I have two templates: post and blog. When publishing a first-time post, I must update the (same) field date_modified on its parent (a single) template blog. I am trying it via hook, but nothing happens. This checking for status unpublished is not working for some reason too. I appreciate any help! $wire->addHookAfter("Pages::saveReady(template=post)", function($event) { $page = $event->arguments(0); $pages = $event->object; // if ($page->isNew() && $page->status->unpublished != true) { if ($page->isNew()) { $blog = wire('pages')->get('template=blog'); $blog->date_modified = $page->date_modified; $blog->save($blog->date_modified); // $blog->save(); } });
-
I logged into Google Search Console last night. For the umpteenth time, I received the message: "Fixes failed for Page indexing issues - Page with redirect." I am trying to get non-www URLs and use the default htaccess file (trying to keep up with the updates). Problem - Google scans the website URLs in this particular order, and chaining (which is The problem) via htaccess happens: http://www.example.com -> https://www.example.com -> https://example.com Fix: While I do not know how to write directives in the .htaccess, I spent hours to find a solution and finally succeeded. RewriteEngine On RewriteCond %{HTTPS} !on [OR] RewriteCond %{HTTP_HOST} ^www\. [NC] RewriteRule ^ https://example.com%{REQUEST_URI} [R=301,L,NE] However, as I mentioned, I'm unfamiliar with the .htaccess file, and I am 100% sure that this could be written with a wild card. So, on this occasion, by default, can we have an option to avoid chain redirections of URLs?
-
$config->sessionExpireSeconds does not work
Leftfield replied to helmut2509's topic in General Support
@cwsoftthanks for helping me! @adrian It's running on LiteSpeed, but I don't know what's underneath it. But hey, it is working like a charm. -
$config->sessionExpireSeconds does not work
Leftfield replied to helmut2509's topic in General Support
@netcarverYes, it is for me (Thanks for helping me). I tried with php.ini, but nothing. Set 10800, waited a bit and was logged out. :( I see my cookie wires_challenge says: 2024-06-01T15:04:30.853Z but if was same as before asking question session.cookie_lifetime = 10800 -
$config->sessionExpireSeconds does not work
Leftfield replied to helmut2509's topic in General Support
Is it because I ate two cakes and ice cream yesterday that the cookies don't love me anymore? Or maybe it's something else entirely, like needing to clear the cache (I did, deleted cookies too)? This keeps logging me out after about 30 minutes, which is super annoying! Can you help? $config->sessionExpireSeconds = 432000; -
This is my first module. It is primitive, like my neighbor who loves to fire up his new Makita breaker hammer after 21:30h. Please, feel free to do whatever you want. I don't promise I will add better functionality but maybe... If you do, please ping and send me back. Thanks! It loads every page on the backend. It calculates the text width in two fields you choose on the configuration page.. If there are any updates, I will post them here. Happy ProcessWiring! PS: These measurements are specifically for desktop and Google's SERP (Search Engine Results Page). UPDATE on 15 May 2024: Google started to calculate (truncate) the meta title for 20px Arial yesterday. The Module has been updated. Here is the link to download/install the latest version: https://processwire.com/modules/seo-text-width/ EDIT: The version 0.0.5. Added two dropdown fields on the configuration page of the module. PROVE IMAGE: You can check the meta title, which was measured with 18px Arial and it was less than 512 pixels.
- 14 replies
-
- 13
-
Module should load on the (any) page edit in the backend
Leftfield replied to Leftfield's topic in Module/Plugin Development
Resolved. public function init() { $this->addHookAfter('ProcessPageEdit::buildForm', $this, 'addResources'); } public function addResources(HookEvent $event) { $page = $event->object; $this->config->styles->add($this->config->urls->SeoTextWidth . "SeoTextWidth.css"); $this->config->scripts->add($this->config->urls->SeoTextWidth . "SeoTextWidth.js"); }- 1 reply
-
- 1
-
I created this as a hook and it's working great, so I decided to turn it into a module to share. We have option in the backend to calculate number of characters but this script is calculating the width of the text as it should be displayed in Google's SERP for the meta title and meta description. However, it's not working for some reason (that I can't identify). This (primitive) module should load on the (any) page edit in the backend. As you can see, it's supposed to load two files. I'm not sure why it's not functioning. // Module: SeoTextWidth.module class SeoTextWidth extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'SEO field Text Width module', 'summary' => 'This module is calculating width of text in the fields named seo and desc.', 'version' => 1 ]; } public function __construct() { parent::__construct(); } public function init() { $this->addHookAfter('ProcessPageEdit::render', [$this, 'addResources']); } public function addResources(HookArgs $args) { $output = $args->getOutput(); $page = $args->wire('page'); // Check if we're on the page edit view for a valid page if ($page && $page->editable()) { $jsUrl = $this->config->urls->scripts . 'SeoTextWidth.js'; $output->append("<script src='$jsUrl'></script>"); $cssUrl = $this->config->urls->styles . 'SeoTextWidth.css'; $output->prepend("<link rel='stylesheet' href='$cssUrl' />"); } return $output; } }
-
Thank You! Ah, the Privacy Policy! It is a fascinating bedtime story, the legalese equivalent of watching paint dry. But not Terms and Conditions @OLSAbecause you would ping me for a beer next to the sea.