Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 04/07/2015 in all areas

  1. Big update! Version 0.3.0 comes with: a new "NewCommand" provided by HariKT! Big thanks again. This contribution should lead to a better workflow with Wireshell since it opens up the possibility to install PW via command line in a convenient way A command for creating fields A command for assigning fields to existing templates A generic backup command (DB dump) Commands for en/disabling modules (downloading them via Wireshell is still on my bucket list) A little command outputting the currently installed ProcessWire version An unified approach to naming commands and classes: entity:verb, so for example user:create I dropped the "(Experimental)" from the topic's title Read more about the available new commands and their options in the readme. If you have an older version of Wireshell installed, make sure you "$ composer update" it in order to get the new dependencies. And we're on packagist now: https://packagist.org/packages/wireshell/wireshell
    5 points
  2. I've known people in large organisations (not saying which) turn down quotes because the price seemed suspiciously low. No follow-up discussion to ask why it was low, just discarded the quote in favour of a higher one.
    4 points
  3. Not hard at all - fun, as I'm dealing with amazing tools (ProcessWire, Symfony, Composer packages) and learn a lot on the way
    4 points
  4. A whole lot of people are paying a whole lot of money for things they don't need / shouldn't be using / could do better for less. Conversely there are an awful lot of excellent designers and developers who struggle for work / money. A lot depends on who you target / how you sell it and how lucky you are.
    4 points
  5. Ah, figured it out. For some reason, I set the cache on the admin template instead of another template... No idea how I did that. Must have just clicked on the wrong template and not noticed which one I was editing.
    3 points
  6. I've never seen a Hello World in the Form Builder. Maybe you could grep "Hello world" in the Form Builder files or in your /site/templates/ files to see where it is coming from?
    2 points
  7. Money is relative and mostly in perspective of what they can spend. I feel my wallet when refuelling the car others don't care to refuel an oil tanker.
    2 points
  8. Repeaters are not officially supported by inputfield dependencies.
    2 points
  9. Thanks! The idea behind backup:db is that backup is the entity/namespace, and you can specify: :db for database :files for /site/assets/files :scripts for all scripts (/site + /wire + root files) :all for :scripts + :db
    2 points
  10. So I got it worked out thanks to my friend, he directed me to this post https://processwire.com/talk/topic/648-storing-module-config-using-api/ I just added this line: $data = wire('modules')->getModuleConfigData('ModuleClassName'); to the top of the getModuleConfigInputfields(array $data) method and it worked. I called the variables using $this->permalinkURL and $this->membersPath. I'm leaving this up in case anyone else has similar issues. Thanks again to all who took time to look at it.
    2 points
  11. @Mike Anthony, thanks for pointing that out. It was implemented but got lost in refactoring. I fixed that in the latest commit. You now can set it on the asset type level: 'jsAppendNewLine' => true, 'cssAppendNewLine' => true, 'imgAppendNewLine' => true,
    2 points
  12. A friend of mine asked me to build a website for the dog training business she just started. She already had a graphic designer create a logo and a small print brochure and wanted a clean, simple website. www.hundeschule-grosse-freiheit.de is the result. The website is neither big nor fancy. But it has some nice details: Responsive, lazy loading images Almost all images (except the SVGs and the badge image in the footer) are maintained via the ProcessWire backend. Each image is rendered in eight different sizes – using respimage and lazysizes for frontend display. All images are created using the great ImageFocusArea module – something I wanted to be able to use in ProcessWire since I first worked with Drupal’s “ImageField Focus” module. Of course all images are minified using minimize.pw. Central asset management for images Because most of the decorative images are used on more than one page, it made sense to build a central image management – using a specific “settings” part of the page tree with one page per image. Images in sidebars or on the gallery page are chosen using page fields in combination with the Page List Image Label module: So an editor’s experience regarding the visual representation of the “linked” images is not so much different from working with default image fields. Consequent usage of a cookieless subdomain for static content. The cookieless subdomain specified in the AIOM+ module’s setting is also used to deliver images. Multi-language content. Nothing big, but my first ProcessWire site with more than one language. Of course it uses the Autodetect Language module for the homepage – as well as “hreflang” links in each page’s head to give Google as much language information as possible. Feedback and ratings The feedback page, which features quotes and pictures of happy clients, is populated semi-automatically. Feedback is collected using a Form Builder form on a secret page. After a training has ended the site owner sends an email to clients, thanking them for taking part and asking them for their feedback with a link to the secret form page. Clients can enter a quote, a 5-star rating and optionally an image – as well as their permission to use the quote and the image (necessary to avoid legal problems). This information is saved as a new unpublished page. After a new feedback entry page is published by the site owner, the new entry is displayed on the main feedback page. The pages used to save feedback entries feature multi-language fields. So it’s possible to present all testimonial quotes in both languages. The footer of each page features an aggregated 5-star rating, calculated from all single ratings displayed on the feedback page. Each individual feedback entry on the feedback page as well as the aggregated rating are formated using Schema.org markup. So it can be read and understood by Google and thus has the potential to be displayed as rich snippet on Google result pages. Oh by the way: The decision to use email links rather than a contact form was made by the site owner.
    1 point
  13. Since I've been working on a few projects where I used Bootstrap 3 and will be using it for future projects, I put together a blank site profile with Bootstrap 3 Sass, Fontawesome and a few markup render functions for Bootstrap dropdown menu, image carousel and accordion. You can find it at https://github.com/gebeer/site-pwbs Features bootstrap-sass-official font-awesome SASS version jquery modernizr render functions for:BS3 dropdown menu BS3 accordion from PageArray BS3 carousel from PW images array Prerequisites compass bower How to install from zip: download the zip extract the folder "site-pwbs" into a clean ProcessWire install's root folder during install of ProcessWire choose the profile "bootstrap-sass-official fontawesome blank profile" After installation The last step after installing the profile is to install all assets with bower: open a terminal in site/templates and execute "bower install" How it works The profile is based on the blank site profile that comes with PW 2.5 and uses the delegate template approach. It comes with a top navbar, a main container and a footer section. Rest is up to you. CSS gets compiled through compass. You can easily override BS variables and exclude BS components that you don't need. I intentionally did not add structure to the sass folder so you can structure your partials yourself as you please. There is only one folder "generic" with _mixins.scss whith a very lean and flexible breakpoint mixin that I discovered here. JS Since I only use the BS javascript plugins I really need, I usually copy them over to my plugins.js file. I use bower to install bootstrap-sass-original and fontawesome because it gives more flexibility than requiring them through ruby gems. This way you can tweak the BS and FA partials to your liking (of course only if you don't intend to do "bower update" further down the road) Enjoy!
    1 point
  14. I write a login / register module. Basic login / logout / register works fine. Also a simple PersistLogin and ProcessForgotPassword integration. https://processwire.com/talk/topic/8001-frontenduserlogin/?p=92083 Testing repo: https://bitbucket.org/pwFoo/frontenduser/overview Requires FormHelper module testing branch: https://bitbucket.org/pwFoo/formhelper/src/baa9fc92d08103775626ed931e1b6af02bbb8cba/?at=testing InputfieldText as password field from my module. protected function password() { $field = $this->modules->get('InputfieldText'); $field->skipLabel = 4; // Inputfield::skipLabelBlank; $field->placeholder = $this->_('Password'); $field->attr('id+name', 'password'); $field->attr('type','password'); $field->required = 1; return $field; }
    1 point
  15. Hey Joss - I think the issue is more about refreshing the modules cache in general which probably happens when you update another module. That error with PageEditFieldPermissionConfig is actually a bit painful - if you upgraded PW to latest dev before upgrading the module it becomes quite difficult to get rid of that error because you can't actually upgrade the module to the latest version that fixes it. You might need to manually uninstall it, then reinstall - at least that was my experience.
    1 point
  16. I need several fields that will be calculated at runtime like Concat but (a) based on PHP code (b) it should be visible & locked in admin UI. I'd also use this filed in custom Listers. Example - "total price" which is calculated based on some logic and fields inside "order" page as well as fields outside of the page. Should I develop new Fieldtype? Or there is something ready to use in PW 2.5?
    1 point
  17. If you like you can write me a PM in german - to clear open questions. Welcome to processwire forum - be not afraid - asking for help here.
    1 point
  18. Marcus, this looks fantastic, thanks for all your hard work!
    1 point
  19. Hey, thanks for taking the time to read! So I'm new to module development and I'm having trouble understanding how to pass data in my module. The module I am making extends process and implements ConfigurableModule.( A lot of the module aspect of the code is copied from other modules.) It's purpose is to download a report that contains a list of people from a permalink and then parse and create a page for each person on the list. That part works fine, if I just run it as a script or hard code the default values into my module. What I am having a hard time understanding is how do I access the fields that are in the module via the admin page interface? I can't seem to actually get a hold of the data that is saved in the two fields of my module. I have my module show up under the setup tab with a submit button and the module itself with the two configurable fields are under site->modules. When I press submit I need it to get the data from the two fields. Is the best way to create global variables in my module?(Which I have tried) Or is there some other preferred way. I really am stumped on how to get it working. My Module: <?php class MemberImporter extends Process implements Module, ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'LGL Members Importer', 'author' => 'Tyler Williams, Sam Fleming', 'summary' => 'Import a list of LGL members who have an active website.', 'version' => .001, 'singular' => true, ); } //Get the module config data protected $data; /** * Name used for the page created in the admin * */ const adminPageName = 'member-importer'; /** * Instance of Template, used for imported pages * */ protected $template = null; /** * Instance of Page, representing the parent Page for imported pages * */ protected $parent = null; protected static $defaults = array( 'permalinkURL' => 'link-removed-for-privacy', 'membersPath' => '/Members' ); protected $link = null; protected $memPath = null; static public function getDefaultData() { return array( 'permalinkURL' => 'link-removed-for-privacy', 'membersPath' => '/Members' ); } public function __construct() { //set defaults foreach(self::getDefaultData() as $key => $value) { $this->$key = $value; } } public function init() { parent::init(); ini_set('auto_detect_line_endings', true); } public static function getModuleConfigInputfields(array $data) { $data = array_merge(self::getDefaultData(), $data); $fields = new InputfieldWrapper(); $head = new InputfieldMarkup; $head->label = __('Member Import Configuration'); $head->description = __('Set the permalink to the LGL report file and set the parent page for the Member Profiles'); $fields->add($head); //permalink url for report $field = wire('modules')->get('InputfieldText'); $field->attr('name', 'permalinkURL'); $field->attr('value', $data['permalinkURL']); $field->label = "The permalink URL that downloads the LGL report"; $fields->add($field); //members parent page $field = wire('modules')->get('InputfieldPageListSelect'); $field->attr('name', 'membersPath'); $field->attr('value', $data['membersPath']); $field->label = "Path to Members' profiles"; $fields->add($field); return $fields; } public function getConfig(){ return ($this->get($key)) ? $this->get($key) : self::$defaults[$key]; } protected function getInstalledPage() { $admin = $this->pages->get($this->config->adminRootPageID); $parent = $admin->child("name=setup"); if(!$parent->id) $parent = $admin; $page = $parent->child("name=" . self::adminPageName); if(!$page->id) { $page = new Page(); $page->parent = $parent; $page->template = $this->templates->get('admin'); $page->name = self::adminPageName; $page->title = "Member Importer"; $page->process = $this; $page->sort = $parent->numChildren; $page->save(); } return $page; } public function ___execute() { if($this->input->get->import == "Import"){ //run the importer and then redirect back to page tree $this->ImportMembers(); $this->session->redirect(wire('config')->urls->admin); }else{ $form = $this->modules->get("InputfieldForm"); $form->method = 'get'; $form->action = './'; $head = new InputfieldMarkup; $head->label = __('Import Members from Little Green Light'); $head->description = __('Imports members from the LGL Database that have active website URLs. List from LGL is updated daily. Press submit to update the website Members list to match that of the LGL members list.'); $form->add($head); // add submit button $field = $this->modules->get("InputfieldButton"); $field->type = 'submit'; $field->value = 'Import'; $field->name = 'import'; $form->add($field); return $form->render(); } } public function ___ImportMembers(){ $this->ClearAllMemberProfiles(); $this->GetMemberList(); } private function GetMemberList(){ //download the csv report from the permalink $link = $this->getConfig('permalinkURL'); $f = fopen($this->link, 'r'); $members = stream_get_contents($f); fclose($f); $members = str_replace('"','', $members); $rows = explode("\n", $members); array_shift($rows); foreach($rows as $row => $members) { $row_data = explode(',', $members); if(trim($row_data[0]) !=''){ $info[$row]['id'] = trim($row_data[0]); $info[$row]['name'] = trim($row_data[1]) .' '. trim($row_data[2]); $info[$row]['website'] = trim($row_data[3]); } } $this->GenerateMemberProfiles($info, $memPath); } private function GenerateMemberProfiles($info, $memPath){ foreach($info as $mem) { if(!empty($mem['website'])){ $p = new Page(); $p->template = 'member'; $p->parent = $this->getConfig('membersPath'); $p->name = $mem['name']; $p->title =$mem['name']; $p->save(); $p->memID = $mem['id']; $p->memWebsite = $mem['website']; $p->save(); } } } private function ClearAllMemberProfiles(){ $members = wire('pages')->get('/members')->children(); foreach($members as $mem){ wire('pages')->delete($mem, true); } } public function ___install() { wire('modules')->saveModuleConfigData($this, self::getDefaultData()); $p = new Page(); $p->template = $this->templates->get("admin"); $p->parent = $this->pages->get("template=admin, name=setup"); $p->title = $this->_('Member Importer'); $p->name = __CLASS__; $p->process = $this; $p->save(); } public function ___uninstall() { $p = $this->pages->get('template=admin, name=' . __CLASS__); if ($p->id > 0) { $p->delete(); } } } ?> **Updated to reflect current version
    1 point
  20. You should at least know some basic PHP to work with ProcessWire. Take the time to learn the basics about variables, foreach, while and so on. Your site is german so a easy to read and great tutorial documentation in german is from Peter Kropff: http://www.peterkropff.de/site/php/php.htm regards mr-fan
    1 point
  21. you need a template for the single image... in that template you show the single image and prev/next image in your gallery. the simple gallery system don't fit this, but the functions could used. have a look at this example: https://processwire.com/talk/topic/772-image-gallery-v01/#entry6489 there is a singleImage function included that could used: function singleImage(Page $page,$image){ $images = $page->images; $image = $images->get($image); $nextImage = $image->getNext(); $prevImage = $image->getPrev(); $sizedImage = $image->size(900); if($image) return (object) array( next_image => '?img='.$nextImage->name, prev_image => '?img='.$prevImage->name, url => $sizedImage->url, description => $image->description ); } here is a link to prev next image links on a images field/page: https://processwire.com/talk/topic/9144-how-can-i-make-working-links-prev-and-next-arrow-slide-links/#entry88426 and how to use the PW pagination on images from ryan: https://processwire.com/talk/topic/390-images-pagination/#entry2928 regards mr-fan
    1 point
  22. The thing with Windows is that it doesn't automatically pick up the laravel command like *nix can, which is why a batch file needs to be created. However, because your wireshell file is looking for the vendor directory inside it's own, it doesn't work. As such, you'll need to change your request for autoload.php to this (the way Laravel's installer does it): if (file_exists(__DIR__.'/../../autoload.php')) { require __DIR__.'/../../autoload.php'; } else { require __DIR__.'/vendor/autoload.php'; } Then, the user can create a wireshell.bat file in a directory visible to the windows path containing this: @echo off php "%appdata%\Composer\vendor\wireshell\wireshell\wireshell" %* This works on my side. Update: If using mingw32 or cygwin, however, this isn't necessary - it's just a matter of adding %appdata%\Composer\vendor\wireshell\wireshell\wireshell to the path.
    1 point
  23. Hi everybody, First of all: Thanks to everybody for keeping the community alive. Every time I search for something in the forum I find the solution. Great work! I wanted to share a small module with you / my first one. I use it in order to switch the user language on page load. Processwire GeoInfo GeoInfo is a small module that Implements Geoplugin PHP web service. Please donate to "geoplugin.com" in order to keep the service alive. The Module ads two methods to retrieve data from the web service. $page->GeoInfoIP('IP ADDRESS'); you can enter the ip address manually. If left blank the server remote address will be used. The retrieved data is then stored to the active session, in order to limit the requests. The web service gives back following data. 'geoplugin_request' 'geoplugin_status' 'geoplugin_credit' 'geoplugin_city' 'geoplugin_region' 'geoplugin_areaCode' 'geoplugin_dmaCode' 'geoplugin_countryCode' 'geoplugin_countryName' 'geoplugin_continentCode' 'geoplugin_latitude' 'geoplugin_longitude' 'geoplugin_regionCode' 'geoplugin_regionName' 'geoplugin_currencyCode' 'geoplugin_currencySymbol' 'geoplugin_currencySymbol_UTF8' 'geoplugin_currencyConverter' for e.g. $page->GeoInfoIP('IP ADDRESS')->geoplugin_countryCode; will give back the country iso code. $page->GeoInfoLatLong('LAT', 'LONG'); Enter Latitude and Longitude in order to get following information: 'geoplugin_place' 'geoplugin_countryCode' 'geoplugin_region' 'geoplugin_regionAbbreviated' 'geoplugin_latitude' 'geoplugin_longitude' 'geoplugin_distanceMiles' 'geoplugin_distanceKilometers' for e.g. $page->GeoInfoLatLong('40.712784', '-74.005941'); will give back the city name "New York City". Todo store places in json file / check if place exists implement nearby "service" https://bitbucket.org/pmichaelis/processwire-geoinfo
    1 point
  24. I did try deleting it anyway and it started to work again! So if nothing helps try this brutal solution))
    1 point
  25. I wanted to go for the regular user but it didn't make sense for me to do so, as I didn't want to want users in the backend, also as for my solution we already imported the users into pages with password so it was obvious taking the regular route was too late so what i did, was create a login that checks the pages for password. I created a Hook to change the layout to my Admin Backend and i was able to get an admin interface I simply used the Session to store the user id and once its gone it redirects to the login page. Also for the backend i created a Class to parse the Url Segment and call a similar method in a controller e.g url1 is always the controller and url2 is the action and I default to a controller and an action. This works well for me as an AVID MVC adopter so its hard for me to change my pattern which is why i like PW it allows me create a flexible system.
    1 point
  26. I'm interested learning more, do you have specs? Here's something I'm working on now, it showcases my skills w/ PW.
    1 point
  27. I'll make this quick since these are pretty boring given the fact that in both cases, the original design was not done by me but is based on print designs originally intended for flyers. Both sites actually belong to the same client, a local non-profit organization providing help and counceling for women (abuse, domestic violence, mobbing, stalking but also pregnancy, divorce etc.). Both sites used to be static pages (both technically and design-wise), they have now been upgraded to responsive designs powered by PW. frauennotruf-oh.de (the main site of the organization) maedchenberatung-in-oh.de (a one-pager tailored to girls and young women who prefer counceling via email) The most remarkable part was (once again, I might add) how easy it can be to convey using a CMS with PW. None of the client's editors had ever worked with a CMS before, yet we still managed to get the CMS training done in 90 minutes for both sites. Everyone was pretty surprised how easy it can be to manage your own website with PW.
    1 point
  28. Latest update to my local testing branch... Moved totally from custom callbacks to PW hooks (core and module own hookable methods) Have a working minimal FrontendUserLogin and FrontendUserRegister module. Added FormHelper dependency again (instead of a extended wrapper FormHelper is changed to extend InputfieldForm object) FrontendUserLogin / FrontendUserRegister (simple use) // login echo $modules->get('FrontendUserLogin')->render($redirectAfterLogin); // register echo $modules->get('FrontendUserRegister')->render($redirectAfterRegister); The method render() is a shortcut. Long form with chance to modify parameters, form, ... $fu->form(); $fu->validate(); $fu->process($redirect); $fu->renderForm(); How to add plugins? After $fu->form() define the plugin field and needed processing validation code as a PW hook RememberMe plugin to integrate LoginPersist module // RememberMe field / persistLogin integration $remember = $modules->get('InputfieldCheckboxes'); $remember->name = 'persist'; $remember->attr('id+name', 'persist'); $remember->skipLabel = 4; $remember->addoption('persist', 'Remember me?'); $remember->addHookAfter('processInput', function($event) { $field = $event->object; if (isset($field->value[0]) && $field->value[0] === 'persist') { wire()->addHookAfter('Session::login', function($event) { wire('modules')->get('LoginPersist')->persist(); }); } }); $fu->attr('form')->add($remember); Or an integration of core module ProcessForgotPassword // ForgotPassword integration $forgot = $modules->get('InputfieldMarkup'); $forgot->value = "<a href='{$page->url}?forgot=1'>{$this->_('Forgot password?')}</a>"; $fu->attr('form')->add($forgot); if ($input->get->forgot) { function processForgot($event) { wire('config')->styles->add('/pw/wire/modules/AdminTheme/AdminThemeDefault/styles/main-classic.css'); $event->return = wire('modules')->get('ProcessForgotPassword')->execute(); $event->replace = true; } $fu->addHookBefore('FrontendUserLogin::login', null, 'processForgot'); } Login with email address instead of username? // Email login instead of username $fieldUser = $fu->attr('form')->get('username'); $fieldUser->addHookBefore('FrontendUserLogin::auth', function($event) { $fu = $event->object; $email = $fu->attr('form')->fhValue('username', 'email'); $loginUser = wire('users')->get("email={$email}"); if ($loginUser instanceof User && !$loginUser->isGuest()) { $event->arguments(0, $loginUser->name); } }); You have added a nickname field to user template? The plugin to use the nickname (sanitized text instead of username) to login // Nickname login instead of username $fieldUser = $fu->attr('form')->get('username'); $fieldUser->addHookBefore('FrontendUserLogin::auth', function($event) { $fu = $event->object; $nick = $fu->attr('form')->fhValue('username', 'text'); $loginUser = wire('users')->get("nickname={$nick}"); if ($loginUser instanceof User && !$loginUser->isGuest()) { $event->arguments(0, $loginUser->name); } }); The plugins are tested and working fine, but I don't know how to ship plugins. At the moment it's code inside the template login.php, but should be moved to a separate plugin file or the FrontendUserLogin module... Any suggestions? *Added nickname login plugin and fixed a nickname / email login bug*
    1 point
  29. This is the organization we've put in place at work. The structure is pretty much fixed now, we're still grabbing parts of things we like elsewhere. It's basically a bootstrap kit. Workflow goes at this : 1) clone latest pw and setup project with https://github.com/plauclair/pwscripts 2) clone our site profile 3) remove extra, configure grid or else from less mixins, select which layout to use and import html presets that match these 4) marvel at all the time saved 5) code 6) ?? 7) happy customers, happy devs! templates/ |-- styles/ | |-- styles.less // general styles, calls parts in inc/ | |-- styles.css // compiled from styles.less | |-- inc/ | | |-- layout-one-pager.less // standard layouts | | |-- layout-standard.less | | |-- content.less // regular h1, p, ul, etc.. | | |-- template-name.less // each template has its own less file | | |-- template-...less | | |-- vendor/ // decoupled parts from different frameworks | | |-- bootstrap/ | | |-- grid.less // decoupled grid system, generator w settings | |-- images/ // images called from css | | |-- scripts/ | |-- main.js // main js stuff for global things | |-- vendor/ | |-- vendor-name/ | |-- files... | | |— inc/ // php includes, has ready-made classes like a recursive menu generator and other helpers |-- views, controllers, classes, etc../ // depends on the project's complexity | |-- _header.php | _init.php // config->prepend |-- template-name.php // typical PW template files |-- template-...php
    1 point
  30. There's another method to be able to overwrite created user directly when creating a page. There's a new template setting to allow overwriting the $page->createdUser that you can enable to allow this via API. Then you can do this: $p = new Page(); $p->template = "basic-page"; $p->set("createdUser", wire("users")->get("importer")); $p->title = "Imported page"; $p->save();
    1 point
×
×
  • Create New...