Leaderboard
Popular Content
Showing content with the highest reputation on 09/18/2017 in all areas
-
Why not? It's not that much work and provides you with all the niceties of language support. Drop a simple PHP template in the regular templates folder: <?php include("../site/ajax/{$input->urlSegment1}.php"); and create a template with url segments enabled with pattern: regex:^[a-zA-Z0-9]+\.php$ A single, hidden page can then route all your ajax calls in a language-aware way. Altogether that shouldn't take more than five minutes.6 points
-
I also recommend using built-in InputfieldPageAutoComplete, install it from Modules > Core and change categories field to use autocomplete. It's much easier to seach and pick categories with it. There's also selectize and chosen js alternatives as well https://modules.processwire.com/modules/inputfield-selectize/ https://modules.processwire.com/modules/inputfield-chosen-select/3 points
-
3 points
-
For the last week or so, a number of accouts have started to post status updates with (mostly) unrelated content. I've checked out the submission histories of ~20 of them, and none of them has a recent post. They were registered long time ago and made several status updates over time. I started noticing them after the last week's forum update. Something about it allowed these status updates to surface, and now around ~10-15 updates are posted daily, which is enough to flood the activity stream. Is anyone else bothered by this? These are from the last 24 hours3 points
-
You are right. Yes, and we are working to resolve it. You've been a great help so far, reporting the spam, thanks!3 points
-
@elabx - thought I'd take a quick look into what is actually required and this seems to work well: $this->addHookAfter('ProcessPageSearch::executeFor', function($event) { $response = $event->return; $responseArray = json_decode($response, true); $matches = $responseArray['matches']; $i=0; foreach($matches as $match) { if($match['type'] == 'Pages' && strpos($match['path'], $this->config->urls->admin) === false) $matches[$i]['editUrl'] = $match['path']; $i++; } $responseArray['matches'] = $matches; $event->return = json_encode($responseArray); }); Note that it only changes the link if the match has type of "Pages" and also doesn't point to an admin url. Let me know if this works at your end ok.3 points
-
Not what you asked, but assuming that you will be using these (or their variants) nutrition name, quantity and measure over and over, typing them in a textarea field and using some regex magic to split them up is probably not the better solution. In addition, typing the stuff up every time is tedious. I'd go for page fields or fieldtype options, or better yet, since you are grouping items, repeaters or even better repeater matrix or table combined with page field (for nutrition name) + integer (quantity) + fieldtype options or page field (measure). The latter modules are paid modules but well worth the spend. Using this approach, not only do you throw out the need to use regex, you also get the benefits of a clear presentation, user friendly/easy to edit, easy to add and remove items, searchable items, etc.2 points
-
2 points
-
That's basically how I have handles it in the past: path/to/myajaxtemplatefile.php?lang=portugues Then in the myajaxtemplatefile.php file add this to set the language: $user->language = $languages->get($sanitizer->selectorValue($input->get->lang));2 points
-
Looking at ProcessField.module, this is where a field is saved // ProcessField.module public function ___executeAdd() { // unrelated shortcut feature: double check that all field tables actually exist // and re-create them in instances where they don't (like if a bunch of fields // were migrated over in an SQL dump of the "fields" table or something). $this->wire("fields")->checkFieldTables(); return $this->executeEdit(); } public function ___executeEdit() { // ... if($this->field->id) { $headline = sprintf($this->_x('Edit Field: %s', 'edit headline'), $this->field->name); // Headline when editing a field } else { $headline = $this->_x('Add New Field', 'add headline'); // Headline when adding a field } // ... return $out; } And this is the checkFieldTables() method protected function checkFieldTable(Field $field) { // if(!$this->wire('config')->debug) return; $database = $this->wire('database'); $table = $database->escapeTable($field->getTable()); if(empty($table)) return; $exists = $database->query("SHOW TABLES LIKE '$table'")->rowCount() > 0; if($exists) return; try { if($field->type && count($field->type->getDatabaseSchema($field))) { if($field->type->createField($field)) $this->message("Created table '$table'"); } } catch(\Exception $e) { $this->trackException($e, false, $e->getMessage() . " (checkFieldTable)"); } } Here I can deduce: There's something wrong with the field table, it already exists but PW cant associate the field with its id/table? $field->type is empty string or field does not return a schema. Having null fieldtype probably means something wrong with the Module cache, refreshing cache may help. Going forward, this is how field table is created public function ___createField(Field $field) { $database = $this->wire('database'); $schema = $this->getDatabaseSchema($field); if(!isset($schema['pages_id'])) throw new WireException("Field '$field' database schema must have a 'pages_id' field."); if(!isset($schema['data'])) throw new WireException("Field '$field' database schema must have a 'data' field."); $table = $database->escapeTable($field->table); $sql = "CREATE TABLE `$table` ("; foreach($schema as $f => $v) { if($f == 'keys' || $f == 'xtra') continue; $sql .= "`$f` $v, "; } foreach($schema['keys'] as $v) { $sql .= "$v, "; } $xtra = isset($schema['xtra']) ? $schema['xtra'] : array(); if(is_string($xtra)) $xtra = array('append' => $xtra); // backwards compat: xtra used to be a string, what 'append' is now. $append = isset($xtra['append']) ? $xtra['append'] : ''; $sql = rtrim($sql, ", ") . ') ' . $append; $query = $database->prepare($sql); $result = $query->execute(); if(!$result) $this->error("Error creating table '{$table}'"); return $result; } From here it seems you'd get an error if table couldnt be created, so no issues with table creation. Also you've mentioned that duplication works fine. These are somewhat obvious deductions from the source code. But, to me, everything points to fields table in the DB.2 points
-
I have the same problem. I can confirm it is not really a bug but unwanted behavior @ryan. It occurs, that when you delete pages and create ones (with the same name? in the same run, there is a problem with the correct page to be found. As the page still exists. Is there a way to delete a page not after the entire page call is done? I supposed there is some smart mechanism to make only one SQL query, instead of synchronously deleting pages. Thanks in advance. Right now, I have to resort to two page calls.2 points
-
@bernhard, I've found a way. Hooking ProcessPageEdit::buildForm works wire()->addHookAfter('ProcessPageEdit::buildForm', function (HookEvent $e) { /** @var ProcessPageEdit $edit */ $templates = ['post', 'basic']; $edit = $e->object; $page = $edit->getPage(); if (!in_array($page->template->name, $templates)) return; /** @var InputfieldForm $form */ $form = $e->return; /** @var InputfieldImage $imageField */ $imageField = $form->children->findOne('name=images'); if (!$imageField) return; $imageField->maxFiles = 1; }); When I try to add more images, field just replaces the first one, not allowing more than one. If there were multiple images before, they disappear after page save, only the first one remains.2 points
-
2 points
-
@MilenKo If you want to go plain text, you can use: https://modules.processwire.com/modules/fieldtype-yaml/ and no need to use regex magic Also, to make it colorful, you can use this one: https://modules.processwire.com/modules/inputfield-ace-extended/ But the latter has some quirks when using with Fieldtype Yaml, I cannot recall exactly what, but it was something with the settings not showing. I decided to remove it because Inputfield Ace Extended's GUI is too scary for ordinary editors1 point
-
1 point
-
I agree, this could be improved a bit, otherwise from the security standpoint you are – of course – right. However, currently I need to "import" old users with passwords of the previous "old" site and their role does not let them do anything in the admin, they only have access to a custom "download page" to download some "semi sensitive" docs. This will change in the future and that is when the site will need "proper" user management.1 point
-
Glad it worked so well for you! The profile-edit permission I guess is not critical if you don't have the "Password Force Change" module installed, or if you are not relying on the "Email New User" module to automatically generate the user passwords. The thinking here is that you probably don't (or shouldn't) know the passwords of the users, so you use EmailNewUser to generate a password, but then you want to ensure they change it quickly because the password was included in an email (hence the use of PasswordForceChange). And to be able to change their password on first login, they need to be able to edit their profile. I guess that wording needs to change to explain things better. Any thoughts?1 point
-
And today it worked for me flawlessly! A big thanks for this (and for all the other countless goodies you've shared with us....). Just one question though, your note in the Role's block reads: At least one of these roles must have the "profile-edit" permission so that the user can change their password the first time they log in. The permission profile-edit is not needed if my client does not want users to change their passwords, right? At least for the time being users should not change their passwords, it is a feature we want to add later.1 point
-
You can do this with a hook to Pages:added() in /site/ready.php $pages->addHookAfter('added', function(HookEvent $event) { $page = $event->arguments(0); if($page->template->name !== 'project') return; // Only for this template // Define your default labels and values $defaults = [ 'Size' => '', 'Year' => '2017', 'Location' => 'New Zealand', 'Status' => '', ]; // Add default items to repeater field foreach($defaults as $key => $value) { $item = $page->meta_fields->getNew(); // Populate subfields $item->field_1 = $key; $item->field_2 = $value; $item->save(); $page->meta_fields->add($item); $page->save(); } });1 point
-
I understand. No need to overengineer a simple blog. But check out the module description. Maybe not with this project but @Robin S gives a few use cases, which I'm sure you'll find quite useful later on.1 point
-
Thank you @abdus and @bernhard for sharing your ways. It is always interesting to find out some ways to have an easier and lighter approaches. Will try the next theme to accomplish the multiple use of single fields and setting up the differences in the code.1 point
-
Thanks @abdus I like the idea of listing the categories with a few posts under each one at /categories/. Is a good use of that page. Might try the /blog/categories/ too, see which works best for me. Not got into hooks yet but that's the second time I've read about Page::path tonight. On the bucket list along with writing a module.1 point
-
I'd pluralize category -> categories and display a list of categories with 3-4 posts under each category. Then you can display a category under /categories/processwire or use urlSegments to rename that to /category/processwire. Or just render category list at /categories with urlSegments and redirect /category to /categories. What I normally do is keep categories under /blog/categories/. Everything works just fine with no need for urlSegments. One handy tool when using urlSegments is to hook into Page::path and modify $event->return, so you won't have to manually building urls everywhere you need. You still need to implement urlSegment logic though, changing Page::path is a passive operation, it doesnt change routing behavior1 point
-
Hello @ all, I have a some templates which will be loaded via AJAX. They are located in a separate folder under site/ajax/ so they are not in the PW template folder. I have bootstraped these templates via "include("../../index.php");" so I can query PW fields via API calls. It works quite well and I get all values from my PW fields. Unfortunately if I switch the language from German to English, all values will stay in the default language (German). So the language change will not be taken into account, because there are no different urls for each language (no PW pages). Has someone dealed with the same problem and could give me a hint how to take the language change into account? My idea was to add a query string with the id of the language at the end of the AJAX href (like "path/to/myajaxtemplatefile?id=1008) but maybe someone has a better idea. I dont want to create a real PW page for such small piece of information. Best regards1 point
-
Hi @Juergen Maybe you can use wireRenderFile and pass language variable in arguments and then use getLanguageValue.1 point
-
Glad to help I'm intrigued, though. I thought Empty Cache and Hard Reload affected just the asset/file cache. Does chrome cache redirects too? Or how can file cache stop fields from being saved? Also, a useful hook to keep around. To refresh module cache on superuser login: $this->addHookAfter('Session::loginSuccess', function (HookEvent $e) { /** @var User $user */ $user = $e->arguments('user'); if ($user->isSuperuser()) { $e->modules->refresh(); } });1 point
-
Thanks @abdus for taking a look at it! Unfortunately it did not help. I also tried cleaning all the other ProcessWire cache just in case but it did not help either. However, since initially I forgot about refreshing the module cache, you gave me the idea to refresh the browser cache too (Chrome: Empty cache and hard reload). And this one did help! I still find it strange that this was the issue but browser caches can lead to troubles Thanx once more!1 point
-
Never got round to Bootstrap 4. I used BS 2 and really liked it but the pace of development was pretty slow. Foundation were introducing some great features that I liked so I switched. I was probably a little hasty with the switch because I began to miss the simplicity of Bootstrap, it's much better docs and support for xs screens. What led me to UI Kit (V2 at the time) was a project I worked on really needed a native dynamic grid. UI Kit had that and it worked really well. I can recommend UI Kit 4 though. It's looking like a really advanced but simple to use system. Thanks for the BS 4 tip. Will have a look.1 point
-
Works great! Just added: $match["template"] == "admin" Because I didn't want normal "content" pages being modified. Thanks a lot for the help!1 point
-
Bumped to 0.2.3-beta: Adds support for ProcessWire 2.8 Rolls back previous fix in favour of the FileCompiler doing its thing1 point
-
Is this a ProcessWire friday happiness guest blog post request I'm reading?! 'cause it would be awesome.1 point
-
Just in case someone else arrives in this thread, this is now implemented in Batch Child Editor: https://processwire.com/talk/topic/6102-batch-child-editor/?do=findComment&comment=1499751 point
-
This is a really BIG Project you should write an article around this especially a case study1 point
-
If you define the namespace on top of your script, you wont have to prefix functions with \Processwire\ #!/usr/bin/php <?php namespace ProcessWire; // remember to include namespace include("./index.php"); // bootstrap ProcessWire // ... function createMockUsers() { $u = new User(); $u->of(false); // short for outputFormatting // inside closure you cannot access global $wire variable // unless you set function myFunction() use ($wire) {} // but you can call wire() function instead $u->name = wire()->sanitizer->pageName("newname"); $u->pass = "yo12345"; $u->email = wire()->sanitizer->email("example@processwire.com"); $u->addRole('guest'); $u->save(); } // ... createMockUsers();1 point
-
I just hit this same issue as well. My resolution was to break up my script into two separate files (first one deletes a bunch of pages, second one adds a bunch).1 point
-
That the css way. You can also use php to achieve this: $i = 1; foreach($page->repeater_field as $repeater) { $i++; // 2, 3, 4, 5, etc $odd = $i % 2 == 0; if ($odd) { echo "<div class='item-$i item-odd'>"; // Use .item-1, .item-2, etc to style /* OR */ echo "<div class='item-$i item-odd' style='background:{$repeater->color_field}'>"; // Or use a the color field by soma to select color in repeater echo $repeater->text; // Left echo $repeater->image; // Right echo "</div>"; } else { echo "<div class='item-$i item-even'>"; echo $repeater->image; // Left echo $repeater->text; // Right echo "</div>"; } } This could be written less verbose, but I think it gets the point accross.1 point
-
Here's a tip for making your global settings / global options page easily accessible in the admin, without having to create a custom process module or going to the page using the pagetree. Let's say the page name of your settings page is called "settings" and it's directly under home. Now, create a *new* page under the admin page in ProcessWire. Use the "admin" template. Call this page "settings" as well. After saving, it will now give you the option to choose which process module this admin page will utilize. Choose "ProcessPageEdit". Now you will have a link in the main navbar to this Settings page, but when you go to it, it will error saying "Unknown page" + "the process returned no content". What you need to do is make this page load the /settings/ page you originally made. Using the special "/site/ready.php" file (create ready.php if it doesn't exist), you can add the following line of code to it: if($page->template=="admin" && $page->name=="settings") $input->get->id = $pages->get("/settings/")->id; Now go to the Settings page in the navbar. Nice, easy and "official" feeling.1 point
-
See these examples: http://processwire.com/api/variables/pages/ https://processwire.com/talk/topic/1153-adding-images-to-a-page-via-the-api/ https://processwire.com/talk/topic/1153-adding-images-to-a-page-via-the-api/?p=10334 https://processwire.com/talk/topic/206-renaming-uploaded-files-from-tmp-name/#entry13711 point
-
Welcome to the forums briangroce. I've begun to understand WillyC's language, but it's taken awhile. I think what he was trying to say is that you need to use $l->files->path(); as a function (method) call, and not as a property. Though that's a good reminder to me that I need to make it work as a property too.1 point