-
Posts
6,314 -
Joined
-
Last visited
-
Days Won
318
Everything posted by bernhard
-
This thread/post might also be interesting for you:
-
Page Hit Counter – Simple Page View Tracking
bernhard replied to David Karich's topic in Modules/Plugins
Maybe PHC simply does not track your visits because you are logged in? You can try visiting the page in incognito mode.- 111 replies
-
- hitcounter
- tracking
- (and 4 more)
-
Page Hit Counter – Simple Page View Tracking
bernhard replied to David Karich's topic in Modules/Plugins
Hey @David Karich thx for this great module ? Could you please make the buildPageListHitCounter() method public, so that I can use it on my custom pagelist labels? Then I can build more complex labels like this one: // hit counter $hits = $this->wire->modules->get('PageHitCounter') ->buildPageListHitCounter((int) $page->get(PageHitCounter::PHCFIELDNAME)); $event->return = $hits.$badge($type($page)).$page->range->format().", ".$page->title; Thx- 111 replies
-
- hitcounter
- tracking
- (and 4 more)
-
I've added an example how this can be done using RockFinder3 in the related thread:
-
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
I was mentioned in this post by @MoritzLost and thought that would be a nice challenge and a nice little tutorial. I've updated the docs: https://github.com/baumrock/rockfinder3#example-group-by-date Example: Group by date As an example we will create a list of the count of cats and dogs related to their page-creation day. We start with a simple list of all ids of cats and dogs: $rf = $rockfinder->find("template=cat|dog"); $rf->dumpSQL(); $rf->dump(); We can't simply add the created column because this is a timestamp. We need a formatted date, so we add it as custom SQL: $rf = $rockfinder->find("template=cat|dog"); $rf->query->select("DATE_FORMAT(pages.created, '%Y-%m-%d') as created"); $rf->dumpSQL(); $rf->dump(); Great! Now we need to group the result by the date string: $rf = $rockfinder->find("template=cat|dog"); $rf->query->select("DATE_FORMAT(pages.created, '%Y-%m-%d') as created"); $rf->query->select("COUNT(id) as cnt"); $rf->query->groupby("DATE_FORMAT(pages.created, '%Y-%m-%d')"); $rf->dumpSQL(); $rf->dump(); Wait... That's not what we expected, right? That's because we still have the pages.id column in our SELECT and GROUP BY statement and therefore we end up with all the cats and dogs as unique rows. To get rid of that column we make one important change: Instead of adding the SELECT and GROUP BY statement to the query we overwrite it: $rf = $rockfinder->find("template=cat|dog"); $rf->query->set('select', [ "DATE_FORMAT(pages.created, '%Y-%m-%d') as created", "COUNT(id) as cnt", ]); $rf->query->set('groupby', [ "DATE_FORMAT(pages.created, '%Y-%m-%d')", ]); $rf->dumpSQL(); $rf->dump(); Not too complicated, right? You want yearly stats? Easy! Simply change the date format string to %Y: -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
I think everybody who has ever used the macro recorder of msoffice/vba knows that this world is not ideal ? But I think I know what you are talking about - I've been there ? -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
Well... I've read your post 3 times and think I understand what you mean. I don't think that there is any common definition what a migration exactly is. There are too many different scenarios where the term can be used: https://en.wikipedia.org/wiki/Migration I'm mainly using it in my modules nowadays with the migrate() function to get consistent field/template/page setups that I can use and quickly change in the codebase that is version controlled: $this->rm()->migrate([ 'fields' => [ 'foo' => [ 'type' => 'textarea', 'label' => 'Text1', "inputfieldClass" => "InputfieldCKEditor", "contentType" => 1, ], ], ]); This could simply be changed and committed: $this->rm()->migrate([ 'fields' => [ 'foo' => [ 'type' => 'textarea', 'label' => 'Text1', "inputfieldClass" => "InputfieldCKEditor", "contentType" => 1, ], 'bar' => [ 'type' => 'textarea', 'label' => 'Text2', "inputfieldClass" => "InputfieldCKEditor", "contentType" => 1, ], ], ]); Then simply run a git pull on the server and I have the same setup as locally. -
Are you talking about adding the script in the PW backend or frontend? If backend, then it's simple: // in your init() method of the module $url = $this->wire->config->urls($this); // url to current module $this->wire->config->scripts->add($url."YourScript.js"); You can hook ProcessPageView::pageNotFound and define custom endpoints so you don't need to create a file for the ajax endpoint manually. A simple example can look like this: public function init() { $this->addHookBefore('ProcessPageView::pageNotFound', $this, 'handleWebhooks'); } public function handleWebhooks($event) { $url = trim($event->arguments(1),"/"); switch($url) { case "api-create-user": $this->createUser(); break; case "api-delete-user": $this->deleteUser(); break; // by default we exit early and don't do anything default: return; } // show 200 status code instead of 404 // this could also be done in the method calls above http_response_code(200); die("success"); } There's also this thread with lots of infos:
-
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Please dump your SQL and fire that manually to your DB. You can use whatever tool you like. Tracy comes with Adminer for example. You might get more helpful error messages then. Start with simple SQL statements and then go further. -
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
I'm not sure about the limit=12 in the initial find - you need to check that! -
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Yes, that was my guess. Please report back your findings ? -
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Hi @Erik Richter First, I'd try to find out where the slowdown comes from: ProcessWire or RockFinder? Maybe you can dump the created SQL statement and test it manually. https://github.com/baumrock/RockFinder3#dumping-data It's just a guess, but maybe it gets faster if you do a really simple query on the PW selector part and then refine the result using custom SQL? https://github.com/baumrock/RockFinder3#custom-sql -
Thx, that helped me a lot today ?
-
Yes and no. This post is a result of removing jQuery from my project, so you are on one hand spot on. I'M using uikit for the frontend and I didn't want to include another framework when uikit already ships with lots of nice little helpers. Only things that I've added so far are custom methods for slideDown(), slideToggle() and slideUp() (https://gist.github.com/skttl/b8ea597ebf2db66a3e2a06491f7b4029) Thx @adrian, you are always one step ahead ? This is my final (?) version: let mail = util.$('#frm-mail').value; let sms = util.$('#frm-sms').value; let msg = util.$('#nl-form input[name=message]').value; let cmt = util.$('#nl-form input[name=comment]').value; let csrf = util.$('#tm-newsletter input[name=csrf]'); // show loading icon util.addClass(button, 'loading'); // setup headers let headers = {} headers['X-Requested-With'] = 'XMLHttpRequest'; headers['X-'+util.data(csrf, 'tokenname')] = util.data(csrf, 'tokenvalue'); // send ajax util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', headers, data: JSON.stringify({ mail:mail, sms:sms, honey:msg+cmt, }), }) .then(function() { // success RockUikit.slideUp(button.closest('form')); RockUikit.slideDown(util.$('#tm-newsletter .tm-success')); }).catch(function(error) { UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>'); util.removeClass(button, 'loading'); }); Server side: // template if(!$config->ajax) throw new Wire404Exception(); $gg->subscribe(); // module public function subscribe() { try { $input = json_decode(file_get_contents('php://input')); if(!$input) throw new WireException("No data"); if(!$this->wire->session->CSRF->hasValidToken()) { throw new WireException("CSRF failed"); } $mail = $this->wire->sanitizer->text($input->mail); $sms = $this->wire->sanitizer->text($input->sms); $honey = $this->wire->sanitizer->text($input->honey); // honeypot if($honey) throw new WireException("Invalid request"); // both empty? if(!$mail AND !$sms) throw new WireException("No data"); // create page $p = new Page(); $p->template = 'signup'; $p->parent = '/data/newsletter'; $p->title = implode(" | ", [ date("Y-m-d H:i:s"), $mail, $sms ]); $p->json = json_encode(['mail'=>$mail, 'sms'=>$sms]); $p->save(); die('success'); } catch(\Throwable $th) { http_response_code(400); die($th->getMessage()); } } Thx guys! Any ideas for improvement? ?
-
Thx @kongondo that helped a lot ? Also thx @elabx this is what seems to work for me: util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', data: JSON.stringify({ mail:mail, sms:sms, msg:msg, cmt:cmt, }), }) .then(function(response) { // show success message }).catch(function(error) { UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>'); util.removeClass(button, 'loading'); }); No idea how exactly I was using the catch statement before, but it somehow did not fire. Now everything seems to be fine, but I'll have to do more testing ? Probably not the best idea for a PW developer ?
-
Hi, I'm trying to send an ajax request on my new site via UIkit's built in little JavaScript framework: https://github.com/uikit/uikit-site/blob/feature/js-utils/docs/pages/javascript-utilities.md#ajax util.ajax('/data/newsletter/', { responseType: 'json', method: 'POST', data: JSON.stringify({ mail:mail, sms:sms, msg:msg, cmt:cmt, }), }) .then(function(xhr) { console.log(xhr); if(xhr.status !== 200) { UIkit.modal.alert('error xyz'); } }); The backend throws a WireException because the form is not filled correctly and that's totally fine. try { $gg->subscribe(); } catch(Throwable $th) { http_response_code(400); die($th->getMessage()); } But I'd like to catch this error and show a message to the user. In jQuery this is easy: $.post('status.ajax.php', {deviceId: id}) .done( function(msg) { ... } ) .fail( function(xhr, textStatus, errorThrown) { alert(xhr.responseText); }); But how do I do that with the uikit framework or vanilla javascript? I've done some research and tried several try/catch variants but I always end up in the error message in the console. This is the source of the uikit ajax function: https://github.com/uikit/uikit/blob/ea4453b1a71bfebb8ac43d81757071cfc5c7cca0/src/js/util/ajax.js#L5-L62 It seems that they have thought about "network error" and "network timeout". But how do I catch them? Thx for your help ? PS I think @Tom. you are quite experienced with JS and Uikit?
-
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Hi @thetuningspoon I think so, but don't know for sure. It's definitely worth a try ? This is a sample sql that RF3 generates: https://github.com/baumrock/rockfinder3#dumping-the-sql-of-the-finder Why? Do you need to query lots of pages and fields and then return a subset of that? Yeah, why not. Just try RF3 and add such a method as PR ? https://github.com/baumrock/RockFinder3/blob/40da7c5f087d87bc33d883add5b78cf7c546bacd/RockFinder3.module.php#L356 Sounds like another great PR ? I don't want do sound like "do that yourself"... I'm happy to implement anything you need. But I don't have the time and energy to do that for free atm. Hope that helps ? -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
the function itself is not deprecated - just its use on objects is. I don't know if I'm using it like this anywhere. If I do, please let me know. If not - everything's fine ? ? -
RockMigrations1 - Easy migrations from dev/staging to live server
bernhard replied to bernhard's topic in Modules/Plugins
Thx @eydun but your error message states that this error comes from the core and not from my module ? -
yeah, I'm working on something but don't have anything usable yet ?
-
Hi @teppo any ideas why I'm getting this error on a fresh install? Notice: Trying to get property 'paths' of non-object in C:\laragon\www\micropage\site\modules\Wireframe\lib\Config.php on line 163 Warning: Creating default object from empty value in C:\laragon\www\micropage\site\modules\Wireframe\lib\Config.php on line 173 Also the directories look weird. The regular directories have not been created, but they are also not listed on the settings page:
-
RockFinder3 - Combine the power of ProcessWire selectors and SQL
bernhard replied to bernhard's topic in Modules/Plugins
Hi @3fingers I'm sorry, I have never ever used this field. But what you need should be quite simple to do using custom SQL: https://github.com/baumrock/rockfinder3#custom-sql You could also create a custom column type: https://github.com/baumrock/rockfinder3#custom-column-types and I could add support for that if you send a PR. Or I could implement that feature if you want to sponsor such an update. -
Hi @markus_blue_tomato just wanted to let you know that I got rid of the errors ? I used 1600x900 for the blurhash which led to the errors on the one hand and also to a huge filesize on the other hand. Changing the blurhash size to 16x9 solved both issues. I didn't want to use a small hash at first, because the images are part of a slider and the small hash messed up the design. I also didn't want to code things into css. I ended up setting the width of the hash as style attribute. Seems to work fine and got the document size from 1MB to 25kB ?
- 37 replies
-
- image
- lazy loading
-
(and 2 more)
Tagged with:
-
RockNette - Wrapper to integrate Nette Framework into ProcessWire
bernhard replied to bernhard's topic in Modules/Plugins
Hi eydun, I thought it might make sense to be able to share the nette components across several modules. I'm not sure if that is the best approach. Another option would be to use composer in the root folder to load nette components (I think that would be the more standard way)! I just didn't want to put it in the module itself because this would mean I'd need to update the modules with every update of nette...