Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/23/2017 in all areas

  1. To show our *.module files with the correct PHP syntax highlighter is now possible on Github. With new repos, you first need to add a .gitattributes file to it. After that you can view *.module files with the PHP syntax highlighter applied: MetadataExif.module So, this doesn't work with already created / comitted repos by simply adding the .gitattributes file. But it will find its way through different caching layers on github if you add it to your repos and further committs to them. (https://github.com/github/linguist/issues/1792#issuecomment-286379822)
    7 points
  2. Hi, here is a very useful tool that check your images in websites against responsiveness: https://github.com/ausi/respimagelint
    4 points
  3. I have found my better checkerbox background image again: in use as BG it looks like this:
    3 points
  4. Process modules (ones that extend Process class) can have execute[Action] methods that are called with their respective urlSegments. In case of your example, the method comments portrait the exact conditions where ___executeFields is executed with /fields urlSegment, for instance. The problem with this approach is that you cannot (or should not) use them on frontend, as Process modules are intended for backend use (unless I'm mistaken). However, calling the method depending on urlSegment is quite simple with the snippet I posted earlier. You can use something similar to following to call execute[Action] methods <?php public function ready() { // accept only single urlSegment if($this->input->urlSegment2) throw new Wire404Error(); // always sanitize user input $method = $this->sanitizer->alpha($this->input->urlSegment1); if(!$method) return; // or perform more sophisticated checks // respond to execute[Action] methods // such as executeList() with /list urlSegment // or executeFields() for /fields urlSegment // create camelCase method name // /json urlSegment will be intercepted by executeJson() function $method = "execute" . ucfirst($method); if (method_exists($this, $method)) { $this->{$method}($param1, $param2); } else { // method does not exist throw new Wire404Exception(); } } public function executeJson() { echo json_encode(['a' => 1, 'b' => 2]); } Put this inside your init() or ready() method in your module to relay the request to specific functions.
    2 points
  5. @rick: In your code that handles the form input, you simply can call the module or public module method: //if(<condition for form was posted>) { $myModule = $modules->get("MyModulesName"); // get a module handle $myModule->passNewDataIn($input->post->someData); // call the public method for data input // rest is done in modules method, ... // if you are not in template scope, you can use $myModule = wire("modules")->get("MyModulesName"); //}
    2 points
  6. this is wonderful news, thank you. here are the official docs https://github.com/github/linguist#overrides
    2 points
  7. You can use this hook to remove Settings tab from page edit pages <?php wire()->addHook('ProcessPageEdit::buildFormSettings', function (HookEvent $e) { // get the page currently being edited $page = $e->object->getPage(); // check its template if($page->template->name !== 'some-template') return; // remove settings tab $e->object->removeTab('ProcessPageEditSettings') })
    2 points
  8. I am not sure you can access Process modules (pages with admin template) as a guest. If you need to know what page the request is sent to, and perform operations depending on the page, or need some functionality from other autoload modules, then you'd do your checks under ready() function. If you don't, then both init() and ready() is fine. To intercept the requests, you can create a new template called api in your install() function (and remove in uninstall() function), then set it to accept urlSegments (as many as you want), then create a page with that template under root page, then inside your module check if request is made to that page and to that specific urlSegment. Optionally return 404 for all other urlSegments you're not interested in like this <?php $method = $this->sanitizer->alpha($this->input->urlSegment1); if(!$method) return; if (method_exists($this, $method)) { $this->{$method}($param1, $param2); } else { // method does not exist throw new Wire404Exception(); } You can build such a module like this <form action="/api/sendmail"> ... </form> <?php namespace ProcessWire; class MyModule extends Wire implements Module { public static function getModuleInfo () { return [ // ... 'autoload' => true // ... ] } public function ready() { if ($this->wire()->input->requestMethod() === 'POST') { // perform other checks if($this->input->url !== '/api/sendmail') return; // this is the request we should be intercepting $data = $this->wire()->input->post; $name = $this->sanitizer->text($data->name); $email = $this->sanitizer->email($data->name); if($this->sendMail($name, $email)) { // email sent successfully } else { // email failed } } } public function sendMail($name, $email) { $mailer = $this->wire()->mail; // check if any mail is sent successfully return 0 < $mailer->send( 'test@example.com', // to address 'pw@myhost.com', // from address 'Test post, please ignore', // subject 'Hey there, this is a test mail' ); } }
    2 points
  9. Hi, absolutely possible. My thoughts about your points - just some recommendations and very rough ideas: Front end member registration, password retrieval, etc. You may want to check out this: http://modules.processwire.com/modules/frontend-user/ Though I have never used it before. It is quite easy to build your own registration process (once you get the idea how PW works) Regarding this, and regarding everything else, this is a must read I think: Also: Front end thread creation by all members (I assume each new thread would be a separate "page") I would add something like a user role "member". These users are allowed to create threads and post. Then, I think I would only go with one datatype (template) for all the posts. Give them a page-reference field "reply_to". If the field is empty - it is the beginning of a thread. Otherwise you will have a handy reference to the preceding post. Also a page reference like "initial_thread_post" which always references the beginning of a thread could be handy to easily group the posts in threads. Some inspiration: <?php // get the beginning of a thrad $pages->get("template=post, initial_thread_post=$threadNameOrId, reply_to=''"); // find all items of a thread $pages->find("template=post, initial_thread_post=$threadNameOrId"); Front end member profile editing Yep. Just a page / template with that ability. See "Create simple forms using API". Picture upload required to create each new thread About picture upload: Google it, I think it has been asked here before. "required" - absolutely possible. Picture upload optional on all subsequent comments inside a thread Sure. Front end post and comment uploads restricted to images only – .jpg, .gif, .png Sure. Appropriate security to prevent uploading malicious files disguised as images Hm - complex topic I guess, not necessarily related to processwire? https://www.owasp.org/index.php/Unrestricted_File_Upload Optional tagging of each thread as it's being created Automatic SEF urls created based on the thread title ( e.g. http://site.com/forum/title-of-my-thread-12345 -or- http://site.com/forum/12345/this-is-title-of-my-thread ) Already kinda processwires default! : ) You also can change the name of a page (will be the url name) to anything you like. See "Create Pages using API" Sitewide search feature Look it up here in the forums / on the site. There is at least one thread and / or one tutorial! Happy coding
    2 points
  10. Holy __insert-term-of-choice__ This works absolutely great! I replaced stuff on hundreds of pages with textareas of type text and teatareas with CKE and didn't encouter one error! Without BCE and the replace admin action this whole untertaking of migrating to PW wouldn't work at all! I can't thank you enough.
    2 points
  11. No problem - I'm used to it I am away next week, so it's now or not for a while. I have committed a quick update that should take care of Profields Textareas. Please let me know if you have any problems. I really need to revisit this action and add support for other field types as well - for example I haven't tested inside repeaters or page tables. I'll add this to my list, but might be a while.
    2 points
  12. Hi everyone, Here's a new module that I have been meaning to build for a long time. http://modules.processwire.com/modules/process-admin-actions/ https://github.com/adrianbj/ProcessAdminActions What does it do? Do you have a bunch of admin snippets laying around, or do you recreate from them from scratch every time you need them, or do you try to find where you saw them in the forums, or on the ProcessWire Recipes site? Admin Actions lets you quickly create actions in the admin that you can use over and over and even make available to your site editors (permissions for each action are assigned to roles separately so you have full control over who has access to which actions). Included Actions It comes bundled with several actions and I will be adding more over time (and hopefully I'll get some PRs from you guys too). You can browse and sort and if you have @tpr's Admin on Steroid's datatables filter feature, you can even filter based on the content of all columns. The headliner action included with the module is: PageTable To RepeaterMatrix which fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. This is a huge timesaver if you have an existing site that makes heavy use of PageTable fields and you would like to give the clients the improved interface of RepeaterMatrix. Copy Content To Other Field This action copies the content from one field to another field on all pages that use the selected template. Copy Field Content To Other Page Copies the content from a field on one page to the same field on another page. Copy Repeater Items To Other Page Add the items from a Repeater field on one page to the same field on another page. Copy Table Field Rows To Other Page Add the rows from a Table field on one page to the same field on another page. Create Users Batcher Allows you to batch create users. This module requires the Email New User module and it should be configured to generate a password automatically. Delete Unused Fields Deletes fields that are not used by any templates. Delete Unused Templates Deletes templates that are not used by any pages. Email Batcher Lets you email multiple addresses at once. Field Set Or Search And Replace Set field values, or search and replace text in field values from a filtered selection of pages and fields. FTP Files to Page Add files/images from a folder to a selected page. Page Active Languages Batcher Lets you enable or disable active status of multiple languages on multiple pages at once. Page Manipulator Uses an InputfieldSelector to query pages and then allows batch actions on the matched pages. Page Table To Repeater Matrix Fully converts an existing (and populated) PageTable field to either a Repeater or RepeaterMatrix field. Template Fields Batcher Lets you add or remove multiple fields from multiple templates at once. Template Roles Batcher Lets you add or remove access permissions, for multiple roles and multiple templates at once. User Roles Permissions Batcher Lets you add or remove permissions for multiple roles, or roles for multiple users at once. Creating a New Action If you create a new action that you think others would find useful, please add it to the actions subfolder of this module and submit a PR. If you think it is only useful for you, place it in /site/templates/AdminActions/ so that it doesn't get lost on module updates. A new action file can be as simple as this: <?php namespace ProcessWire; class UnpublishAboutPage extends ProcessAdminActions { protected function executeAction() { $p = $this->pages->get('/about/'); $p->addStatus(Page::statusUnpublished); $p->save(); return true; } } Each action: class must extend "ProcessAdminActions" and the filename must match the class name and end in ".action.php" like: UnpublishAboutPage.action.php the action method must be: executeAction() As you can see there are only a few lines needed to wrap the actual API call, so it's really worth the small extra effort to make an action. Obviously that example action is not very useful. Here is another more useful one that is included with the module. It includes $description, $notes, and $author variables which are used in the module table selector interface. It also makes use of the defineOptions() method which builds the input fields used to gather the required options before running the action. <?php namespace ProcessWire; class DeleteUnusedFields extends ProcessAdminActions { protected $description = 'Deletes fields that are not used by any templates.'; protected $notes = 'Shows a list of unused fields with checkboxes to select those to delete.'; protected $author = 'Adrian Jones'; protected $authorLinks = array( 'pwforum' => '985-adrian', 'pwdirectory' => 'adrian-jones', 'github' => 'adrianbj', ); protected function defineOptions() { $fieldOptions = array(); foreach($this->fields as $field) { if ($field->flags & Field::flagSystem || $field->flags & Field::flagPermanent) continue; if(count($field->getFieldgroups()) === 0) $fieldOptions[$field->id] = $field->label ? $field->label . ' (' . $field->name . ')' : $field->name; } return array( array( 'name' => 'fields', 'label' => 'Fields', 'description' => 'Select the fields you want to delete', 'notes' => 'Note that all fields listed are not used by any templates and should therefore be safe to delete', 'type' => 'checkboxes', 'options' => $fieldOptions, 'required' => true ) ); } protected function executeAction($options) { $count = 0; foreach($options['fields'] as $field) { $f = $this->fields->get($field); $this->fields->delete($f); $count++; } $this->successMessage = $count . ' field' . _n('', 's', $count) . ' ' . _n('was', 'were', $count) . ' successfully deleted'; return true; } } This defineOptions() method builds input fields that look like this: Finally we use $options array in the executeAction() method to get the values entered into those options fields to run the API script to remove the checked fields. There is one additional method that I didn't outline called: checkRequirements() - you can see it in action in the PageTableToRepeaterMatrix action. You can use this to prevent the action from running if certain requirements are not met. At the end of the executeAction() method you can populate $this->successMessage, or $this->failureMessage which will be returned after the action has finished. Populating options via URL parameters You can also populate the option parameters via URL parameters. You should split multiple values with a “|” character. You can either just pre-populate options: http://mysite.dev/processwire/setup/admin-actions/options?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add or you can execute immediately: http://mysite.dev/processwire/setup/admin-actions/execute?action=TemplateFieldsBatcher&templates=29|56&fields=219&addOrRemove=add Note the “options” vs “execute” as the last path before the parameters. Automatic Backup / Restore Before any action is executed, a full database backup is automatically made. You have a few options to run a restore if needed: Follow the Restore link that is presented after an action completes Use the "Restore" submenu: Setup > Admin Actions > Restore Move the restoredb.php file from the /site/assets/cache/AdminActions/ folder to the root of your site and load in the browser Manually restore using the AdminActionsBackup.sql file in the /site/assets/cache/AdminActions/ folder I think all these features make it very easy to create custom admin data manipulation methods that can be shared with others and executed using a simple interface without needing to build a full Process Module custom interface from scratch. I also hope it will reduce the barriers for new ProcessWire users to create custom admin functionality. Please let me know what you think, especially if you have ideas for improving the interface, or the way actions are defined.
    1 point
  13. This module allows you to automatically send an email to a newly created user with their username and password. It also has the option to automatically generate a password for the user upon creation. http://modules.processwire.com/modules/email-new-user/ https://github.com/adrianbj/EmailNewUser The following things are configurable: Whether Send Email option should be automatically checked when creating new user - also affects new users created via API From email address (if left blank it will use the admin email set in the config/php file Email subject Email body - includes the ability to use any fields from the user template using {field_name} codes so these can be put into the body wherever you want. It's your choice if you want to include the password in the email or not. Whether to automatically generate a password. This can be toggled on/off, but even if it is on, you can override it by simply entering a password manually when creating the new user. Ability to control the length and character sets used to make up the automatically generated password. Option to send a test email to yourself to make sure it is configured the way you expect. Because it is generally not a good idea to email passwords, it is highly recommended to use the new Password Force Change module in conjunction with this module. That way the user has to change their password the first time they login which will somewhat reduce the vulnerability of emailing the password. It can also be used for API generated users: $modules->get("EmailNewUser"); // call the module since it is not autoload on the front end $newuser = new User(); $newuser->name = 'newuser'; $newuser->email = 'newuser@gmail.com'; $newuser->sendEmail = true; // only needed if Automatic Email Send is unchecked $newuser->save(); Please let me know if you have any ideas for improvements. PS Thanks to everyone in this post: https://processwire.com/talk/topic/2981-new-user-welcome-message/ for their thoughts and ideas on how to do this.
    1 point
  14. Recipes website: http://superpola.com Modules Used: ProCache ProcessImageMinimize / minimize.pw Batcher AIOM
    1 point
  15. This topic has some useful links on building custom button/command
    1 point
  16. My module (https://processwire.com/talk/topic/9496-restrict-tab-view/) mentioned above still works fine in PW 3 if that's helpful for you.
    1 point
  17. You are correct that process modules should be restricted to back-end use. It was my mistake for using that example and applying it to front-end use. I am not writing any process modules, though. I believe I have enough to continue converting my olden-days code to use in ProcessWire. I understand your URL segment example, too. I'm sure I will make use of it soon. Thank you for your help.
    1 point
  18. Hi @abdus, @horst Thanks for your replies. abdus, If I understand you correctly, ProcessWire has it's own set of "magic functions" relating to module classes similar to how it automatically handles template files, such as <code>init.php</code> and <code>ready.php</code>, where init() and ready() are automatically executed within a module if present. In Ryan's module, ImportPagesCSV, it appears that module functions are automatically executed based on URL segments (which are not defined in a template): Maybe I am making things far more complicated than they really are, which is highly likely, but this is the basis of my confusion. Information like what you both have posted needs to be documented somewhere so it's easy to find. Thank you both for your replies.
    1 point
  19. Jean Luc, Thank you for the prompt reply, commenting out line 14 did the trick, removed the error and the module is now fully functional in Processwire 3.0.42. Kind regards, Erik van Berkum
    1 point
  20. @Karl_T, @seddass you should both have collaborator invitations in a moment or two.
    1 point
  21. Actually, I've managed to come up with a very elegant solution now, and would like to share it. I've added a Page field (multiple options) to the template (for the pages that have lists of pages on them). Then I added the following code to the template file: $stories = $page->children(); if ($page->pageimport) { $stories->append($page->pageimport); } $stories = $stories->sort("name"); pageimport is the name of the Page field I mentioned above. Now you can select pages that you want to import and display as 'fake' children of other pages.
    1 point
  22. Thanks for the input. I found another solution though, so I thought I'd share it. $stories = $page->children("sort=-date"); $stories->append($pages->get("/thrillers/")->find("template=horrorthriller")); It may not be optimal, but it's short and it works
    1 point
  23. Okey, I see. From sanitizer docs: * Modules may also add methods to the Sanitizer as needed i.e. $this->sanitizer->addHook('myMethod', $myClass, 'myMethod'); So you can add custom sanitizer method and then hook __construct method of InputfieldName and set your custom method for some pages https://github.com/processwire/processwire/blob/master/wire/modules/Inputfield/InputfieldName.module#L19
    1 point
  24. Hello Vikestart, for that you can use "tags". To create "tags" there are many options and here is one: 1) create template "tags" 2) create template "tag" with only deafult field "title" 3) create field "tags", type page ( my suggestion is to use Lostkobrakai module Chosen Select ), and add it to "movie" template *** note: for page field "tags" set as parent page "Tags" (example below) As example here is some page tree: - Home - About Us - Movies --- Horror ------ Some Horror Movie (eg. template "movie" with your custom fields - and one is field "tags" (3.) ) --- Thriller ------ Some Thriller Movie ( -//- -//- -//- ) - Contact - Tags ( template: "tags", page/settings: hidden ) --- Horror (template: "tag") --- Thriller (-//-) --- Scifi --- etc After that inside movies set "tags" for every movie (one or multiple tags per movie). 1) Here is example how to get Some Horror-Thriller inside your category Thriller's: // on page "Thriller" $search_term = $sanitizer->text($page->title); // thriller $items = $pages->find("tags.title%=$search_term, sort=-sort"); // here you can add more precious filters... 2) You have some "Tags Cloud" widget (eg. in some sidebar) <?php // tags cloud $tags = $pages->find("template=tag, include=all");// include=all because of hidden parent ?> <div class="widget tags-cloud"> <?php foreach($tags as $tag): ?> <a href="<?php echo $tag->url;?>"><?php echo $tag->title;?></a> <?php endforeach; ?> </div> Maybe links inside "tags-cloud" are little confused, eg. "my-website.com/tags/horror" but that's part will be more clear if you watch main part inside tag.php and tags.php templates (below): // tag.php $search_term = $sanitizer->text($page->title); $items = $pages->find("tags.title%=$search_term, sort=-sort"); // tags.php $tags = $pages->find("template=tag"); $items = $pages->find("tags=$tags, sort=tags.title"); regards p.s. this principle is used here on some of my testing website (at sidebar column is tags-cloud widget)
    1 point
  25. Here's how you might dynamically create it with ProcessWire without tinkering with .htaccess files. Create a new template, call it robots, and set its URLs > Should page URLs end with a slash setting to no, and Files > Content-Type to text/plain. You should tick disable Append file and Prepend file options as well. Optionally set its Family > May this page have children to no, and Family > Can this template be used for new pages to one. Family > Optionally Set allowed templates for parents to home only. Create a new page under homepage, set its template to robots, and name as robots.txt. Create a new template file at /site/templates/robots.php, inside it you type <?php namespace Processwire; // render different robots.txt depending on your own conditions. if ($config->debug) { // use PHP_EOL to create multiline strings echo <<<PHP_EOL User-agent: * Disallow: / PHP_EOL; } else { echo <<<PHP_EOL User-agent: * Disallow: PHP_EOL; } and done. You should be able to see robots.txt at the url /robots.txt.
    1 point
  26. Thanks for your points. It indeed makes less difference for low traffic site where shared hosting is the common choice. I always use cheap VPS plan in DigitalOcean or Linode to gain the largest control for less money so I forgot about shared hosting for long..
    1 point
  27. Hello, If you use this module, you may be interested by my fork https://github.com/jlj/MarkupTwitterFeed, that adds the following features to the official MarkupTweeterFeed module: support of the recent Twitter extended tweet format (tweets longer than 140 chars); support of emoji characters in tweets; display of image in a tweet (only the first image is displayed in the curent version); display of video in a tweet (with a html5 video markup); for retweets, display of the original author and avatar in the tweet. Also, it allows a more flexible per-item rendering, as in the following example: $t = $modules->get('MarkupTwitterFeed'); $t->limit = 10; $renderOptions = array( 'showDate' => 'before, after', 'dateFormat' => __("M j, Y"), // Tweet block date format 'listItemOpen' => "\n\t<div class='tweet-item'>", 'listItemClose' => "</div>", 'listItemText' => "<i class='fa fa-twitter'></i> <span class='tweet-text'>{text}</span>", 'listItemDate' => " <div class='date'><i class='fa fa-calendar'></i> {date}</div>", 'listItemLink' => "<a rel='nofollow' href='{href}'>{url}</a>", 'videoAttributes' => "autoplay loop muted", 'preserveLineBreaks' => 'coalesce', ); foreach($t as $tweet) { echo $t->renderItem($tweet, $renderOptions); } Examples from my website: This module has been tested with pw 2.7.2 only, so I cannot guarantee the proper working with 3.0… Hope this will be useful for others here.
    1 point
  28. Just pushed some updates to this ancient module. The new version (v1.2.0) uses wireMail and should work with PW 3.
    1 point
  29. Not sure why this hasn't been mentioned, so I am wondering if I am missing something relevant, but why not use the $template->noSettings option? Do you need to hide on a page basis, rather than per template? Anyway, if it suits your needs, turn on advanced mode in your config.php file and then you will have a Disable Settings Tab? option on the Template's System Tab. Hope that might help.
    1 point
  30. @mrkhan: There have been changes in ProcessPageEdit recently. The tabs need to be deleted manually. The code below works in 2.5.25 (dev). (don't know if thats the case for 2.5 and if so could you report this back) function removeSettings(HookEvent $event){ // check what role the user has, if not has editor role do nothing if(!wire("user")->hasRole("webmaster")) return; // $event->return being the inputfield wrapper $wrapper = $event->return; // set the inputfield wrapper to hidden $wrapper->collapsed = Inputfield::collapsedHidden; // Get the active Object (ProcessPageEdit) $process = $event->object; // Remove the Settings tab with the ID $process->removeTab('ProcessPageEditSettings'); // we're done }
    1 point
  31. Here's an example module that removes "Add New" button(s) on InputfieldPageTable on a condition (here if there's 2 ore more entries). Hook before InputfieldPageTable::render, then add hook after InputfieldButton::render. Since InputfieldButton is used by PageTable, we just use that hook to empty the returned markup for the button. Then remove that button hook after the InputfieldPageTable rendered. https://gist.github.com/somatonic/c9db5c43f10d050bb14d
    1 point
  32. Thanks adrian, not only for this new module but also for your abundant supporting posts and contributions in this forum.
    1 point
  33. Limiting by IP or cookie both have their drawbacks. You can imagine an office with 100 workers all behind one ip address. Cookies can also be deleted. For my needs the implementation is good enough, but if you really wanted to prevent bots taking advantage you'd require users to be logged in to vote. That being said the voted detection could be a lot more sophisticated.
    1 point
×
×
  • Create New...