Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 12/12/2018 in all areas

  1. I've been working with ProcessWire for a while now, and I've noticed that using Composer to manage dependencies and autoload external libraries isn't as prevalent in ProcessWire development as in other areas of PHP programming. I started out by using the default setup recommend in this blogpost. However, one major problem I have with this approach is that all external dependencies live in the webroot (the directory the server points to), which is unfavourable from a security standpoint and, in my opinion, just feels a bit messy. In this tutorial, I want to go through a quick setup of Composer and ProcessWire that keeps the dependencies, all custom-written code and other source material outside of the webroot, and makes full usage of the Composer autoloader. This setup is pretty basic, so this tutorial is probably more useful to beginners (this is why I'll also include some general information on Composer), but hopefully everyone can take something away from this for their personal workflow. Site structure after setup This is what the directory structure can look like after the setup: . ├── composer.json ├── composer.lock ├── node_modules │ └── ... ├── public │ ├── index.php │ ├── site │ ├── wire │ └── ... ├── packacke-lock.json ├── package.json ├── sass │ ├── main.scss │ ├── _variables.scss │ └── ... ├── src │ ├── ContentBag.php │ └── ... └── vendor ├── autoload.php ├── composer ├── league ├── symfony └── ... As mentioned, the main point of this setup is to keep all external libraries, all other custom source code and resources out of the webroot. That includes Composer's vendor folder, your node_modules and JavaScript source folder if you are compiling JavaScript with webpack or something similar and including external scripts via NPM, or your CSS preprocessor files if you are using SASS or LESS. In this setup, the public directory acts as the webroot (the directory that is used as the entry point by the server, DocumentRoot in the Apache configuration). So all other files and directories in the mysite folder aren't accessible over the web, even if something goes wrong. One caveat of this setup is that it's not possible to install ProcessWire modules through Composer using the PW Module Installer (see Blogpost above), but that's just a minor inconvenience in my experience. Installation You'll need to have composer installed on your system for this. Installation guides can be found on getcomposer.org. First, open up your shell and navigate to the mysite folder. $ cd /path/to/mysite/ Now, we'll initialize a new Composer project: $ composer init The CLI will ask some questions about your projects. Some hints if you are unsure how to answer the prompts: Package names are in the format <vendor>/<project>, where vendor is your developer handle. I use my Github account, so I'll put moritzlost/mysite (all lowercase). Project type is project if you are creating a website. Author should be in the format Name <email>. Minimum Stability: I prefer stable, this way you only get stable versions of dependencies. License will be proprietary unless you plan on sharing your code under a FOSS license. Answer no to the interactive dependencies prompts. This creates the composer.json file, which will be used to keep track of your dependencies. For now, you only need to run the composer install command to initialize the vendor directory and the autoloader: $ composer install Now it's time to download and install ProcessWire into the public directory: $ git clone https://github.com/processwire/processwire public If you don't use git, you can also download ProcessWire manually. I like to clean up the directory after that: $ cd public $ rm -r .git .gitattributes .gitignore CONTRIBUTING.md LICENSE.TXT README.md Now, setup your development server to point to the /path/to/mysite/public/ directory (mind the public/ at the end!) and install ProcessWire normally. Including & using the autoloader With ProcessWire installed, we need to include the composer autoloader. If you check ProcessWire's index.php file, you'll see that it tries to include the autoloader if present. However, this assumes the vendor folder is inside the webroot, so it won't work in our case. One good place to include the autoloader is using a site hook file. We need the autoloader as early as possible, so we'll use init.php: EDIT: As @horst pointed out, it's much better to put this code inside the config.php file instead, as the autoloader will be included much earlier: // public/site/config.php <?php namespace Processwire; require '../../vendor/autoload.php'; The following also doesn't apply when including the autoloader in the config-file. This has one caveat: Since this file is executed by ProcessWire after all modules had their init methods called, the autoloader will not be available in those. I haven't come across a case where I needed it this early so far; however, if you really need to include the autoloader earlier than that, you could just edit the lines in the index.php file linked above to include the correct autoloader path. In this case, make sure not to overwrite this when you update the core! Now we can finally include external libraries and use them in our code without hassle! I'll give you an example. For one project, I needed to parse URLs and check some properties of the path, host et c. I could use parse_url, however that has a couple of downsides (specifically, it doesn't throw exceptions, but just fails silently). Since I didn't want to write a huge error-prone regex myself, I looked for a package that would help me out. I decided to use this URI parser, since it's included in the PHP League directory, which generally stands for high quality. First, install the dependency (from the project root, the folder your composer.json file lives in): $ composer require league/uri-parser This will download the package into your vendor directory and refresh the autoloader. Now you can just use the package in your own code, and composer will autoload the required class files: // public/site/templates/basic-page.php <?php namespace Processwire; use \League\Uri\Parser; // ... if ($url = $page->get('url')) { $parser = new Parser(); $parsed_url = $parser->parse($url); // do stuff with $parsed_url ... } Wiring up custom classes and code Another topic that I find really useful but often gets overlooked in Composer tutorials is the ability to wire up your own namespace to a folder. So if you want to write some object-oriented code outside of your template files, this gives you an easy way to autoload those using Composer as well. If you look at the tree above, you'll see there's a src/ directory inside the project root, and a ContentBag.php file inside. I want to connect classes in this directory with a custom namespace to be able to have them autoloaded when I use them in my templates. To do this, you need to edit your composer.json file: { "name": "moritzlost/mysite", "type": "project", "license": "proprietary", "authors": [ { "name": "Moritz L'Hoest", "email": "info@herebedragons.world" } ], "minimum-stability": "stable", "require": {}, "autoload": { "psr-4": { "MoritzLost\\MySite\\": "src/" } } } Most of this stuff was added during initialization, for now take note of the autoload information. The syntax is a bit tricky, since you have to escape the namespace seperator (backslash) with another backslash (see the documentation for more information). Also note the PSR-4 key, since that's the standard I use to namespace my classes. The line "MoritzLost\\MySite\\": "src/" tells Composer to look for classes under the namespace \MoritzLost\MySite\ in the src/ directory in my project root. After adding the autoload information, you have to tell composer to refresh the autoloader information: $ composer dump-autoload Now I'm ready to use my classes in my templates. So, if I have this file: // src/ContentBag.php <?php namespace MoritzLost\MySite; class ContentBag { // class stuff } I can now use the ContentBag class freely in my templates without having to include those files manually: // public/site/templates/home.php <?php namespace Processwire; use MoritzLost\MySite\ContentBag; $contentbag = new ContentBag(); // do stuff with contentbag ... Awesome! By the way, in PSR-4, sub-namespaces correspond to folders, so I can put the class MoritzLost\MySite\Stuff\SomeStuff in src/Stuff/SomeStuff.php and it will get autoloaded as well. If you have a lot of classes, you can group them this way. Conclusion With this setup, you are following secure practices and have much flexibility over what you want to include in your project. For example, you can just as well initialize a JavaScript project by typing npm init in the project root. You can also start tracking the source code of your project inside your src/ directory independently of the ProcessWire installation. All in all, you have good seperation of concerns between ProcessWire, external dependencies, your templates and your OOP-code, as well as another level of security should your Server or CGI-handler ever go AWOL. You can also build upon this approach. For example, it's good practice to keep credentials for your database outside the webroot. So you could modify the public/site/config.php file to include a config or .env file in your project root and read the database credentials from there. Anyway, that's the setup I came up with. I'm sure it's not perfect yet; also this tutorial is probably missing some information or isn't detailed enough in some areas depending on your level of experience. Feel free to ask for clarification, and to point out the things I got wrong. I like to learn as well ? Thanks for making it all the way to the bottom. Cheers!
    7 points
  2. Just to clarify the bit about "putting stuff outside the webroot" for security reasons: This is certainly a nice precaution, but processwire is not using it because there are way to many shared hosters, where it's simply not possible to go outside the webroot. I'd also say that if your webserver is not behaving correctly you've got bigger problems to deal with, so usually just adjusting your .htaccess file should be perfectly fine as well. Especially as your php process still needs to be able to read things even if they're not within the webroot to be able to execute them. There's not really a need for composer for that part as processwire has it's own psr-4 compatible classloader: https://processwire.com/api/ref/class-loader/
    5 points
  3. @LostKobrakai Thanks for the clarifications! As for the PHP read access, I'm more worried about remote code execution through undiscovered vulnerabilities in external packages (or an attacker gaining write access to a package that gets included through the dependency chain, like we've seen with the event-stream debacle recently). If a PHP file with such a vulnerability lives inside the webroot (especially if it's in a "standard" path like /vendor/vulnerable-package/...), this could give an attacker access to the entire system. Granted, direct access can be blocked in the .htaccess or something like that, but for me it's just one less thing to worry about. Though I'm admittedly a bit paranoid ? ProcessWire's classloader is certainly a good option as well, I just use the composer autoloader because I need to set up Composer anyway for most projects, I guess it comes down to preference. For a shared module or site profile I'd definitely go with the ProcessWire classloader!
    3 points
  4. CKEditor is a nasty beast when it comes to configuring it, but I will try to help ? First things first, how to configure it: https://github.com/processwire/processwire/blob/dev/wire/modules/Inputfield/InputfieldCKEditor/README.md#custom-editor-css-file You probably did this but to make things clear: the field's type is Textarea, while the inputfield's type is CKEditor. So far so good ? On the Details tab: content type is recommended to be Markup/HTML and it should be. "Markup/HTML (Content Type)" option can be configured as required, as they do not affect the CSS we are dealing with. The things in question be configured on the Input tab, under the CKEditor settings, so here come the interesting bits. Available core toolbar items are listed there, and as an example, here is what I often use: PWImage, Format, Styles, RemoveFormat, Bold, Italic, NumberedList, BulletedList, PWLink, Unlink, Table, SpecialChar, Sourcedialog Format and Styles are needed to make those dropdowns show up. If you do not have too many CKEditor fields on the edit page then I recommend setting them to "Regular Editor". We have a thread of discussing settings, BTW: https://processwire.com/talk/topic/17862-share-your-ckeditor-settings/ Turning ACF and HTML Purifier on is generally recommended, however, they might make things harder in terms of keeping those HTML bits intact when saving the page. In the case of ACF, you need to deal with "extra allowed content" so that your code actually gets saved as intended. Here are some forum topics to tackle some issues that may arise: https://processwire.com/talk/topic/19519-ckeditor-and-extra-allowed-content/ https://processwire.com/talk/topic/19918-modify-ckeditor-image-markup-via-hook/?do=findComment&amp;comment=172616 https://processwire.com/talk/topic/12773-ckeditor-does-not-reapply-styles/#entry116174 Normally I turn ACF on, but keep HTML Purifier off in some cases, as I usually use "Regular Editor" instead of "Inline" and have trusted users. However, HTML Purifier is good for making sure only valid code is saved, so it is a trade off not to turn it on. When I do use HTML Purifier, then I sometimes temporarily turn it off during development but I make sure to turn in on for the production site, even for trusted users. If you run into troubles, try turning it on and off to see what it changes in the source. Sadly, HTML Purifier is not yet configurable in ProcessWire. You can give this request a thumb's up though: https://github.com/processwire/processwire-requests/issues/226 Setting up Format Tags is self explanatory, usually I use at least the minimum of p;h2;h3;h4;h5 (h1 is always generated by the template file so no need to include it). Extra Allowed Content is very important, normally I use this: p(*)[*]{*};div(*)[*]{*};li(*)[*]{*};ul(*)[*]{*};i(*)[*]{*};tr(*)[*]{*};*[id];*(class); *[id] and *(class) are somewhat redundant as they allow any IDs and any classes while (*)[*] also allow any of those in the case of the element they are applied to. Now we are getting to the bits you are probably concerned with: Custom Editor CSS File (regular mode) - which can be used to style the HTML of content editor itself as opposed to the frontend Custom Editor JS Styles Set - this is the file you need when you want to define styes for the Style toolbar dropdown Custom Config Options - the notes of the field read: these settings can also be set in one of these files (e.g.) ...config.js and ...config-body.js and this is what I normally use. To configure these options properly this is what you need to tripple check: Make sure: you did create the directory /site/modules/InputfieldCKEditor/ and copied the file called mystyles.js from /wire/modules/Inputfield/InputfieldCKEditor/ to its counterpart: /site/modules/InputfieldCKEditor/ Make sure: files in the directory /site/modules/InputfieldCKEditor/ are named exactly as the ones configured in the options. In the case of Custom Editor JS Styles Set, make sure that in the JS file the function parameter reflects the name you defined in the admin. The default is "mystyles", defined this way: mystyles:/site/modules/InputfieldCKEditor/site_styles.js which means that in the JS file you need CKEDITOR.stylesSet.add( 'mystyles', [... but if you want to use a different string, then replace "mystyles" both in the admin's configuration filed and the accompanying JS file, something like: cke_extra:/site/modules/InputfieldCKEditor/my_extra.js and CKEDITOR.stylesSet.add( 'cke_extra', [... Regarding the configuration files themselves, here is an example for config-body.js: CKEDITOR.editorConfig = function (config) { // Define changes to default configuration here. For example: // config.uiColor = '#AADC6E'; //config.enterMode = CKEDITOR.ENTER_BR; // stops new <p> tags from being added, adds <br /> instead. config.protectedSource.push(/<i[a-z0-9\=\'\"_\- ]*><\/i>/g); // needed for empty <i> tags (icons) config.protectedSource.push(/@/g); // needed for empty <i> tags (icons) /* If this one is enabled: * config.allowedContent = true; * then it is not possible to stop adding widht and height to images */ config.disallowedContent = 'img[width,height]'; // to stop adding widht and height to images }; CKEDITOR.dtd.$removeEmpty['i'] = 0; // needed for empty <i> tags (icons) Regarding mystyles:/site/modules/InputfieldCKEditor/mystyles.js here is one approach for UIkit 3: CKEDITOR.stylesSet.add( 'cke_extra', [ { name: 'Normal Paragraph', element: 'p', attributes: {'class': 'site-paragraph'} }, { name: 'Clear runaround', element: 'p', attributes: {'class': 'uk-clearfix'} }, { name: 'Warning Paragraph', element: 'p', attributes: {'class': 'uk-alert-warning', 'data-uk-alert': ''} }, { name: 'Success Paragraph', element: 'p', attributes: {'class': 'uk-alert-success', 'data-uk-alert': ''} }, { name: '1/2 left align', element: 'img', attributes: {'class': 'align_left uk-float-left uk-width-1-2@s site-body-img'} }, { name: '1/2 right align', element: 'img', attributes: {'class': 'align_right uk-float-right uk-width-1-2@s site-body-img'} }, { name: '1/3 left align', element: 'img', attributes: {'class': 'align_left uk-float-left uk-width-1-3 site-body-img'} }, { name: '1/3 right align', element: 'img', attributes: {'class': 'align_right uk-float-right uk-width-1-3 site-body-img'} }, { name: '1/4 left align', element: 'img', attributes: {'class': 'align_left uk-float-left uk-width-1-4 site-body-img'} }, { name: '1/4 right align', element: 'img', attributes: {'class': 'align_right uk-float-right uk-width-1-4 site-body-img'} }, { name: 'center image', element: 'img', attributes: {'class': 'align_center uk-align-center site-body-img'} }, ]); This method above defines classes for the Style toolbar dropdown in a way that more than one class or attribute is applied to the selected element. For example align_left is applied because the default ProcessWire CKEditor class for left align is this (see this post). However, to make sure that in the frontend the same element is also aligned to the left, I also apply uk-float-left uk-width-1-2@s to it. This is just a dead simple approach but you can make it more sophisticated. If you want to turn CKEditor into a WYSIWYG editor then you need do some extra work, because you need to make sure your contents.css defines the classes and styles also used on the fronted. I have not ventured too far in this direction though. Normally I use UIkit 3 on the frontend and not in the admin so I simply mimic the most important subset of the frontend's styles in contents.css. I will need to improve on this practice but only after I have switched from the Reno Admin Theme to Admin Theme UIkit. I hope I cleared up a few things for you. I you want even more tips form others, I recommend using google to search like this: https://www.google.hu/search?q=CKEditor+site%3Aprocesswire.com%2Ftalk&amp;oq=CKEditor
    2 points
  5. Also, if you're going to use a separate config.php file, I think it's worth considering the $config = array() approach seen here: https://github.com/ryancramerdesign/Helloworld/blob/master/Helloworld.config.php
    2 points
  6. Your ProcessGoodNews module needs to tell PW that it is configurable by having "implements ConfigurableModule" in the class declaration.
    2 points
  7. Quoting from the blog post that @Zeka linked to: "At present, you have to tell ProcessWire you want to use the functions API by setting $config->useFunctionsAPI = true; in your /site/config.php file. Though after more testing, we may make it enabled by default in the future. If you don't have that $config property set to true, the functions are still available, but you have to prepend "wire" to them, i.e. the more verbose wirePages() rather than pages()."
    2 points
  8. @Laikmosh I'm not sure, but I think that there is no difference in performance between $pages, wire('pages) and pages(). There is also a third way to access API variables - functions API https://processwire.com/blog/posts/processwire-3.0.39-core-updates/#new-functions-api
    2 points
  9. The RC1 version for our next master release is here. This post covers all the details and information about how you can help. We also look at a a new PageAction module added to ListerPro, and a couple of other new modules currently in development: https://processwire.com/blog/posts/processwire-3.0.121-core-updates-and-more/
    1 point
  10. I can confirm this issue only affects Safari, on Chrome everything works fine
    1 point
  11. Just a note here to say that repeater support is now fixed. A big thanks to @PWaddict for help testing these changes.
    1 point
  12. What do you mean by this? Echo the value of a field or echo a field name? If the latter, spaces are not allowed in field names (neither are hyphens; only underscores). If the former, you can just use these PHP functions strtolower or mb_strtolower (for multibyte support)
    1 point
  13. I came to the same question as @adrian: The FieldtypeVerifiedURL is nice, but without any assist not quite comfy for our editors. How can a combination of FieldtypeVerifiedURL and FieldtypeAssistedURL achieved? Edit: I'll open a Thread on this in the Profields forum.
    1 point
  14. Wow, thanks @horst that's an awesome reply! Nice one ? I'm also looking for something similar for an app outside PW. I found http://image.intervention.io/ which I tried out locally. Seemed to do the job pretty well but I know next to nothing about image manipulation. Does anyone still use just plain ol' GD(2) anymore?
    1 point
  15. Which Theme/Font is That? Tired of hearing that question when you share a screenshot or a tutorial on YouTube? Your problems are over! ? Introducing "Which Theme is That" Visual Studio Code extension. This extension will show on the status bar your workspace's current theme name and font. Install Grab it here: https://marketplace.visualstudio.com/items?itemName=sjardim.whichthemeisthat How to Run Install the extension and run the Command Palette Ctrl+Shift+P or Cmd+Shift+P on Mac. Search for "Which Theme is That?" and hit Enter. Screenshot Enjoy!
    1 point
  16. I test it on a new page and getting the same problem. Having "Rename on Save" unchecked everything seems to be ok. Are you sure that it's working for you with multiple repeater items and with "Rename on Save" checked?
    1 point
  17. @Soma Yeah this is my issue with Vue.JS - I use Vue.JS often for two way data-binding which is amazing to be able to easily update content and do visual changes to the site based on those updates. For example adding something to a basket. It's much easier with Vue than jQuery or JavaScript. My issue with Vue is exactly that. You can use it just on a component basis or you can use it to render your entire UI. To me it just doesn't make sense to use it to render an entire UI with a website. A web app sure, but a website it's often overkill and introduces that exact problem. You can introduce server side rendering of Vue with Nuxt but then it just seems like another layer of 'over complication'. I personally stopped using Vue for websites unless I absolutely needed two way binding. It just didn't make sense and the extra complication of implementing it such as having to convert everything from ProcessWire into a JSON feed. EDIT: Noticed this post still gets likes, so what's changed since then? AlpineJS. AlpineJS is a solution to this exact problem, worth a look for anyone wanting to do some cool UI stuff without including all of Vue features and overhead.
    1 point
  18. All nice and I know there's ways to get around it, but the Site has no content to crawl, just empty html. And if JS is not enabled you see this: "This is your fallback content in case JavaScript fails to load."
    1 point
  19. Hi @Karl_T. The module has no ability to modify the session data. It only can modify PW pages. AFAIK session data is not stored as pages. What you can do is add a custom GraphQL mutation field for modifying your session. But that would require you to learn GraphQL and the PHP library that we use. Here is how it might look like <?php namespace ProcessWire; use Youshido\GraphQL\Type\Scalar\BooleanType; use Youshido\GraphQL\Type\Scalar\StringType; use Youshido\GraphQL\Type\Scalar\IntType; use Youshido\GraphQL\Execution\ResolveInfo; $processGraphQL = $modules->get('ProcessGraphQL'); wire()->addHookAfter('ProcessGraphQL::getMutation', function ($event) { $mutation = $event->return; $mutation->addField('modifySessionData', [ 'type' => new BooleanType(), 'args' => [ 'foo' => new StringType(), 'bar' => new IntType(), ], 'resolve' => function ($value, array $args, ResolveInfo $info) { $success = false; // modify session data here... if ($something) { $success = true; } return $success; } ]); }); echo $processGraphQL->executeGraphQL(); And then the query for this could look like this mutation { modifySessionData("foo": "boblibob", "bar": 12234) } Haven't tried it. So there might be something I'm missing. But I hope this gives you the idea of how you can achieve what you want.
    1 point
  20. Docker (http://www.docker.com) is an open platform for building, shipping and running distributed applications. Docker containers are a great way to package a complete application with its specific dependencies in a portable way so that it can easily be deployed on any compatible network or cloud infrastructure. Recently I spent a few days making my ProcessWire site run in a Docker container, and - as I could not find any good tutorial for this - it sounded like a good idea to write one. You will find on the web plenty of presentations and tutorials about Docker, so I won't start with the basic concepts, and this tuto assumes that you have a first understanding of Docker's fundamentals. What we want to do here is to migrate an existing site to a set of docker containers. Therefore, to start with, you should have: - docker installed on your computer; - the site directory of your ProcessWIre site - a backup of your site's MySQL database Let's start. Create a docker container for the site database For several reasons (insulation, security, scalability), it is preferable to host the site database in a separate docker container. 1. Set-up a SQL database with MariaDb or MySQL $ docker run --name database -e MYSQL_ROOT_PASSWORD=rootdbpassword -d mariadb Here I choose to use the MariaDB official container in its latest version, but MySQLwould be just fine as well. 2. Run a PhpMyAdmin container and create the ProcessWire database We first select an simple image with PhpMyAdmin on the Docker Hub: nazarpc/phpmyadmin and we create a docker container based on this image. This container will access the port exposed by the database container via a private networking interface. We specify this with the `--link` option. It can be run temporarily (and exited by ctrl-C): docker run --rm --link database:mysql -p 8881:80 nazarpc/phpmyadmin Or it can be run as a daemon in the background: docker run -d --name phpmyadmin --link database:mysql -p 8881:80 nazarpc/phpmyadmin From phpmyadmin (accessed from your browser at http://hostaddress:8881) you can now create your ProcessWire database, create a dedicated user for it, and import the database content from a previously saved SQL file. Note: alternatively, you can do all database operations from the command line in the database docker container created during step 1, or use another mysql user interface container if you prefer… 3. Update the database parameters in your site configuration In your site's `config.php` file, the sql server name shall be set to `mysql`: $config->dbHost = 'mysql'; Other `$config->dbXxx` settings shall match the database name, user and password of the just-created database. Create a Docker Image for Apache, PHP and the Processwire site 1. Create an image-specific directory with the following contents and `cd` to it bash-3.2$ ls -l . config .: total 16 -rw-rw-rw- 1 jean-luc staff 1163 21 aoû 12:09 Dockerfile drwxr-xr-x 17 jean-luc staff 578 17 aoû 12:48 ProcessWire drwxr-xr-x 7 jean-luc staff 238 21 aoû 12:07 config drwxr-xr-x 7 jean-luc staff 238 20 aoû 18:46 site config: total 160 -rw-rw-rw- 1 jean-luc staff 160 20 aoû 18:28 msmtprc -rw-rw-rw- 1 jean-luc staff 72518 20 aoû 18:56 php.ini where: `ProcessWire` contains the version of ProcessWire that we want to use for this site; It can be retrieved from github with a link like https://github.com/ryancramerdesign/ProcessWire/archive/{version}.zip` For example, the 2.6.13 dev version can be obtained by the link https://github.com/ryancramerdesign/ProcessWire/archive/7d37db8d6b4ca6a132e50aff496a70e48fcd2284.zip `site`: our site-specific files `Dockerfile`: the dockerfile for building the image (see below) `config`: a directory containing specific configuration files copied to the docker image (see below) 2. Set the `Dockerfile` content FROM php:5.6-apache RUN apt-get update \ && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libmcrypt-dev libpng12-dev zziplib-bin msmtp\ && a2enmod rewrite \ && a2enmod ssl \ && docker-php-ext-install mysqli pdo_mysql iconv mcrypt zip \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install gd EXPOSE 80 EXPOSE 443 # Add a specific php.ini file COPY config/php.ini /usr/local/etc/php/ # Configure the mail sent utility msmtp (http://msmtp.sourceforge.net) and make it readable only by www-data COPY config/msmtprc /usr/local/etc/php/ RUN chmod 600 /usr/local/etc/php/msmtprc \ && chown www-data:www-data /usr/local/etc/php/msmtprc # Remove all default site files in /var/www/html RUN rm -fR /var/www/html/* # Copy ProcessWire core files COPY ProcessWire/wire /var/www/html/wire COPY ProcessWire/index.php /var/www/html/index.php COPY ProcessWire/htaccess.txt /var/www/html/.htaccess # Copy site-specific files COPY site /var/www/html/site # Make www-data the owner of site-specific files RUN chown -R www-data:www-data /var/www/html/site VOLUME /var/www/html/site Based on the official image `php:5.6-apache`, it installs missing packages to the system, adds mod-rewrite and mod-ssl to Apache, plus a number of PHP modules needed by Processwire (core or modules): mysqli, pdo_mysql, iconv, mcrypt, zip, and gd. Then it copies the site files to the location expected by the Apache server. Finally it declares a Docker volume `/var/www/html/site` (i.e. the site files and assets), so that it can be shared with other containers. 3. Set the msmtp configuration We need to configure a sendmail utility, so that we can send emails from php, for example when a user registers on the website. The simplest way to do it is to rely on an external smtp server to do the actual sending. That's why we use msmtp. - define the desired smtp account in `config/msmtprc` account celedev-webmaster tls on tls_certcheck off auth on host smtp.celedev.com port 587 user webmaster@celedev.com from webmaster@celedev.com password thepasswordofwebmasteratceledevdotcom - in `config/php.ini`, configure the sendmail command so it uses msmtp: sendmail_path = /usr/bin/msmtp -C /usr/local/etc/php/msmtprc --logfile /var/log/msmtp.log -a celedev-webmaster -t 4. Build the Docker image docker build -t php-5.6-pw-celedev . 5. Create a Data-only container for the site files docker run --name celedev-data php-5.6-pw-celedev echo "Celedev site data-only container" 6. Run the web server container docker run --name celedev-site -p 8088:80 --link database:mysql --volumes-from celedev-data -d php-5.6-pw-celedev Note that this container is linked to our database and shares the 'celedev-data' volume created previously During development, it can be convenient to keep an access to the host file system from the container. For this, we can add a shared volume to the previous command: docker run --name celedev-site -p 8088:80 --link database:mysql -v /Users/jean-luc/web/test-docker:/hostdir --volumes-from celedev-data -d php-5.6-pw-celedev Our ProcessWire website is now up and running and we can test it in our browser at http://hostaddress:8088. Great! What we now have in Docker bash-3.2$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE php-5.6-pw-celedev latest 2aaeb241c2e2 3 hours ago 1.149 GB nazarpc/phpmyadmin latest e25cd4fd48b3 8 days ago 521 MB mariadb latest dd208bafcc33 2 weeks ago 302.2 MB debian latest 9a61b6b1315e 5 weeks ago 125.2 MB bash-3.2$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 68cc5d976f0d php-5.6-pw-celedev "apache2-foreground" 20 hours ago Up 20 hours 443/tcp, 0.0.0.0:8088->80/tcp celedev-site 0729fe6d6752 php-5.6-pw-celedev "echo 'Celedev site d" 20 hours ago Exited (0) 20 hours ago celedev-data e3e9e3a4715c mariadb "/docker-entrypoint.s" 3 days ago Up 3 days 3306/tcp database Saving the site data We can create an archive of the site files by running a tar command in a dedicated container: bash-3.2$ docker run --rm -it --volumes-from celedev-data -v /Users/jean-luc/web/test-docker:/hostdir debian /bin/bash root@2973c5af3eaf:/# cd /var/www/html/ root@2973c5af3eaf:/var/www/html# tar cvf /hostdir/backup.tar site root@2973c5af3eaf:exit bash-3.2$ Tagging and archiving the Docker image We can also add a tag to the docker image that we have created in step 4 (recommended): bash-3.2$ docker tag 2aaeb241c2e2 php-5.6-pw-celedev:0.11 bash-3.2$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE php-5.6-pw-celedev latest 2aaeb241c2e2 3 hours ago 1.149 GB php-5.6-pw-celedev 0.11 2aaeb241c2e2 3 hours ago 1.149 GB nazarpc/phpmyadmin latest e25cd4fd48b3 8 days ago 521 MB mariadb latest dd208bafcc33 2 weeks ago 302.2 MB And we can archive this image locally if we dont want to push it now to the Docker Hub: bash-3.2$ docker save php-5.6-pw-celedev:0.11 | gzip > php-5.6-pw-celedev-0.11.tar.gz And that's it! You now have a portable image of your ProcessWire website that you can run directly on any docker-compatible system.
    1 point
  21. Done! The latest version now allows you to hook into getQuery & getMutation methods of the ProcessGraphQL class. Those hooks are solely there so you could modify the query and mutation operations. Here how it might look like in your template file. <?php namespace ProcessWire; use Youshido\GraphQL\Type\Scalar\StringType; $processGraphQL = $modules->get('ProcessGraphQL'); wire()->addHookAfter('ProcessGraphQL::getQuery', function ($event) { $query = $event->return; $query->addField('hello', [ 'type' => new StringType(), 'resolve' => function () { return 'world!'; } ]); }); echo $processGraphQL->executeGraphQL(); The above code will add a hello field into your GraphQL query that responds with the string "world!". You'll have to use the Youshido\GraphQL library that ProcessGraphQL module uses internally. The same thing could be done with the mutation operation via getMutation hook method.
    1 point
×
×
  • Create New...