Leaderboard
Popular Content
Showing content with the highest reputation on 03/25/2021 in all areas
-
After looking into the code, adding support for a parallel uploads limit wasn't too hard, I think. If you're willing to try, I've created a fork of the current PW dev branch and added that functionality. This lets you set a configurable limit for how many uploads happen at once, the rest is queued and processed as soon as others finish.4 points
-
RF3 got a very nice little update today ? Aggregations Often we need to calculate sums or averages of table data quickly and efficiently. RockFinder3 makes that easy as well: $avg = $rockfinder->find("template=cat") ->addColumn('weight') ->getObject("SELECT AVG(weight)"); db($avg); $cats = $rockfinder ->find("template=cat") ->addColumns(['title', 'weight']); $cats->dump(); // dump finder data to tracy $obj = $cats->getObject("SELECT SUM(`weight`) AS `total`, COUNT(`id`) AS `cats`, SUM(`weight`)/COUNT(`id`) AS `avg`"); db($obj); // dump result of aggregation What happens behind the scenes is that RockFinder3 gets the current SQL query of the finder and adds that as FROM (...sql...) AS tmp to the query that you provide for aggregation. This is the resulting SQL query of the example above: SELECT SUM(`weight`) AS `total`, COUNT(`id`) AS `cats`, SUM(`weight`)/COUNT(`id`) AS `avg` FROM ( SELECT `pages`.`id` AS `id`, `_field_title_605cab16f38ce`.`data` AS `title`, `_field_weight_605cab16f3993`.`data` AS `weight` FROM `pages` LEFT JOIN `field_title` AS `_field_title_605cab16f38ce` ON `_field_title_605cab16f38ce`.`pages_id` = `pages`.`id` LEFT JOIN `field_weight` AS `_field_weight_605cab16f3993` ON `_field_weight_605cab16f3993`.`pages_id` = `pages`.`id` WHERE (pages.templates_id=44) AND (pages.status<1024) GROUP BY pages.id ) AS tmp You can even provide a suffix for your query to do things like GROUP BY etc: $rf = $rockfinder->find("template=cat|dog"); $rf->addColumns(['created']); $rf->dump(); db($rf->getObjects( "SELECT COUNT(id) AS `count`, DATE_FORMAT(created, '%Y-%m-%d') AS `date`", "GROUP BY DATE_FORMAT(created, '%Y-%m-%d')" ));3 points
-
3 points
-
Hi folks, Just stumbled upon this gem and completed the first two levels ? Looks entertaining indeed (at least for coders, of course...) https://www.i-programmer.info/news/90-tools/14431-oh-my-git-the-game.html Quote: "All in all, Oh My Git! is an intuitive game that really teaches you Git. ...[for those] who has ever struggled with Git." https://blinry.itch.io/oh-my-git Happy gitting ?3 points
-
I've reworked this slightly, based on the helpful suggestion of @Kiwi Chris. The individual migration items are now entered in a repeater field and so the sequence can take into account any dependencies. Each item can be either 'new', 'changed' or 'removed'. When a migration is uninstalled, the sequence is automatically reversed and 'new' items are changed to 'removed' and vice versa. Example below shows a migration testing a page reference dependency (it works!). This is the appearance in the source database (pre-export): If you click 'Preview' you see what changes are proposed to export (see below). This feature also operates to review (in the target database) what changes will happen on install or uninstall - or, if the install has failed, what changes remain (either by modifying the migration or applying a manual fix if all else fails). Export is shown as 'no object' in the above, because the migration has not yet been exported. I think this all seems to work as designed, but am grateful for any futher thoughts on the design. I will now work on tidying the code a bit and doing a bit of documentation. There may still be a few bugs. There are some at the moment that I can't pin down but they are cosmetic rather than fundamental - I think I may need some help from those who understand the inner workings of PW better ( @adrian ?). Promises of help will encourage me to get on and release some code ? Meanwhile, I am happy to answer any further questions.2 points
-
Exactly - THX ? I should maybe use this panel more often, it looks very useful ?2 points
-
Reopening the offtopic for a moment ? I guess life takes people in other directions. That's not my case though (the older ones must remember me a bit ?). Still working with ProcessWire every day, and I'm hugely thankful to Ryan for this. Just not posting much lately. I have a bunch of sites to add to the directory and have to find a bit of time and will to do it. Aside from Processwire I'm also exploring Svelte and the very new (still in Beta) SvelteKit. They don't replace Processwire though, and can even be complementary if Processwire is used as a headless CMS. I started a new thread, so the discussion can go on without getting on and off topic all the time2 points
-
Change Default Language to be None-English | Walk Trough When you start a new (single) language site and the default language shouldn't be English, you can change it this way: Go to the modules core section: Select the Language ones by the filter function: We have four language related modules here, but for a single language site in none english, we only need the base module, named "Languages Support". So go on and install it. After that, you can leave it, ... ... and switch to the newly created Language section under SETUP: Select the default language Enter your new language name or its Shortcut and save the page. I will use DE for a single language site in german here as example: Now I go to the ProcessWire online modules directory, down to the subsection for language packs and select and download my desired (german) one: After downloading a lang pack as ZIP, I go back into my SETUP > LANGUAGES > default language page in admin, select the downloaded lang pack ZIP and install it: After the ZIP is uploaded, the files are extracted and installed, most of my screen is already in the new default language. To get all fully switched, we save and leave that page, ... ... and completely logout from the admin. Now, of course, we directly login back, ... ... and see, that now also the cached parts of the admin have switched to the new default language. ? That was it for a single language site in none english. If you want to have a multi language site, just add more languages to the SETUP > LANGUAGES section. When using a multi language site, I think you also want to use multi language input fields, and maybe different page names for your language page pendents. If so, you need to go into MODULES > CORE > filter LANGUAGE and install what you need or want to use of it, (if not already done). Thanks for reading and happy coding, ?1 point
-
Custom Inputfield Dependencies A module for ProcessWire CMS/CMF. Extends inputfield dependencies so that inputfield visibility or required status may be determined at runtime by selector or custom PHP code. Overview Custom Inputfield Dependencies adds several new settings options to the "Input" tab of "Edit Field". These are described below. Note that the visibility or required status of fields determined by the module is calculated once at the time Page Edit loads. If your dependency settings refer to fields in the page being edited then changes will not be recalculated until the page is saved and Page Edit reloaded. Usage Install the Custom Inputfield Dependencies module. Optional: for nice code highlighting of custom PHP install InputfieldAceExtended v1.2.0 or newer (currently available on the 'dev' branch of the GitHub repo). The custom inputfield dependencies are set on the "Input" tab of "Edit Field". Visibility Show only if page is matched by custom find Use InputfieldSelector to create a $pages->find() query. If the edited page is matched by the selector then the field is shown. Show only if page is matched by selector As above, but the selector string may be entered manually. Show only if custom PHP returns true Enter custom PHP/API code – if the statement returns boolean true then the field is shown. $page and $pages are available as local variables – other API variables may be accessed with $this, e.g. $this->config In most cases $page refers to the page being edited, but note that if the field is inside a repeater then $page will be the repeater page. As there could conceivably be cases where you want to use the repeater page in your custom PHP the module does not forcibly set $page to be the edited page. Instead, a helper function getEditedPage($page) is available if you want to get the edited page regardless of if the field in inside a repeater or not. $edited_page = $this->getEditedPage($page); Required The settings inputfields are the same as for Visibility above, but are used to determine if the field has 'required' status on the page being edited. https://github.com/Toutouwai/CustomInputfieldDependencies http://modules.processwire.com/modules/custom-inputfield-dependencies/1 point
-
I guess that answers the question, thanks!1 point
-
I think I don't understand your question.. I don't have any functions in init.php nowadays. I have everything in init() of a module or in init() of a pageclass. If there is something in init() of a pageclass I have to trigger that manually, which is the reason for the loadClasses method of RM which triggers init() automatically https://github.com/BernhardBaumrock/RockMigrations/blob/2d85e460ce5aa394480906ad5b41cd1a0e86d0fe/RockMigrations.module.php#L1991-L2003 This is a simple pageClass I'm using in my CRM for managing contacts: <?php namespace RockCRM; use ProcessWire\HookEvent; use ProcessWire\Page; class Contact extends Page { const tags = RockCRM::tags; const tpl = RockCRM::prefix."contact"; const prefix = RockCRM::prefix."contact_"; const field_skills = self::prefix."skills"; public function __construct() { parent::__construct(); $this->parent = $this->wire->rockcrm->contacts(); $this->template = $this->wire->templates->get(self::tpl); } public function init() { $tpl = "template=".self::tpl; $this->wire->addHookAfter("ProcessPageEdit::buildForm", $this, "buildForm"); $this->wire->addHookAfter("Pages::saveReady($tpl,id=0)", $this, "onCreate"); } /** * Page edit screen */ public function buildForm(HookEvent $event) { $form = $event->return; $page = $event->process->getPage(); if(!$page instanceof self) return; $crm = $this->wire->rockcrm; /** @var RockCRM $crm */ $rm = $crm->rm(); // modify page edit screen of a contact if($f = $form->get('title')) { $f->label = 'Name of the Contact'; $f->notes = 'Enter a great Name'; } // or load scripts with the new update $rm->addScript(__DIR__."/Contact.js"); } /** * Migrate this pageclass */ public function migrate() { $crm = $this->wire->rockcrm; /** @var RockCRM $crm */ $rm = $crm->rm(); $rm->migrate([ 'fields' => [ self::field_skills => [ 'type' => 'text', 'tags' => self::tags, ], ], 'templates' => [ self::tpl => [ 'tags' => self::tags, 'icon' => 'user-o', 'noSettings' => 1, 'pageClass' => '\RockCRM\Contact', 'fields' => [ 'title', self::field_skills, ], ], ], ]); } /** * Things to do when a contact is created * @return void */ public function onCreate(HookEvent $event) { $page = $event->arguments(0); $page->status = 1; // published, non-temp $event->pages->names()->uniqueRandomPageName(); // unique name } } This setup is extremely powerful, extremely clear and extremely nice to work with ? Was that what you were asking for? ?1 point
-
The module gets better and better and I love working with it every day ? v0.0.42 has a nice little update to include scripts or styles in the PW backend easily. Why is that great? Because you can organize your files better and have everything in place while still having the ease of use (and you don't need to install any other modules for such simple tasks): Usage: I'm using custom page classes for EVERY page I have in my PW installs. One might think that this is overkill - but I'm wasting so much time on old projects looking for code snippets that are all over the project. Some in ready.php, some in init.php, another story are JavaScript snippets for small GUI tweaks... Not any more ? I have a custom PageClass "Foo" and there I have a method that modifies the page edit form (ProcessPageEdit::buildForm) - this is great for changing field properties like columnWidth or labels etc. on the fly without ever having to fire a migration. If I want to change something for my Foo pages, I head over to my IDE, type "Foo" and get directly to the Foo PageClass. But what about JavaScript? Today I needed a little snippet that populates some fields based on other fields. As easy as that: // in the buildForm hook $rm->addScript(__DIR__."/Foo.js"); Everything is well organized, because I have all my classes in a custom folder (inside a module, but the same would apply for the /site/classes folder): .../myModule/classes |-- Bar.php |-- Foo.js |-- Foo.php '-- Whatsoever.php And the JS file will only be loaded on the page edit screen to prevent overhead. Why not just use $config->scripts->add() you might ask? Good question ? $rm->addScript() will additionally add a cache busting timestamp to the file and it will only include the file if it exists on the system. It will also work on Windows systems, which you might forget to take into account if quickly adding it via $config->scripts->add() and last but not least it will also work on PW instances that are running in a subfolder ? if(!is_file($path)) return; $path = Paths::normalizeSeparators($path); $config = $this->wire->config; $url = str_replace($config->paths->root, $config->urls->root, $path); $m = $timestamp ? "?m=".filemtime($path) : ''; $this->wire->config->scripts->add($url.$m); Happy migrating ?1 point
-
I actually find the Debug panel > Selector Queries section more useful because it shows which selector calls result in which SQL queries.1 point
-
Hi there, the idea of this module was born from the need to integrate FB API to bypass the block of reading data after the IOS14 update. FB tells us that in order to continue reading the data we have to send it via the API Convention. I wanted to publish this module finished, but I can't figure out how to do this. :( I don't know if anyone is willing to help me understand how to solve my problems. I'm trying to create a module with the Facebook SDK to send info via API. I attach here what I have done, at the moment, it is all very simple and rough. facebookSDK.zip At the moment the module works only as a link to the SDK folder and can be used to enter the credentials of the token and pixal via two variables. What I would like to do is to leave all the request to the SDK, in order to keep only the creation of objects in the page. Since the use cases are so many, I thought the best solution is to delegate to the module the connection with the SDK and keep in the page the creation of objects to be customized. Basically for the Convention API you need to make these objects UserData CustomData Event For let this module works fine, at moment, I have to add in to the page also the call to the SDK. So, in my page I have $fbSDK = $modules->get('facebookSDK'); use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; use FacebookAds\Object\ServerSide\Content; use FacebookAds\Object\ServerSide\CustomData; use FacebookAds\Object\ServerSide\DeliveryCategory; use FacebookAds\Object\ServerSide\Event; use FacebookAds\Object\ServerSide\EventRequest; use FacebookAds\Object\ServerSide\Gender; use FacebookAds\Object\ServerSide\UserData; // Configuration this all $time = time(); if (isset($_COOKIE['_fbc'])) {$fb_fbc = $_COOKIE['_fbc'];} // This data is always better to have if (isset($_COOKIE['_fbp'])) {$fb_fbp = $_COOKIE['_fbp'];} // This data is always better to have $access_token = $fbSDK->accessToken(); $pixel_id = $fbSDK->pixelId(); // Initialize Api::init(null, null, $access_token); $api = Api::instance(); $api->setLogger(new CurlLogger()); $events = array(); // Specific data only if need in the object $hashEmail = hash('sha256', $user->email); // some data need to be hashed with SHA256 and UTF-8 encoding $user_data_0 = (new UserData()) ->setEmail($hashEmail) ->setClientIpAddress($_SERVER['REMOTE_ADDR']) ->setClientUserAgent($_SERVER['HTTP_USER_AGENT']) ->setFbc($fb_fbc) ->setFbp($fb_fbp); $custom_data_0 = (new CustomData()) // all these data are optional, I only include them as an example ->setValue(str_replace(",", ".", $page->pad_price)) ->setCurrency("EUR") ->setContentName("API test") ->setContentIds($skuAPI_json) ->setContentType("product_group") ->setCustomProperties(array("product_catalog_id" => "111111111")); $event_0 = (new Event()) ->setEventName("ViewContent") ->setEventTime($time) ->setUserData($user_data_0) ->setCustomData($custom_data_0) ->setActionSource("website") ->setEventSourceUrl($page->url(true)); array_push($events, $event_0); $request = (new EventRequest($pixel_id)) ->setEvents($events); $request->execute(); I would like to bring all this part into the module: use FacebookAds\Api; use FacebookAds\Logger\CurlLogger; use FacebookAds\Object\ServerSide\Content; use FacebookAds\Object\ServerSide\CustomData; use FacebookAds\Object\ServerSide\DeliveryCategory; use FacebookAds\Object\ServerSide\Event; use FacebookAds\Object\ServerSide\EventRequest; use FacebookAds\Object\ServerSide\Gender; use FacebookAds\Object\ServerSide\UserData; // Configuration. if (isset($_COOKIE['_fbc'])) {$fb_fbc = $_COOKIE['_fbc'];} if (isset($_COOKIE['_fbp'])) {$fb_fbp = $_COOKIE['_fbp'];} $access_token = $fbSDK->accessToken(); $pixel_id = $fbSDK->pixelId(); // Initialize Api::init(null, null, $access_token); $api = Api::instance(); $api->setLogger(new CurlLogger()); While keeping everything else on the page, so that it is customizable according to the needs of the moment.1 point
-
Don't be worry. I just created my own ProcessFileManager: https://github.com/techcnet/ProcessFileManager1 point
-
I'm not so sure about that. AFAIK, PW has its own Ajax upload implementation in InputfieldFile.js and doesn't queue uploads at all.1 point
-
Another thing, on PW site, would be to allow upload of zip(ed) files to pagefile pageimage fields. As a workaround.1 point
-
Hi @Marco Ro, sorry for may late reply, yes i can share it this is my function to upload an image and a file at the same time if(!$original || !$indonesia || !$other || !$composer){ $note = "Data tidak lengkap"; } else { $newFile = new WireUpload("song_files"); $newFile->setMaxFiles(1); $newFile->setOverwrite(false); $newFile->setDestinationPath($upload_path); $newFile->setValidExtensions(array('pdf','docx','doc')); $files = $newFile->execute(); if(!count($files)) { $newFile->error("No files received, so not creating page."); return false; } $newImg = new WireUpload("img_files"); $newImg->setMaxFiles(1); $newImg->setOverwrite(false); $newImg->setDestinationPath($upload_path); $newImg->setValidExtensions(array('jpeg','jpg','png','gif')); $images = $newImg->execute(); if(!count($images)) { $newImg->error("No files received, so not creating page."); return false; } $newPage = new Page(); $newPage->template = "files"; $newPage->parent = $pages->get("/files/"); $newPage->title = $original; $newPage->text_1 = $indonesia; $newPage->text_2 = $other; $newPage->text_3 = $composer; $newPage->text_4 = $video; $newPage->text_5 = $audio; $newPage->of(false); $newPage->save(); foreach($files as $filename) { $filepath = $upload_path . '/' . $filename; $newPage->files->add($filepath); $newPage->message("Add file : $filename"); unlink($filepath); } foreach($images as $filename) { //add this foreach iteration to upload an image $filepath = $upload_path.'/'.$filename; $newPage->images->add($filepath); $newPage->message("Add Image : $filename"); unlink($filepath); } $newPage->save(); }1 point
-
I hope everyone is having a good week! Commits to the core this week include 10 issue report resolutions (so far). This will likely continue next week as well, and then I'll bump the version up then. Also included this week is an CKEditor upgrade from 4.14.0 to version 4.16.0. While that may sound like a minor CKEditor version bump, there's actually quite a list of updates in the CKEditor 4.x changelog, including a few security-related fixes, though none that I think are likely to affect PW users. I do still have a couple of core feature requests in progress as well, but there's more work still to do on those. Nothing too exciting this week, but I like to check in and say hello either way. I hope you all have a great weekend!1 point
-
On the Template Advanced tab you can set this option on "List of fields to display in the admin Page List" and write "{title}, {createdUser.name}"1 point
-
1 point